1use std::collections::BTreeMap;
2use std::collections::BTreeSet;
3use std::collections::HashMap;
4
5use frost_core::round1::Nonce;
6use frost_core::round1::NonceCommitment;
7use frost_secp256k1_tr::keys::EvenY;
8use frost_secp256k1_tr::keys::KeyPackage as FrostKeyPackage;
9use frost_secp256k1_tr::keys::PublicKeyPackage;
10use frost_secp256k1_tr::keys::SigningShare;
11use frost_secp256k1_tr::keys::Tweak;
12use frost_secp256k1_tr::keys::VerifyingShare;
13use frost_secp256k1_tr::round1::SigningCommitments as FrostSigningCommitments;
14use frost_secp256k1_tr::round1::SigningNonces as FrostSigningNonces;
15use frost_secp256k1_tr::round2::SignatureShare;
16use frost_secp256k1_tr::Identifier;
17use frost_secp256k1_tr::SigningPackage;
18use frost_secp256k1_tr::VerifyingKey;
19
20use spark_protos::common::*;
21use spark_protos::frost::*;
22
23pub fn frost_nonce_from_proto(nonce: &SigningNonce) -> Result<FrostSigningNonces, String> {
24 let hiding_bytes = nonce.hiding.as_slice();
25 let binding_bytes = nonce.binding.as_slice();
26 let hiding = Nonce::deserialize(hiding_bytes).map_err(|e| e.to_string())?;
27 let binding = Nonce::deserialize(binding_bytes).map_err(|e| e.to_string())?;
28 Ok(FrostSigningNonces::from_nonces(hiding, binding))
29}
30
31pub fn frost_commitments_from_proto(
32 commitments: &SigningCommitment,
33) -> Result<FrostSigningCommitments, String> {
34 let hiding_bytes = commitments.hiding.as_slice();
35 let binding_bytes = commitments.binding.as_slice();
36 let hiding_commitment =
37 NonceCommitment::deserialize(hiding_bytes).map_err(|e| e.to_string())?;
38 let binding_commitment =
39 NonceCommitment::deserialize(binding_bytes).map_err(|e| e.to_string())?;
40 Ok(FrostSigningCommitments::new(
41 hiding_commitment,
42 binding_commitment,
43 ))
44}
45
46pub fn frost_signing_commitment_map_from_proto(
47 map: &HashMap<String, SigningCommitment>,
48) -> Result<BTreeMap<Identifier, FrostSigningCommitments>, String> {
49 map.iter()
50 .map(
51 |(k, v)| -> Result<(Identifier, FrostSigningCommitments), String> {
52 let identifier = hex_string_to_identifier(k)
53 .map_err(|e| format!("Failed to parse identifier: {}", e))?;
54 let commitments = frost_commitments_from_proto(v)?;
55 Ok((identifier, commitments))
56 },
57 )
58 .collect::<Result<BTreeMap<_, _>, String>>()
59}
60
61pub fn verifying_key_from_bytes(bytes: Vec<u8>) -> Result<VerifyingKey, String> {
62 VerifyingKey::deserialize(bytes.as_slice()).map_err(|e| e.to_string())
63}
64
65pub fn frost_build_signin_package(
66 signing_commitments: BTreeMap<Identifier, FrostSigningCommitments>,
67 message: &[u8],
68 signing_participants_groups: Option<Vec<BTreeSet<Identifier>>>,
69 adaptor_public_key: &[u8],
70) -> SigningPackage {
71 let adaptor_public_key = VerifyingKey::deserialize(adaptor_public_key).ok();
72 SigningPackage::new_with_adaptor(
73 signing_commitments,
74 signing_participants_groups,
75 message,
76 adaptor_public_key,
77 )
78}
79
80pub fn frost_signature_shares_from_proto(
81 shares: &HashMap<String, Vec<u8>>,
82 user_identifier: Identifier,
83 user_signature_share: &Vec<u8>,
84) -> Result<BTreeMap<Identifier, SignatureShare>, String> {
85 let mut shares_map = shares
86 .iter()
87 .map(|(k, v)| -> Result<(Identifier, SignatureShare), String> {
88 let identifier = hex_string_to_identifier(k)
89 .map_err(|e| format!("Failed to parse identifier: {}", e))?;
90 let share = SignatureShare::deserialize(v).map_err(|e| e.to_string())?;
91 Ok((identifier, share))
92 })
93 .collect::<Result<BTreeMap<_, _>, String>>()?;
94
95 if user_signature_share.len() > 0 {
96 shares_map.insert(
97 user_identifier,
98 SignatureShare::deserialize(user_signature_share).map_err(|e| e.to_string())?,
99 );
100 }
101 Ok(shares_map)
102}
103
104pub fn frost_public_package_from_proto(
105 public_shares: &HashMap<String, Vec<u8>>,
106 user_identifier: Identifier,
107 user_public_key: Vec<u8>,
108 verifying_key: VerifyingKey,
109) -> Result<PublicKeyPackage, String> {
110 let mut final_shares = public_shares
111 .iter()
112 .map(|(k, v)| -> Result<(Identifier, VerifyingShare), String> {
113 let identifier = hex_string_to_identifier(k)?;
114 let share = VerifyingShare::deserialize(v).map_err(|e| e.to_string())?;
115 Ok((identifier, share))
116 })
117 .collect::<Result<BTreeMap<_, _>, String>>()?;
118
119 if user_public_key.len() > 0 {
120 final_shares.insert(
121 user_identifier,
122 VerifyingShare::deserialize(user_public_key.as_slice()).map_err(|e| e.to_string())?,
123 );
124 }
125 tracing::info!("final_shares: {:?}", final_shares);
126 let public_key_package = PublicKeyPackage::new(final_shares, verifying_key);
127 Ok(public_key_package)
128}
129
130pub fn frost_key_package_from_proto(
131 key_package: &KeyPackage,
132 identifier_override: Option<Identifier>,
133 verifying_key: VerifyingKey,
134 role: i32,
135) -> Result<FrostKeyPackage, String> {
136 let signing_share = SigningShare::deserialize(key_package.secret_share.as_slice())
137 .map_err(|e| e.to_string())?;
138
139 let verifying_share = VerifyingShare::deserialize(
140 key_package
141 .public_shares
142 .get(&key_package.identifier)
143 .ok_or("Verifying share is not found")?
144 .as_slice()
145 .try_into()
146 .map_err(|_| "Verifying share is not 33 bytes")?,
147 )
148 .map_err(|e| e.to_string())?;
149
150 let identifier =
151 identifier_override.unwrap_or(hex_string_to_identifier(&key_package.identifier)?);
152
153 let result = FrostKeyPackage::new(
154 identifier,
155 signing_share,
156 verifying_share,
157 verifying_key,
158 key_package.min_signers as u16,
159 );
160
161 if role == 1 {
162 let merkle_root = vec![];
165 let result_tweaked = result.clone().tweak(Some(&merkle_root));
166 let result_even_y = result.clone().into_even_y(Some(verifying_key.has_even_y()));
167 let final_result = FrostKeyPackage::new(
168 *result_even_y.identifier(),
169 *result_even_y.signing_share(),
170 *result_even_y.verifying_share(),
171 *result_tweaked.verifying_key(),
172 *result_tweaked.min_signers(),
173 );
174 Ok(final_result)
175 } else {
176 Ok(result)
177 }
178}
179
180pub fn frost_nonce(req: &FrostNonceRequest) -> Result<FrostNonceResponse, String> {
181 let mut results = Vec::new();
182
183 for key_package in req.key_packages.iter() {
184 let verifying_key = verifying_key_from_bytes(key_package.public_key.clone())
185 .map_err(|e| format!("Failed to parse verifying key: {:?}", e))?;
186 let key_package = frost_key_package_from_proto(key_package, None, verifying_key, 0)
187 .map_err(|e| format!("Failed to parse key package: {:?}", e))?;
188
189 let rng = &mut rand::thread_rng();
190 let (nonce, commitment) =
191 frost_secp256k1_tr::round1::commit(&key_package.signing_share(), rng);
192
193 let pb_nonce = SigningNonce {
194 hiding: nonce.hiding().serialize().to_vec(),
195 binding: nonce.binding().serialize().to_vec(),
196 };
197
198 let pb_commitment = SigningCommitment {
199 hiding: commitment
200 .hiding()
201 .serialize()
202 .map_err(|e| format!("Failed to serialize hiding commitment: {:?}", e))?,
203 binding: commitment
204 .binding()
205 .serialize()
206 .map_err(|e| format!("Failed to serialize binding commitment: {:?}", e))?,
207 };
208
209 results.push(SigningNonceResult {
210 nonces: Some(pb_nonce),
211 commitments: Some(pb_commitment),
212 });
213 }
214
215 Ok(FrostNonceResponse { results })
216}
217
218pub fn sign_frost(req: &SignFrostRequest) -> Result<SignFrostResponse, String> {
219 let mut results = HashMap::new();
220 for job in req.signing_jobs.iter() {
221 let mut commitments = frost_signing_commitment_map_from_proto(&job.commitments)
222 .map_err(|e| format!("Failed to parse signing commitments: {:?}", e))?;
223
224 let user_identifier =
225 Identifier::derive("user".as_bytes()).expect("Failed to derive user identifier");
226
227 let mut signing_participants_groups = Vec::new();
228 signing_participants_groups.push(commitments.keys().cloned().collect());
229
230 tracing::debug!("User commitments: {:?}", job.user_commitments);
231
232 match &job.user_commitments {
233 Some(c) => {
234 let user_commitments = frost_commitments_from_proto(c)
235 .map_err(|e| format!("Failed to parse user commitments: {:?}", e))?;
236 commitments.insert(user_identifier, user_commitments);
237 signing_participants_groups.push(BTreeSet::from([user_identifier]));
238 }
239 None => {}
240 };
241 tracing::debug!("There are {} commitments", commitments.len());
242
243 let nonce = match &job.nonce {
244 Some(nonce) => frost_nonce_from_proto(nonce)
245 .map_err(|e| format!("Failed to parse nonce: {:?}", e))?,
246 None => return Err(format!("Nonce is required")),
247 };
248
249 let verifying_key = verifying_key_from_bytes(job.verifying_key.clone())
250 .map_err(|e| format!("Failed to parse verifying key: {:?}", e))?;
251
252 let identifier_override = match req.role {
253 0 => None,
254 1 => Some(user_identifier),
255 _ => return Err(format!("Invalid signing role")),
256 };
257
258 let key_package = match &job.key_package {
259 Some(key_package) => frost_key_package_from_proto(
260 key_package,
261 identifier_override,
262 verifying_key,
263 req.role,
264 )
265 .map_err(|e| format!("Failed to parse key package: {:?}", e))?,
266 None => return Err(format!("Key package is required")),
267 };
268
269 let signing_package = frost_build_signin_package(
270 commitments,
271 &job.message,
272 Some(signing_participants_groups),
273 &job.adaptor_public_key,
274 );
275
276 tracing::info!("Building signing package completed");
277 let tweak = vec![];
278 let signature_share = match req.role {
279 0 => frost_secp256k1_tr::round2::sign_with_tweak(
280 &signing_package,
281 &nonce,
282 &key_package,
283 Some(tweak.as_slice()),
284 )
285 .map_err(|e| format!("Failed to sign frost: {:?}", e))?,
286 _ => frost_secp256k1_tr::round2::sign(&signing_package, &nonce, &key_package)
287 .map_err(|e| format!("Failed to sign frost: {:?}", e))?,
288 };
289 tracing::info!("Signing frost completed");
290
291 results.insert(
292 job.job_id.clone(),
293 SigningResult {
294 signature_share: signature_share.serialize().to_vec(),
295 },
296 );
297 }
298
299 Ok(SignFrostResponse { results })
300}
301
302pub fn aggregate_frost(req: &AggregateFrostRequest) -> Result<AggregateFrostResponse, String> {
303 let mut commitments = frost_signing_commitment_map_from_proto(&req.commitments)
304 .map_err(|e| format!("Failed to parse signing commitments: {:?}", e))?;
305
306 let mut signing_participants_groups = Vec::new();
307 signing_participants_groups.push(commitments.keys().cloned().collect());
308
309 let user_identifier =
310 Identifier::derive("user".as_bytes()).expect("Failed to derive user identifier");
311
312 match &req.user_commitments {
313 Some(c) => {
314 let user_commitments = frost_commitments_from_proto(c)
315 .map_err(|e| format!("Failed to parse user commitments: {:?}", e))?;
316 commitments.insert(user_identifier, user_commitments);
317 }
318 None => {}
319 };
320
321 let verifying_key = verifying_key_from_bytes(req.verifying_key.clone())
322 .map_err(|e| format!("Failed to parse verifying key: {:?}", e))?;
323
324 signing_participants_groups.push(BTreeSet::from([user_identifier]));
325
326 let signing_package = frost_build_signin_package(
327 commitments,
328 &req.message,
329 Some(signing_participants_groups),
330 &req.adaptor_public_key,
331 );
332
333 let signature_shares = frost_signature_shares_from_proto(
334 &req.signature_shares,
335 user_identifier,
336 &req.user_signature_share,
337 )
338 .map_err(|e| format!("Failed to parse signature shares: {:?}", e))?;
339
340 let public_package = frost_public_package_from_proto(
341 &req.public_shares,
342 user_identifier,
343 req.user_public_key.clone(),
344 verifying_key,
345 )
346 .map_err(|e| format!("Failed to parse public package: {:?}", e))?;
347
348 let tweak = vec![];
349
350 tracing::info!("signing_package: {:?}", signing_package);
351 tracing::info!("signature_shares: {:?}", signature_shares);
352 tracing::info!("public_package: {:?}", public_package);
353
354 let signature = frost_secp256k1_tr::aggregate_with_tweak(
355 &signing_package,
356 &signature_shares,
357 &public_package,
358 Some(&tweak),
359 )
360 .map_err(|e| format!("Failed to aggregate frost: {:?}", e))?;
361
362 Ok(AggregateFrostResponse {
363 signature: signature
364 .serialize()
365 .map_err(|e| format!("Failed to serialize signature: {:?}", e))?,
366 })
367}
368
369pub fn validate_signature_share(req: &ValidateSignatureShareRequest) -> Result<(), String> {
370 let identifier = match req.role {
371 0 => hex_string_to_identifier(&req.identifier)
372 .map_err(|e| format!("Failed to parse identifier: {:?}", e))?,
373 1 => Identifier::derive("user".as_bytes()).expect("Failed to derive user identifier"),
374 _ => return Err(format!("Invalid signing role")),
375 };
376
377 let signature_share = SignatureShare::deserialize(req.signature_share.as_slice())
378 .map_err(|e| format!("Failed to parse signature share: {:?}", e))?;
379 let verifying_key = verifying_key_from_bytes(req.verifying_key.clone())
380 .map_err(|e| format!("Failed to parse verifying key: {:?}", e))?;
381
382 let mut commitments = frost_signing_commitment_map_from_proto(&req.commitments)
383 .map_err(|e| format!("Failed to parse signing commitments: {:?}", e))?;
384
385 let user_identifier =
386 Identifier::derive("user".as_bytes()).expect("Failed to derive user identifier");
387
388 let mut signing_participants_groups = Vec::new();
389 signing_participants_groups.push(commitments.keys().cloned().collect());
390
391 if let Some(c) = &req.user_commitments {
392 let user_commitments = frost_commitments_from_proto(c)
393 .map_err(|e| format!("Failed to parse user commitments: {:?}", e))?;
394 commitments.insert(user_identifier, user_commitments);
395 signing_participants_groups.push(BTreeSet::from([user_identifier]));
396 }
397
398 let public_share = VerifyingShare::deserialize(req.public_share.as_slice())
399 .map_err(|e| format!("Failed to parse public share: {:?}", e))?;
400
401 let adaptor_key: Vec<u8> = vec![];
402
403 let signing_package = frost_build_signin_package(
404 commitments,
405 &req.message,
406 Some(signing_participants_groups),
407 &adaptor_key,
408 );
409
410 let dummy_signing_share = SigningShare::deserialize(&[0; 32])
411 .map_err(|e| format!("Failed to parse dummy signing share: {:?}", e))?;
412
413 let result = FrostKeyPackage::new(
414 identifier,
415 dummy_signing_share,
416 public_share,
417 verifying_key,
418 2,
419 );
420 let merkle_root = vec![];
421 let result_tweaked = result.clone().tweak(Some(&merkle_root));
422 let result_even_y = result.clone().into_even_y(Some(verifying_key.has_even_y()));
423
424 let verifying_share = match req.role {
425 0 => result_tweaked.verifying_share(),
426 1 => result_even_y.verifying_share(),
427 _ => return Err(format!("Invalid signing role")),
428 };
429
430 let verify_identifier = match req.role {
431 0 => identifier,
432 1 => user_identifier,
433 _ => return Err(format!("Invalid signing role")),
434 };
435
436 frost_secp256k1_tr::verify_signature_share(
437 verify_identifier,
438 &verifying_share,
439 &signature_share,
440 &signing_package,
441 &result_tweaked.verifying_key(),
442 )
443 .map_err(|e| format!("Failed to verify signature share: {:?}", e))?;
444
445 tracing::info!("Signature share is valid");
446
447 Ok(())
448}
449
450pub fn hex_string_to_identifier(identifier: &str) -> Result<Identifier, String> {
452 let id_bytes: [u8; 32] = hex::decode(identifier)
453 .map_err(|e| format!("Invalid hex: {:?}", e))?
454 .try_into()
455 .map_err(|e| format!("Identifier is not 32 bytes: {:?}", e))?;
456 Identifier::deserialize(&id_bytes)
457 .map_err(|e| format!("Failed to deserialize identifier: {:?}", e))
458}