spark_rust/signer/traits/frost_signing.rs
1//! # FROST threshold signing operations for Spark wallet
2//!
3//! This module defines the FROST (Flexible Round-Optimized Schnorr Threshold) signing
4//! capabilities for the Spark wallet. FROST is the threshold signature scheme used by
5//! Spark to enable secure multi-party signing, where both the user and Spark Operators
6//! participate in creating signatures without revealing their private keys.
7//!
8//! The module supports:
9//! - Creating and verifying FROST signature shares
10//! - Aggregating signature shares into complete signatures
11//! - Specialized signing methods for various Spark operations
12//!
13//! In Spark's security model, threshold signing is critical because it ensures that:
14//! 1. Neither the user nor Spark Operators alone can spend funds
15//! 2. Signatures appear as standard Schnorr signatures on-chain
16//! 3. The user maintains control of their portion of the signing key
17//!
18//! This implementation is customized to support Taproot tweaking, enabling
19//! compatibility with Bitcoin's Taproot script system.
20
21// use std::cell::RefCell;
22use std::collections::HashMap;
23use std::sync::Arc;
24
25use bitcoin::secp256k1::PublicKey;
26use frost_secp256k1_tr_unofficial::round1::SigningCommitments;
27use parking_lot::RwLock;
28use spark_protos::common::SigningCommitment;
29use spark_protos::frost::AggregateFrostRequest;
30use spark_protos::frost::AggregateFrostResponse;
31use spark_protos::frost::FrostSigningJob;
32use spark_protos::frost::SignFrostResponse;
33use spark_protos::spark::LeafRefundTxSigningResult;
34use spark_protos::spark::NodeSignatures;
35use spark_protos::spark::RequestedSigningCommitments;
36
37use crate::error::SparkSdkError;
38use crate::wallet::internal_handlers::traits::create_tree::DepositAddressTree;
39use crate::wallet::internal_handlers::traits::transfer::LeafKeyTweak;
40use crate::wallet::internal_handlers::traits::transfer::LeafRefundSigningData;
41
42/// Trait for FROST threshold signing operations in the Spark wallet.
43///
44/// This trait provides methods for performing threshold signing using the FROST
45/// (Flexible Round-Optimized Schnorr Threshold) protocol. FROST enables multiple
46/// parties (the user and Spark Operators) to jointly sign a message without revealing
47/// their private keys.
48///
49/// In the Spark protocol, FROST signing is used for:
50/// - Signing Bitcoin transactions on leaves (UTXOs)
51/// - Creating refund transactions for security guarantees
52/// - Facilitating Lightning Network operations
53/// - Supporting deposit address creation
54///
55/// The implementation is customized to support Taproot tweaking, allowing
56/// compatibility with Bitcoin's Taproot script system while maintaining the
57/// security properties of threshold signatures.
58pub trait SparkSignerFrostSigning {
59 /// Signs messages using the FROST threshold signature scheme.
60 ///
61 /// This method generates signature shares for a set of signing jobs.
62 /// Each job represents a distinct message to be signed with a specific
63 /// key and set of participants.
64 ///
65 /// # Arguments
66 /// * `signing_jobs` - A vector of `FrostSigningJob` objects, each containing:
67 /// - The message to sign
68 /// - The key package (containing signing material)
69 /// - The verifying key
70 /// - Nonce commitments from all participants
71 /// - Optional adaptor public key for adaptor signatures
72 ///
73 /// # Returns
74 /// * `Ok(SignFrostResponse)` - Contains the generated signature shares for each job
75 /// * `Err(SparkSdkError)` - If signing fails for any reason
76 ///
77 /// # Security Considerations
78 /// The security of FROST depends on proper nonce generation. The implementation
79 /// should ensure nonces are never reused for different messages.
80 fn sign_frost(
81 &self,
82 signing_jobs: Vec<FrostSigningJob>,
83 ) -> Result<SignFrostResponse, SparkSdkError>;
84
85 /// Aggregates multiple FROST signature shares into a complete signature.
86 ///
87 /// This method combines signature shares from all participants (the user and
88 /// Spark Operators) into a single signature that can be verified using the
89 /// threshold public key.
90 ///
91 /// # Arguments
92 /// * `request` - An `AggregateFrostRequest` containing:
93 /// - The message that was signed
94 /// - Signature shares from all participants
95 /// - Public key shares from all participants
96 /// - The verifying key (threshold public key)
97 /// - Nonce commitments from all participants
98 /// - Optional adaptor public key for adaptor signatures
99 ///
100 /// # Returns
101 /// * `Ok(AggregateFrostResponse)` - Contains the aggregated signature
102 /// * `Err(SparkSdkError)` - If aggregation fails
103 ///
104 /// # Security Considerations
105 /// The aggregation process must verify that all signature shares are valid
106 /// before combining them to prevent rogue key attacks.
107 fn aggregate_frost(
108 &self,
109 request: AggregateFrostRequest,
110 ) -> Result<AggregateFrostResponse, SparkSdkError>;
111
112 /// Signs all nodes in a deposit tree in breadth-first order.
113 ///
114 /// This method traverses a deposit tree structure and signs each node's transaction
115 /// and refund transaction using FROST. The tree represents a hierarchical structure
116 /// of UTXOs created during the deposit process.
117 ///
118 /// # Arguments
119 /// * `tx` - The parent transaction for the tree
120 /// * `vout` - The output index in the parent transaction
121 /// * `internal_tree_root` - The root of the internal tree structure
122 /// * `request_tree_root` - The tree creation request data
123 /// * `creation_result_tree_root` - The tree creation response data containing operator signatures
124 ///
125 /// # Returns
126 /// * `Ok((Vec<NodeSignatures>, Vec<Vec<u8>>))` - Contains:
127 /// - Signatures for each node in the tree
128 /// - The signing public keys used
129 /// * `Err(SparkSdkError)` - If signing fails for any node
130 fn sign_created_tree_in_bfs_order(
131 &self,
132 tx: bitcoin::Transaction,
133 vout: u32,
134 internal_tree_root: Arc<RwLock<DepositAddressTree>>,
135 request_tree_root: spark_protos::spark::CreationNode,
136 creation_result_tree_root: spark_protos::spark::CreationResponseNode,
137 ) -> Result<(Vec<NodeSignatures>, Vec<Vec<u8>>), SparkSdkError>;
138
139 /// Signs refund transactions for transfer leaves.
140 ///
141 /// This method signs refund transactions that provide security guarantees
142 /// during transfers. Refund transactions allow the user to recover funds
143 /// in case the transfer process is interrupted.
144 ///
145 /// # Arguments
146 /// * `leaf_data_map` - A map of leaf IDs to their refund signing data
147 /// * `operator_signing_results` - Signature shares from Spark Operators
148 /// * `adaptor_public_key` - Public key used for adaptor signatures
149 ///
150 /// # Returns
151 /// * `Ok(Vec<NodeSignatures>)` - Signatures for each refund transaction
152 /// * `Err(SparkSdkError)` - If signing fails for any refund transaction
153 fn sign_transfer_refunds(
154 &self,
155 leaf_data_map: &HashMap<String, LeafRefundSigningData>,
156 operator_signing_results: &Vec<LeafRefundTxSigningResult>,
157 adaptor_public_key: Vec<u8>,
158 ) -> Result<Vec<NodeSignatures>, SparkSdkError>;
159
160 /// Signs transactions for a Lightning swap operation.
161 ///
162 /// This method generates signatures for transactions involved in a Lightning
163 /// payment, where the user's leaves are swapped with the SSP in exchange for
164 /// the Lightning payment execution.
165 ///
166 /// # Arguments
167 /// * `leaves` - The leaves involved in the swap
168 /// * `signing_commitments` - Nonce commitments for signing
169 /// * `receiver_identity_pubkey` - The identity public key of the receiver
170 ///
171 /// # Returns
172 /// * `Ok((SignFrostResponse, Vec<Vec<u8>>, Vec<SigningCommitment>))` - Contains:
173 /// - The signature shares
174 /// - The refund transaction data
175 /// - The user's signing commitments
176 /// * `Err(SparkSdkError)` - If signing fails
177 #[allow(clippy::type_complexity)]
178 fn sign_for_lightning_swap(
179 &self,
180 leaves: &Vec<LeafKeyTweak>,
181 signing_commitments: &Vec<RequestedSigningCommitments>,
182 receiver_identity_pubkey: PublicKey,
183 ) -> Result<(SignFrostResponse, Vec<Vec<u8>>, Vec<SigningCommitment>), SparkSdkError>;
184
185 /// Signs root node and refund transactions during tree creation.
186 ///
187 /// This method signs the root node transaction and its corresponding refund
188 /// transaction during the deposit tree creation process.
189 ///
190 /// # Arguments
191 /// * `signing_pubkey_bytes` - The signing public key as bytes
192 /// * `verifying_pubkey_bytes` - The verifying public key as bytes
193 /// * `root_tx_bytes` - The root transaction bytes
194 /// * `refund_tx_bytes` - The refund transaction bytes
195 /// * `root_tx_sighash` - The sighash of the root transaction
196 /// * `refund_tx_sighash` - The sighash of the refund transaction
197 /// * `root_nonce_commitment` - Nonce commitment for the root transaction
198 /// * `refund_nonce_commitment` - Nonce commitment for the refund transaction
199 /// * `tree_creation_response` - Response from Spark Operators with their signature shares
200 ///
201 /// # Returns
202 /// * `Ok(Vec<Vec<u8>>)` - Signatures for the root and refund transactions
203 /// * `Err(SparkSdkError)` - If signing fails
204 fn sign_root_creation(
205 &self,
206 signing_pubkey_bytes: Vec<u8>,
207 verifying_pubkey_bytes: Vec<u8>,
208 root_tx_bytes: Vec<u8>,
209 refund_tx_bytes: Vec<u8>,
210 root_tx_sighash: Vec<u8>,
211 refund_tx_sighash: Vec<u8>,
212 root_nonce_commitment: SigningCommitments,
213 refund_nonce_commitment: SigningCommitments,
214 tree_creation_response: spark_protos::spark::StartTreeCreationResponse,
215 ) -> Result<Vec<Vec<u8>>, SparkSdkError>;
216
217 /// Signs a message using the new FROST signing flow.
218 ///
219 /// This is an improved signing method that provides a more streamlined
220 /// interface for FROST signing operations.
221 ///
222 /// # Arguments
223 /// * `message` - The message to sign
224 /// * `private_as_pubkey` - The private key represented as a public key (for lookup)
225 /// * `verifying_key` - The verifying key for signature verification
226 /// * `self_commitment` - The user's nonce commitment
227 /// * `spark_commitments` - Nonce commitments from Spark Operators
228 /// * `adaptor_public_key` - Optional adaptor public key for adaptor signatures
229 ///
230 /// # Returns
231 /// * `Ok(Vec<u8>)` - The signature share
232 /// * `Err(SparkSdkError)` - If signing fails
233 fn sign_frost_new(
234 &self,
235 message: Vec<u8>,
236 private_as_pubkey: Vec<u8>,
237 verifying_key: Vec<u8>,
238 self_commitment: SigningCommitments,
239 spark_commitments: HashMap<String, SigningCommitment>,
240 adaptor_public_key: Option<Vec<u8>>,
241 ) -> Result<Vec<u8>, SparkSdkError>;
242}