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)),
                }
            }
        }
    }
}