1use crate::{Seed, error::SdkError, models::Config};
2use bitcoin::bip32::DerivationPath;
3use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine, sha256};
4use bitcoin::secp256k1::{self, Message, Secp256k1, rand::thread_rng};
5use spark_wallet::{DefaultSigner, KeySet, KeySetType, Signer};
6
7use super::BreezSigner;
8
9pub struct BreezSignerImpl {
10 key_set: KeySet,
11 secp: Secp256k1<secp256k1::All>,
12 spark_signer: DefaultSigner,
13}
14
15impl BreezSignerImpl {
16 pub fn new(
17 config: &Config,
18 seed: &Seed,
19 key_set_type: KeySetType,
20 use_address_index: bool,
21 account_number: Option<u32>,
22 ) -> Result<Self, SdkError> {
23 let seed_bytes = seed.to_bytes()?;
24 let key_set = KeySet::new(
25 &seed_bytes,
26 config.network.into(),
27 key_set_type,
28 use_address_index,
29 account_number,
30 )
31 .map_err(|e| SdkError::Generic(e.to_string()))?;
32
33 Ok(Self {
34 key_set: key_set.clone(),
35 secp: Secp256k1::new(),
36 spark_signer: DefaultSigner::from_key_set(key_set),
37 })
38 }
39}
40
41#[macros::async_trait]
42impl BreezSigner for BreezSignerImpl {
43 fn identity_public_key(&self) -> Result<secp256k1::PublicKey, SdkError> {
44 Ok(self.key_set.identity_key_pair.public_key())
45 }
46
47 async fn derive_public_key(
48 &self,
49 path: &DerivationPath,
50 ) -> Result<secp256k1::PublicKey, SdkError> {
51 let derived = self
52 .key_set
53 .identity_master_key
54 .derive_priv(&self.secp, path)
55 .map_err(|e| SdkError::Generic(e.to_string()))?;
56 Ok(derived.private_key.public_key(&self.secp))
57 }
58
59 async fn sign_ecdsa(
60 &self,
61 message: Message,
62 path: &DerivationPath,
63 ) -> Result<secp256k1::ecdsa::Signature, SdkError> {
64 let derived = self
65 .key_set
66 .identity_master_key
67 .derive_priv(&self.secp, path)
68 .map_err(|e| SdkError::Generic(e.to_string()))?;
69 Ok(self.secp.sign_ecdsa_low_r(&message, &derived.private_key))
70 }
71
72 async fn sign_ecdsa_recoverable(
73 &self,
74 message: Message,
75 path: &DerivationPath,
76 ) -> Result<secp256k1::ecdsa::RecoverableSignature, SdkError> {
77 let derived = self
78 .key_set
79 .identity_master_key
80 .derive_priv(&self.secp, path)
81 .map_err(|e| SdkError::Generic(e.to_string()))?;
82 Ok(self
83 .secp
84 .sign_ecdsa_recoverable(&message, &derived.private_key))
85 }
86
87 async fn encrypt_ecies(
88 &self,
89 message: &[u8],
90 path: &DerivationPath,
91 ) -> Result<Vec<u8>, SdkError> {
92 let derived = self
93 .key_set
94 .identity_master_key
95 .derive_priv(&self.secp, path)
96 .map_err(|e| SdkError::Generic(e.to_string()))?;
97 let rc_pub = derived.private_key.public_key(&self.secp).serialize();
98 ecies::encrypt(&rc_pub, message)
99 .map_err(|err| SdkError::Generic(format!("Could not encrypt data: {err}")))
100 }
101
102 async fn decrypt_ecies(
103 &self,
104 message: &[u8],
105 path: &DerivationPath,
106 ) -> Result<Vec<u8>, SdkError> {
107 let derived = self
108 .key_set
109 .identity_master_key
110 .derive_priv(&self.secp, path)
111 .map_err(|e| SdkError::Generic(e.to_string()))?;
112 let rc_prv = derived.private_key.secret_bytes();
113 ecies::decrypt(&rc_prv, message)
114 .map_err(|err| SdkError::Generic(format!("Could not decrypt data: {err}")))
115 }
116
117 async fn sign_hash_schnorr(
118 &self,
119 hash: &[u8],
120 path: &DerivationPath,
121 ) -> Result<secp256k1::schnorr::Signature, SdkError> {
122 let derived = self
123 .key_set
124 .identity_master_key
125 .derive_priv(&self.secp, path)
126 .map_err(|e| SdkError::Generic(e.to_string()))?;
127 let message =
128 Message::from_digest_slice(hash).map_err(|e| SdkError::Generic(e.to_string()))?;
129 let keypair = derived.private_key.keypair(&self.secp);
130
131 let mut rng = thread_rng();
133 Ok(self
134 .secp
135 .sign_schnorr_with_rng(&message, &keypair, &mut rng))
136 }
137
138 async fn generate_random_signing_commitment(
139 &self,
140 ) -> Result<spark_wallet::FrostSigningCommitmentsWithNonces, SdkError> {
141 self.spark_signer
142 .generate_random_signing_commitment()
143 .await
144 .map_err(|e| SdkError::Generic(e.to_string()))
145 }
146
147 async fn get_public_key_for_node(
148 &self,
149 id: &spark_wallet::TreeNodeId,
150 ) -> Result<secp256k1::PublicKey, SdkError> {
151 self.spark_signer
152 .get_public_key_for_node(id)
153 .await
154 .map_err(|e| SdkError::Generic(e.to_string()))
155 }
156
157 async fn generate_random_secret(&self) -> Result<spark_wallet::EncryptedSecret, SdkError> {
158 self.spark_signer
159 .generate_random_secret()
160 .await
161 .map_err(|e| SdkError::Generic(e.to_string()))
162 }
163
164 async fn static_deposit_secret_encrypted(
165 &self,
166 index: u32,
167 ) -> Result<spark_wallet::SecretSource, SdkError> {
168 self.spark_signer
169 .static_deposit_secret_encrypted(index)
170 .await
171 .map_err(|e| SdkError::Generic(e.to_string()))
172 }
173
174 async fn static_deposit_secret(&self, index: u32) -> Result<secp256k1::SecretKey, SdkError> {
175 self.spark_signer
176 .static_deposit_secret(index)
177 .await
178 .map_err(|e| SdkError::Generic(e.to_string()))
179 }
180
181 async fn static_deposit_signing_key(
182 &self,
183 index: u32,
184 ) -> Result<secp256k1::PublicKey, SdkError> {
185 self.spark_signer
186 .static_deposit_signing_key(index)
187 .await
188 .map_err(|e| SdkError::Generic(e.to_string()))
189 }
190
191 async fn subtract_secrets(
192 &self,
193 signing_key: &spark_wallet::SecretSource,
194 new_signing_key: &spark_wallet::SecretSource,
195 ) -> Result<spark_wallet::SecretSource, SdkError> {
196 self.spark_signer
197 .subtract_secrets(signing_key, new_signing_key)
198 .await
199 .map_err(|e| SdkError::Generic(e.to_string()))
200 }
201
202 async fn split_secret_with_proofs(
203 &self,
204 secret: &spark_wallet::SecretToSplit,
205 threshold: u32,
206 num_shares: usize,
207 ) -> Result<Vec<spark_wallet::VerifiableSecretShare>, SdkError> {
208 self.spark_signer
209 .split_secret_with_proofs(secret, threshold, num_shares)
210 .await
211 .map_err(|e| SdkError::Generic(e.to_string()))
212 }
213
214 async fn encrypt_secret_for_receiver(
215 &self,
216 private_key: &spark_wallet::EncryptedSecret,
217 receiver_public_key: &secp256k1::PublicKey,
218 ) -> Result<Vec<u8>, SdkError> {
219 self.spark_signer
220 .encrypt_secret_for_receiver(private_key, receiver_public_key)
221 .await
222 .map_err(|e| SdkError::Generic(e.to_string()))
223 }
224
225 async fn public_key_from_secret(
226 &self,
227 private_key: &spark_wallet::SecretSource,
228 ) -> Result<secp256k1::PublicKey, SdkError> {
229 self.spark_signer
230 .public_key_from_secret(private_key)
231 .await
232 .map_err(|e| SdkError::Generic(e.to_string()))
233 }
234
235 async fn sign_frost<'a>(
236 &self,
237 request: spark_wallet::SignFrostRequest<'a>,
238 ) -> Result<frost_secp256k1_tr::round2::SignatureShare, SdkError> {
239 self.spark_signer
240 .sign_frost(request)
241 .await
242 .map_err(|e| SdkError::Generic(e.to_string()))
243 }
244
245 async fn aggregate_frost<'a>(
246 &self,
247 request: spark_wallet::AggregateFrostRequest<'a>,
248 ) -> Result<frost_secp256k1_tr::Signature, SdkError> {
249 self.spark_signer
250 .aggregate_frost(request)
251 .await
252 .map_err(|e| SdkError::Generic(e.to_string()))
253 }
254
255 async fn hmac_sha256(
256 &self,
257 key_path: &DerivationPath,
258 input: &[u8],
259 ) -> Result<Hmac<sha256::Hash>, SdkError> {
260 let derived = self
261 .key_set
262 .identity_master_key
263 .derive_priv(&self.secp, key_path)
264 .map_err(|e| SdkError::Generic(e.to_string()))?;
265
266 let mut engine = HmacEngine::<sha256::Hash>::new(&derived.private_key.secret_bytes());
267 engine.input(input);
268 Ok(Hmac::<sha256::Hash>::from_engine(engine))
269 }
270}