breez_sdk_spark/signer/
external.rs

1use crate::error::SignerError;
2
3use super::external_types::{
4    EcdsaSignatureBytes, ExternalAggregateFrostRequest, ExternalEncryptedPrivateKey,
5    ExternalFrostCommitments, ExternalFrostSignature, ExternalFrostSignatureShare,
6    ExternalPrivateKeySource, ExternalSecretToSplit, ExternalSignFrostRequest, ExternalTreeNodeId,
7    ExternalVerifiableSecretShare, PrivateKeyBytes, PublicKeyBytes, RecoverableEcdsaSignatureBytes,
8    SchnorrSignatureBytes,
9};
10
11/// External signer trait that can be implemented by users and passed to the SDK.
12///
13/// This trait mirrors the `BreezSigner` trait but uses FFI-compatible types (bytes, strings)
14/// instead of Rust-specific types. This allows it to be exposed through FFI and WASM bindings.
15///
16/// All methods accept and return simple types:
17/// - Derivation paths as strings (e.g., "m/44'/0'/0'")
18/// - Public keys, signatures, and other crypto primitives as Vec<u8>
19/// - Spark-specific types as serialized representations
20///
21/// Errors are returned as `SignerError` for FFI compatibility.
22#[cfg_attr(feature = "uniffi", uniffi::export(with_foreign))]
23#[macros::async_trait]
24pub trait ExternalSigner: Send + Sync {
25    /// Returns the identity public key as 33 bytes (compressed secp256k1 key).
26    fn identity_public_key(&self) -> Result<PublicKeyBytes, SignerError>;
27
28    /// Derives a public key for the given BIP32 derivation path.
29    ///
30    /// # Arguments
31    /// * `path` - BIP32 derivation path as a string (e.g., "m/44'/0'/0'/0/0")
32    ///
33    /// # Returns
34    /// The derived public key as 33 bytes, or a `SignerError`
35    async fn derive_public_key(&self, path: String) -> Result<PublicKeyBytes, SignerError>;
36
37    /// Signs a message using ECDSA at the given derivation path.
38    ///
39    /// # Arguments
40    /// * `message` - The message to sign
41    /// * `path` - BIP32 derivation path as a string
42    ///
43    /// # Returns
44    /// 64-byte compact ECDSA signature, or a `SignerError`
45    async fn sign_ecdsa(
46        &self,
47        message: Vec<u8>,
48        path: String,
49    ) -> Result<EcdsaSignatureBytes, SignerError>;
50
51    /// Signs a message using recoverable ECDSA at the given derivation path.
52    ///
53    /// # Arguments
54    /// * `message` - The message to sign (will be double-SHA256 hashed)
55    /// * `path` - BIP32 derivation path as a string
56    ///
57    /// # Returns
58    /// 65 bytes: recovery ID (31 + `recovery_id`) + 64-byte signature, or a `SignerError`
59    async fn sign_ecdsa_recoverable(
60        &self,
61        message: Vec<u8>,
62        path: String,
63    ) -> Result<RecoverableEcdsaSignatureBytes, SignerError>;
64
65    /// Encrypts a message using ECIES at the given derivation path.
66    ///
67    /// # Arguments
68    /// * `message` - The message to encrypt
69    /// * `path` - BIP32 derivation path for the encryption key
70    ///
71    /// # Returns
72    /// Encrypted data, or a `SignerError`
73    async fn ecies_encrypt(&self, message: Vec<u8>, path: String) -> Result<Vec<u8>, SignerError>;
74
75    /// Decrypts a message using ECIES at the given derivation path.
76    ///
77    /// # Arguments
78    /// * `message` - The encrypted message
79    /// * `path` - BIP32 derivation path for the decryption key
80    ///
81    /// # Returns
82    /// Decrypted data, or a `SignerError`
83    async fn ecies_decrypt(&self, message: Vec<u8>, path: String) -> Result<Vec<u8>, SignerError>;
84
85    /// Signs a hash using Schnorr signature at the given derivation path.
86    ///
87    /// # Arguments
88    /// * `hash` - The 32-byte hash to sign (must be 32 bytes)
89    /// * `path` - BIP32 derivation path as a string
90    ///
91    /// # Returns
92    /// 64-byte Schnorr signature, or a `SignerError`
93    async fn sign_hash_schnorr(
94        &self,
95        hash: Vec<u8>,
96        path: String,
97    ) -> Result<SchnorrSignatureBytes, SignerError>;
98
99    /// Generates Frost signing commitments for multi-party signing.
100    ///
101    /// # Returns
102    /// Frost commitments with nonces, or a `SignerError`
103    async fn generate_frost_signing_commitments(
104        &self,
105    ) -> Result<ExternalFrostCommitments, SignerError>;
106
107    /// Gets the public key for a specific tree node in the Spark wallet.
108    ///
109    /// # Arguments
110    /// * `id` - The tree node identifier
111    ///
112    /// # Returns
113    /// The public key for the node, or an error string
114    async fn get_public_key_for_node(
115        &self,
116        id: ExternalTreeNodeId,
117    ) -> Result<PublicKeyBytes, SignerError>;
118
119    /// Generates a random private key.
120    ///
121    /// # Returns
122    /// A randomly generated private key source, or an error string
123    async fn generate_random_key(&self) -> Result<ExternalPrivateKeySource, SignerError>;
124
125    /// Gets a static deposit private key source by index.
126    ///
127    /// # Arguments
128    /// * `index` - The index of the static deposit key
129    ///
130    /// # Returns
131    /// The private key source, or an error string
132    async fn get_static_deposit_private_key_source(
133        &self,
134        index: u32,
135    ) -> Result<ExternalPrivateKeySource, SignerError>;
136
137    /// Gets a static deposit private key by index.
138    ///
139    /// # Arguments
140    /// * `index` - The index of the static deposit key
141    ///
142    /// # Returns
143    /// The 32-byte private key, or an error string
144    async fn get_static_deposit_private_key(
145        &self,
146        index: u32,
147    ) -> Result<PrivateKeyBytes, SignerError>;
148
149    /// Gets a static deposit public key by index.
150    ///
151    /// # Arguments
152    /// * `index` - The index of the static deposit key
153    ///
154    /// # Returns
155    /// The 33-byte public key, or an error string
156    async fn get_static_deposit_public_key(
157        &self,
158        index: u32,
159    ) -> Result<PublicKeyBytes, SignerError>;
160
161    /// Subtracts one private key from another.
162    ///
163    /// # Arguments
164    /// * `signing_key` - The first private key source
165    /// * `new_signing_key` - The second private key source to subtract
166    ///
167    /// # Returns
168    /// The resulting private key source, or an error string
169    async fn subtract_private_keys(
170        &self,
171        signing_key: ExternalPrivateKeySource,
172        new_signing_key: ExternalPrivateKeySource,
173    ) -> Result<ExternalPrivateKeySource, SignerError>;
174
175    /// Splits a secret with proofs using Shamir's Secret Sharing.
176    ///
177    /// # Arguments
178    /// * `secret` - The secret to split
179    /// * `threshold` - Minimum number of shares needed to reconstruct
180    /// * `num_shares` - Total number of shares to create
181    ///
182    /// # Returns
183    /// Vector of verifiable secret shares, or an error string
184    async fn split_secret(
185        &self,
186        secret: ExternalSecretToSplit,
187        threshold: u32,
188        num_shares: u32,
189    ) -> Result<Vec<ExternalVerifiableSecretShare>, SignerError>;
190
191    /// Encrypts a private key for a specific receiver's public key.
192    ///
193    /// # Arguments
194    /// * `private_key` - The encrypted private key to re-encrypt
195    /// * `receiver_public_key` - The receiver's 33-byte public key
196    ///
197    /// # Returns
198    /// Encrypted data for the receiver, or an error string
199    async fn encrypt_private_key_for_receiver(
200        &self,
201        private_key: ExternalEncryptedPrivateKey,
202        receiver_public_key: PublicKeyBytes,
203    ) -> Result<Vec<u8>, SignerError>;
204
205    /// Gets the public key from a private key source.
206    ///
207    /// # Arguments
208    /// * `private_key` - The private key source
209    ///
210    /// # Returns
211    /// The corresponding 33-byte public key, or an error string
212    async fn get_public_key_from_private_key_source(
213        &self,
214        private_key: ExternalPrivateKeySource,
215    ) -> Result<PublicKeyBytes, SignerError>;
216
217    /// Signs using Frost protocol (multi-party signing).
218    ///
219    /// # Arguments
220    /// * `request` - The Frost signing request
221    ///
222    /// # Returns
223    /// A signature share, or an error string
224    async fn sign_frost(
225        &self,
226        request: ExternalSignFrostRequest,
227    ) -> Result<ExternalFrostSignatureShare, SignerError>;
228
229    /// Aggregates Frost signature shares into a final signature.
230    ///
231    /// # Arguments
232    /// * `request` - The Frost aggregation request
233    ///
234    /// # Returns
235    /// The aggregated Frost signature, or an error string
236    async fn aggregate_frost_signatures(
237        &self,
238        request: ExternalAggregateFrostRequest,
239    ) -> Result<ExternalFrostSignature, SignerError>;
240}