clementine_core/builder/transaction/deposit_signature_owner.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
//! # Deposit Signature Ownership Mapping
//!
//! This module provides types and logic for mapping transaction signature requirements to protocol entities in the Clementine bridge.
//! It is used to determine which entity (operator, verifier, N-of-N, etc.) is responsible for providing a signature for a given transaction input,
//! and what sighash type is required for that signature. Additionally it encodes when this signature is given to other entities.
//!
use crate::errors::BridgeError;
use crate::rpc::clementine::tagged_signature::SignatureId;
use crate::rpc::clementine::{NormalSignatureKind, NumberedSignatureKind};
use bitcoin::TapSighashType;
use eyre::Context;
/// Enumerates the protocol entities that may own a required signature for a transaction input.
/// Additionally it encodes when this signature is given to other entities. For example signatures with OperatorDeposit are operator's
/// signatures that are shared with verifiers during a new deposit, while OperatorSetup is operator's signature that is given to the
/// verifiers when Operator is being newly setup and added to verifiers databases.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EntityType {
OperatorDeposit,
Watchtower,
VerifierDeposit,
OperatorSetup,
}
/// Describes the ownership and sighash type for a required signature.
///
/// - `NotOwned`: No signature required or not owned by any protocol entity.
/// - `OperatorSharedDeposit`: Operator's signature required for deposit, with the given sighash type.
/// - `NofnSharedDeposit`: N-of-N signature required for deposit, with the given sighash type.
/// - `Own`: Signature required for the entity running the program, with the given sighash type.
/// - `OperatorSharedSetup`: Operator's signature required during aggregator setup, with the given sighash type.
#[derive(Debug, Clone, Copy)]
pub enum DepositSigKeyOwner {
NotOwned,
/// Operator's signature required for deposit (shared with verifiers), with the given sighash type.
OperatorSharedDeposit(TapSighashType),
/// N-of-N signature required for deposit, with the given sighash type.
NofnSharedDeposit(TapSighashType),
/// Signature required for the entity itself, with the given sighash type.
/// Verifiers do not need this signature info, thus it is not saved to DB.
/// Added to help define different sighash types for operator's own signatures.
Own(TapSighashType),
/// Operator's signature required during first setup, with the given sighash type.
OperatorSharedSetup(TapSighashType),
}
impl DepositSigKeyOwner {
/// Returns the sighash type for this signature owner, if any.
pub fn sighash_type(&self) -> Option<TapSighashType> {
match self {
DepositSigKeyOwner::NotOwned => None,
DepositSigKeyOwner::Own(t)
| DepositSigKeyOwner::NofnSharedDeposit(t)
| DepositSigKeyOwner::OperatorSharedDeposit(t)
| DepositSigKeyOwner::OperatorSharedSetup(t) => Some(*t),
}
}
}
impl SignatureId {
/// Maps a [`SignatureId`] to its required signature owner and sighash type.
///
/// # Returns
///
/// A [`DepositSigKeyOwner`] describing the required signature owner and sighash type for this signature ID, or a [`BridgeError`] if the mapping fails.
pub fn get_deposit_sig_owner(&self) -> Result<DepositSigKeyOwner, BridgeError> {
use DepositSigKeyOwner::*;
use TapSighashType::{
Default as SighashDefault, None as SighashNone, SinglePlusAnyoneCanPay,
};
match *self {
SignatureId::NormalSignature(normal_sig) => {
let normal_sig_type = NormalSignatureKind::try_from(normal_sig.signature_kind)
.wrap_err("Couldn't convert SignatureId::NormalSignature to DepositSigKey")?;
use NormalSignatureKind::*;
match normal_sig_type {
OperatorSighashDefault => Ok(Own(SighashDefault)),
NormalSignatureUnknown => Ok(NotOwned),
Challenge => Ok(OperatorSharedDeposit(SinglePlusAnyoneCanPay)),
DisproveTimeout2 => Ok(NofnSharedDeposit(SighashDefault)),
Disprove2 => Ok(OperatorSharedDeposit(SighashNone)),
Reimburse1 => Ok(NofnSharedDeposit(SighashDefault)),
KickoffNotFinalized1 => Ok(NofnSharedDeposit(SighashDefault)),
KickoffNotFinalized2 => Ok(OperatorSharedDeposit(SighashDefault)),
Reimburse2 => Ok(NofnSharedDeposit(SighashDefault)),
NoSignature => Ok(NotOwned),
ChallengeTimeout2 => Ok(NofnSharedDeposit(SighashDefault)),
MiniAssert1 => Ok(Own(SighashDefault)),
OperatorChallengeAck1 => Ok(Own(SighashDefault)),
NotStored => Ok(NotOwned),
YieldKickoffTxid => Ok(NotOwned),
LatestBlockhashTimeout1 => Ok(NofnSharedDeposit(SighashDefault)),
LatestBlockhashTimeout2 => Ok(NofnSharedDeposit(SighashDefault)),
LatestBlockhashTimeout3 => Ok(OperatorSharedDeposit(SighashDefault)),
LatestBlockhash => Ok(Own(SighashDefault)),
}
}
SignatureId::NumberedSignature(numbered_sig) => {
let numbered_sig_type = NumberedSignatureKind::try_from(
numbered_sig.signature_kind,
)
.wrap_err("Couldn't convert SignatureId::NumberedSignature to DepositSigKey")?;
use NumberedSignatureKind::*;
match numbered_sig_type {
OperatorChallengeNack1 => Ok(NofnSharedDeposit(SighashDefault)),
OperatorChallengeNack2 => Ok(NofnSharedDeposit(SighashDefault)),
NumberedSignatureUnknown => Ok(NotOwned),
NumberedNotStored => Ok(Own(SighashDefault)),
OperatorChallengeNack3 => Ok(OperatorSharedDeposit(SighashDefault)),
AssertTimeout1 => Ok(NofnSharedDeposit(SighashDefault)),
AssertTimeout2 => Ok(NofnSharedDeposit(SighashDefault)),
AssertTimeout3 => Ok(OperatorSharedDeposit(SighashDefault)),
UnspentKickoff1 => Ok(OperatorSharedSetup(SighashDefault)),
UnspentKickoff2 => Ok(OperatorSharedSetup(SighashDefault)),
WatchtowerChallengeTimeout1 => Ok(NofnSharedDeposit(SighashDefault)),
WatchtowerChallengeTimeout2 => Ok(NofnSharedDeposit(SighashDefault)),
WatchtowerChallenge => Ok(Own(SighashDefault)),
}
}
}
}
}