1use hashbrown::{HashMap, HashSet};
2use num_traits::{One, Zero};
3use polynomial::Polynomial;
4use rand_core::{CryptoRng, RngCore};
5use tracing::warn;
6
7use crate::{
8 common::{check_public_shares, Nonce, PolyCommitment, PublicNonce, Signature, SignatureShare},
9 compute,
10 curve::{
11 point::{Point, G},
12 scalar::Scalar,
13 },
14 errors::{AggregatorError, DkgError},
15 schnorr::ID,
16 taproot::SchnorrProof,
17 traits,
18 vss::VSS,
19};
20
21#[derive(Clone, Debug, Eq, PartialEq)]
22pub struct Party {
24 pub party_id: u32,
26 pub key_ids: Vec<u32>,
28 num_keys: u32,
30 num_parties: u32,
31 threshold: u32,
32 f: Option<Polynomial<Scalar>>,
33 private_keys: HashMap<u32, Scalar>,
34 group_key: Point,
35 nonce: Nonce,
36}
37
38impl Party {
39 pub fn new<RNG: RngCore + CryptoRng>(
41 party_id: u32,
42 key_ids: &[u32],
43 num_parties: u32,
44 num_keys: u32,
45 threshold: u32,
46 rng: &mut RNG,
47 ) -> Self {
48 Self {
49 party_id,
50 key_ids: key_ids.to_vec(),
51 num_keys,
52 num_parties,
53 threshold,
54 f: Some(VSS::random_poly(threshold - 1, rng)),
55 private_keys: Default::default(),
56 group_key: Point::zero(),
57 nonce: Nonce::zero(),
58 }
59 }
60
61 pub fn gen_nonce<RNG: RngCore + CryptoRng>(&mut self, rng: &mut RNG) -> PublicNonce {
63 self.nonce = Nonce::random(rng);
64 PublicNonce::from(&self.nonce)
65 }
66
67 pub fn get_poly_commitment<RNG: RngCore + CryptoRng>(
69 &self,
70 rng: &mut RNG,
71 ) -> Option<PolyCommitment> {
72 if let Some(poly) = &self.f {
73 Some(PolyCommitment {
74 id: ID::new(&self.id(), &poly.data()[0], rng),
75 poly: (0..poly.data().len())
76 .map(|i| &poly.data()[i] * G)
77 .collect(),
78 })
79 } else {
80 warn!("get_poly_commitment called with no polynomial");
81 None
82 }
83 }
84
85 pub fn get_shares(&self) -> HashMap<u32, Scalar> {
87 let mut shares = HashMap::new();
88 if let Some(poly) = &self.f {
89 for i in 1..self.num_keys + 1 {
90 shares.insert(i, poly.eval(compute::id(i)));
91 }
92 } else {
93 warn!("get_poly_commitment called with no polynomial");
94 }
95 shares
96 }
97
98 pub fn compute_secret(
104 &mut self,
105 private_shares: &HashMap<u32, HashMap<u32, Scalar>>,
106 public_shares: &HashMap<u32, PolyCommitment>,
107 ) -> Result<(), DkgError> {
108 self.private_keys.clear();
109 self.group_key = Point::zero();
110
111 let threshold: usize = self.threshold.try_into()?;
112
113 let mut bad_ids = Vec::new();
114 for (i, comm) in public_shares.iter() {
115 if !check_public_shares(comm, threshold) {
116 bad_ids.push(*i);
117 } else {
118 self.group_key += comm.poly[0];
119 }
120 }
121 if !bad_ids.is_empty() {
122 return Err(DkgError::BadPublicShares(bad_ids));
123 }
124
125 let mut missing_shares = Vec::new();
126 for dst_key_id in &self.key_ids {
127 for src_key_id in public_shares.keys() {
128 match private_shares.get(dst_key_id) {
129 Some(shares) => {
130 if shares.get(src_key_id).is_none() {
131 missing_shares.push((*dst_key_id, *src_key_id));
132 }
133 }
134 None => {
135 missing_shares.push((*dst_key_id, *src_key_id));
136 }
137 }
138 }
139 }
140 if !missing_shares.is_empty() {
141 return Err(DkgError::MissingPrivateShares(missing_shares));
142 }
143
144 let mut bad_shares = Vec::new();
145 for key_id in &self.key_ids {
146 if let Some(shares) = private_shares.get(key_id) {
147 for (sender, s) in shares {
148 if let Some(comm) = public_shares.get(sender) {
149 if s * G != compute::poly(&compute::id(*key_id), &comm.poly)? {
150 bad_shares.push(*sender);
151 }
152 } else {
153 warn!("unable to check private share from {}: no corresponding public share, even though we checked for it above", sender);
154 }
155 }
156 } else {
157 warn!(
158 "no private shares for key_id {}, even though we checked for it above",
159 key_id
160 );
161 }
162 }
163 if !bad_shares.is_empty() {
164 return Err(DkgError::BadPrivateShares(bad_shares));
165 }
166
167 for key_id in &self.key_ids {
168 self.private_keys.insert(*key_id, Scalar::zero());
169 if let Some(shares) = private_shares.get(key_id) {
170 let secret = shares.values().sum();
171 self.private_keys.insert(*key_id, secret);
172 } else {
173 warn!(
174 "no private shares for key_id {}, even though we checked for it above",
175 key_id
176 );
177 }
178 }
179
180 Ok(())
181 }
182
183 pub fn id(&self) -> Scalar {
185 compute::id(self.party_id)
186 }
187
188 pub fn sign(
190 &self,
191 msg: &[u8],
192 party_ids: &[u32],
193 key_ids: &[u32],
194 nonces: &[PublicNonce],
195 ) -> SignatureShare {
196 self.sign_with_tweak(msg, party_ids, key_ids, nonces, None)
197 }
198
199 #[allow(non_snake_case)]
204 pub fn sign_with_tweak(
205 &self,
206 msg: &[u8],
207 party_ids: &[u32],
208 key_ids: &[u32],
209 nonces: &[PublicNonce],
210 tweak: Option<Scalar>,
211 ) -> SignatureShare {
212 let mut cx_sign = Scalar::one();
217 let tweaked_public_key = if let Some(t) = tweak {
218 if t != Scalar::zero() {
219 let key = compute::tweaked_public_key_from_tweak(&self.group_key, t);
220 if key.has_even_y() ^ self.group_key.has_even_y() {
221 cx_sign = -cx_sign;
222 }
223
224 key
225 } else {
226 if !self.group_key.has_even_y() {
227 cx_sign = -cx_sign;
228 }
229 self.group_key
230 }
231 } else {
232 self.group_key
233 };
234 let (_, R) = compute::intermediate(msg, party_ids, nonces);
235 let c = compute::challenge(&tweaked_public_key, &R, msg);
236 let mut r = &self.nonce.d + &self.nonce.e * compute::binding(&self.id(), nonces, msg);
237 if tweak.is_some() && !R.has_even_y() {
238 r = -r;
239 }
240
241 let mut cx = Scalar::zero();
242 for key_id in self.key_ids.iter() {
243 cx += c * &self.private_keys[key_id] * compute::lambda(*key_id, key_ids);
244 }
245
246 cx = cx_sign * cx;
247
248 let z = r + cx;
249
250 SignatureShare {
251 id: self.party_id,
252 z_i: z,
253 key_ids: self.key_ids.clone(),
254 }
255 }
256}
257
258#[derive(Clone, Debug, PartialEq)]
260pub struct Aggregator {
261 pub num_keys: u32,
263 pub threshold: u32,
265 pub poly: Vec<Point>,
267}
268
269impl Aggregator {
270 #[allow(non_snake_case)]
275 pub fn sign_with_tweak(
276 &mut self,
277 msg: &[u8],
278 nonces: &[PublicNonce],
279 sig_shares: &[SignatureShare],
280 _key_ids: &[u32],
281 tweak: Option<Scalar>,
282 ) -> Result<(Point, Signature), AggregatorError> {
283 if nonces.len() != sig_shares.len() {
284 return Err(AggregatorError::BadNonceLen(nonces.len(), sig_shares.len()));
285 }
286
287 let party_ids: Vec<u32> = sig_shares.iter().map(|ss| ss.id).collect();
288 let (_Rs, R) = compute::intermediate(msg, &party_ids, nonces);
289 let mut z = Scalar::zero();
290 let mut cx_sign = Scalar::one();
291 let aggregate_public_key = self.poly[0];
292 let tweaked_public_key = if let Some(t) = tweak {
293 if t != Scalar::zero() {
294 let key = compute::tweaked_public_key_from_tweak(&aggregate_public_key, t);
295 if !key.has_even_y() {
296 cx_sign = -cx_sign;
297 }
298 key
299 } else {
300 aggregate_public_key
301 }
302 } else {
303 aggregate_public_key
304 };
305 let c = compute::challenge(&tweaked_public_key, &R, msg);
306 for sig_share in sig_shares {
308 z += sig_share.z_i;
309 }
310
311 if let Some(t) = tweak {
313 z += cx_sign * c * t;
314 }
315
316 let sig = Signature { R, z };
317
318 Ok((tweaked_public_key, sig))
319 }
320
321 #[allow(non_snake_case)]
326 pub fn check_signature_shares(
327 &mut self,
328 msg: &[u8],
329 nonces: &[PublicNonce],
330 sig_shares: &[SignatureShare],
331 key_ids: &[u32],
332 tweak: Option<Scalar>,
333 ) -> AggregatorError {
334 if nonces.len() != sig_shares.len() {
335 return AggregatorError::BadNonceLen(nonces.len(), sig_shares.len());
336 }
337
338 let party_ids: Vec<u32> = sig_shares.iter().map(|ss| ss.id).collect();
339 let (Rs, R) = compute::intermediate(msg, &party_ids, nonces);
340 let mut bad_party_keys = Vec::new();
341 let mut bad_party_sigs = Vec::new();
342 let aggregate_public_key = self.poly[0];
343 let tweaked_public_key = if let Some(t) = tweak {
344 if t != Scalar::zero() {
345 compute::tweaked_public_key_from_tweak(&aggregate_public_key, t)
346 } else {
347 aggregate_public_key
348 }
349 } else {
350 aggregate_public_key
351 };
352 let c = compute::challenge(&tweaked_public_key, &R, msg);
353 let mut r_sign = Scalar::one();
354 let mut cx_sign = Scalar::one();
355 if let Some(t) = tweak {
356 if !R.has_even_y() {
357 r_sign = -Scalar::one();
358 }
359 if t != Scalar::zero() {
360 if !tweaked_public_key.has_even_y() ^ !aggregate_public_key.has_even_y() {
361 cx_sign = -Scalar::one();
362 }
363 } else if !aggregate_public_key.has_even_y() {
364 cx_sign = -Scalar::one();
365 }
366 }
367
368 for i in 0..sig_shares.len() {
369 let z_i = sig_shares[i].z_i;
370 let mut cx = Point::zero();
371
372 for key_id in &sig_shares[i].key_ids {
373 let kid = compute::id(*key_id);
374 let public_key = match compute::poly(&kid, &self.poly) {
375 Ok(p) => p,
376 Err(_) => {
377 bad_party_keys.push(sig_shares[i].id);
378 Point::zero()
379 }
380 };
381
382 cx += compute::lambda(*key_id, key_ids) * c * public_key;
383 }
384
385 if z_i * G != (r_sign * Rs[i] + cx_sign * cx) {
386 bad_party_sigs.push(sig_shares[i].id);
387 }
388 }
389 if !bad_party_keys.is_empty() {
390 AggregatorError::BadPartyKeys(bad_party_keys)
391 } else if !bad_party_sigs.is_empty() {
392 AggregatorError::BadPartySigs(bad_party_sigs)
393 } else {
394 AggregatorError::BadGroupSig
395 }
396 }
397}
398
399impl traits::Aggregator for Aggregator {
400 fn new(num_keys: u32, threshold: u32) -> Self {
402 Self {
403 num_keys,
404 threshold,
405 poly: Default::default(),
406 }
407 }
408
409 fn init(&mut self, comms: &HashMap<u32, PolyCommitment>) -> Result<(), AggregatorError> {
411 let threshold: usize = self.threshold.try_into()?;
412 let mut poly = Vec::with_capacity(threshold);
413
414 for i in 0..poly.capacity() {
415 poly.push(Point::zero());
416 for (_, comm) in comms {
417 poly[i] += &comm.poly[i];
418 }
419 }
420
421 self.poly = poly;
422
423 Ok(())
424 }
425
426 fn sign(
428 &mut self,
429 msg: &[u8],
430 nonces: &[PublicNonce],
431 sig_shares: &[SignatureShare],
432 key_ids: &[u32],
433 ) -> Result<Signature, AggregatorError> {
434 let (key, sig) = self.sign_with_tweak(msg, nonces, sig_shares, key_ids, None)?;
435
436 if sig.verify(&key, msg) {
437 Ok(sig)
438 } else {
439 Err(self.check_signature_shares(msg, nonces, sig_shares, key_ids, None))
440 }
441 }
442
443 fn sign_schnorr(
445 &mut self,
446 msg: &[u8],
447 nonces: &[PublicNonce],
448 sig_shares: &[SignatureShare],
449 key_ids: &[u32],
450 ) -> Result<SchnorrProof, AggregatorError> {
451 let tweak = Scalar::from(0);
452 let (key, sig) = self.sign_with_tweak(msg, nonces, sig_shares, key_ids, Some(tweak))?;
453 let proof = SchnorrProof::new(&sig);
454
455 if proof.verify(&key.x(), msg) {
456 Ok(proof)
457 } else {
458 Err(self.check_signature_shares(msg, nonces, sig_shares, key_ids, Some(tweak)))
459 }
460 }
461
462 fn sign_taproot(
464 &mut self,
465 msg: &[u8],
466 nonces: &[PublicNonce],
467 sig_shares: &[SignatureShare],
468 key_ids: &[u32],
469 merkle_root: Option<[u8; 32]>,
470 ) -> Result<SchnorrProof, AggregatorError> {
471 let tweak = compute::tweak(&self.poly[0], merkle_root);
472 let (key, sig) = self.sign_with_tweak(msg, nonces, sig_shares, key_ids, Some(tweak))?;
473 let proof = SchnorrProof::new(&sig);
474
475 if proof.verify(&key.x(), msg) {
476 Ok(proof)
477 } else {
478 Err(self.check_signature_shares(msg, nonces, sig_shares, key_ids, Some(tweak)))
479 }
480 }
481}
482
483pub type Signer = Party;
485
486impl traits::Signer for Party {
487 fn new<RNG: RngCore + CryptoRng>(
488 party_id: u32,
489 key_ids: &[u32],
490 num_signers: u32,
491 num_keys: u32,
492 threshold: u32,
493 rng: &mut RNG,
494 ) -> Self {
495 Party::new(party_id, key_ids, num_signers, num_keys, threshold, rng)
496 }
497
498 fn load(state: &traits::SignerState) -> Self {
499 assert_eq!(state.parties.len(), 1);
501
502 let party_state = &state.parties[0].1;
503
504 Self {
505 party_id: state.id,
506 key_ids: state.key_ids.clone(),
507 num_keys: state.num_keys,
508 num_parties: state.num_parties,
509 threshold: state.threshold,
510 f: party_state.polynomial.clone(),
511 private_keys: party_state
512 .private_keys
513 .iter()
514 .map(|(k, v)| (*k, *v))
515 .collect(),
516 group_key: state.group_key,
517 nonce: party_state.nonce.clone(),
518 }
519 }
520
521 fn save(&self) -> traits::SignerState {
522 let party_state = traits::PartyState {
523 polynomial: self.f.clone(),
524 private_keys: self.private_keys.iter().map(|(k, v)| (*k, *v)).collect(),
525 nonce: self.nonce.clone(),
526 };
527 traits::SignerState {
528 id: self.party_id,
529 key_ids: self.key_ids.clone(),
530 num_keys: self.num_keys,
531 num_parties: self.num_parties,
532 threshold: self.threshold,
533 group_key: self.group_key,
534 parties: vec![(self.party_id, party_state)],
535 }
536 }
537
538 fn get_id(&self) -> u32 {
539 self.party_id
540 }
541
542 fn get_key_ids(&self) -> Vec<u32> {
543 self.key_ids.clone()
544 }
545
546 fn get_num_parties(&self) -> u32 {
547 self.num_parties
548 }
549
550 fn get_poly_commitments<RNG: RngCore + CryptoRng>(&self, rng: &mut RNG) -> Vec<PolyCommitment> {
551 if let Some(poly) = self.get_poly_commitment(rng) {
552 vec![poly.clone()]
553 } else {
554 vec![]
555 }
556 }
557
558 fn reset_polys<RNG: RngCore + CryptoRng>(&mut self, rng: &mut RNG) {
559 self.f = Some(VSS::random_poly(self.threshold - 1, rng));
560 }
561
562 fn clear_polys(&mut self) {
563 self.f = None;
564 }
565
566 fn get_shares(&self) -> HashMap<u32, HashMap<u32, Scalar>> {
567 let mut shares = HashMap::new();
568
569 shares.insert(self.party_id, self.get_shares());
570
571 shares
572 }
573
574 fn compute_secrets(
575 &mut self,
576 private_shares: &HashMap<u32, HashMap<u32, Scalar>>,
577 polys: &HashMap<u32, PolyCommitment>,
578 ) -> Result<(), HashMap<u32, DkgError>> {
579 let mut key_shares = HashMap::new();
581 for dest_key_id in self.get_key_ids() {
582 let mut shares = HashMap::new();
583 for (src_party_id, signer_shares) in private_shares.iter() {
584 if let Some(signer_share) = signer_shares.get(&dest_key_id) {
585 shares.insert(*src_party_id, *signer_share);
586 }
587 }
588 key_shares.insert(dest_key_id, shares);
589 }
590
591 match self.compute_secret(&key_shares, polys) {
592 Ok(()) => Ok(()),
593 Err(dkg_error) => {
594 let mut dkg_errors = HashMap::new();
595 dkg_errors.insert(self.party_id, dkg_error);
596 Err(dkg_errors)
597 }
598 }
599 }
600
601 fn gen_nonces<RNG: RngCore + CryptoRng>(&mut self, rng: &mut RNG) -> Vec<PublicNonce> {
602 vec![self.gen_nonce(rng)]
603 }
604
605 fn compute_intermediate(
606 msg: &[u8],
607 signer_ids: &[u32],
608 _key_ids: &[u32],
609 nonces: &[PublicNonce],
610 ) -> (Vec<Point>, Point) {
611 compute::intermediate(msg, signer_ids, nonces)
612 }
613
614 fn validate_party_id(
615 signer_id: u32,
616 party_id: u32,
617 _signer_key_ids: &HashMap<u32, HashSet<u32>>,
618 ) -> bool {
619 signer_id == party_id
620 }
621
622 fn sign(
623 &self,
624 msg: &[u8],
625 signer_ids: &[u32],
626 key_ids: &[u32],
627 nonces: &[PublicNonce],
628 ) -> Vec<SignatureShare> {
629 vec![self.sign(msg, signer_ids, key_ids, nonces)]
630 }
631
632 fn sign_schnorr(
633 &self,
634 msg: &[u8],
635 signer_ids: &[u32],
636 key_ids: &[u32],
637 nonces: &[PublicNonce],
638 ) -> Vec<SignatureShare> {
639 vec![self.sign_with_tweak(msg, signer_ids, key_ids, nonces, Some(Scalar::from(0)))]
640 }
641
642 fn sign_taproot(
643 &self,
644 msg: &[u8],
645 signer_ids: &[u32],
646 key_ids: &[u32],
647 nonces: &[PublicNonce],
648 merkle_root: Option<[u8; 32]>,
649 ) -> Vec<SignatureShare> {
650 let tweak = compute::tweak(&self.group_key, merkle_root);
651 vec![self.sign_with_tweak(msg, signer_ids, key_ids, nonces, Some(tweak))]
652 }
653}
654
655pub mod test_helpers {
657 use crate::common::{PolyCommitment, PublicNonce};
658 use crate::errors::DkgError;
659 use crate::traits::Signer;
660 use crate::v2;
661 use crate::v2::SignatureShare;
662
663 use hashbrown::HashMap;
664 use rand_core::{CryptoRng, RngCore};
665
666 pub fn dkg<RNG: RngCore + CryptoRng>(
668 signers: &mut [v2::Party],
669 rng: &mut RNG,
670 ) -> Result<HashMap<u32, PolyCommitment>, HashMap<u32, DkgError>> {
671 let mut polys: HashMap<u32, PolyCommitment> = Default::default();
672 for signer in signers.iter() {
673 if let Some(poly) = signer.get_poly_commitment(rng) {
674 polys.insert(signer.get_id(), poly);
675 }
676 }
677
678 let mut broadcast_shares = Vec::new();
680 for party in signers.iter() {
681 broadcast_shares.push((party.party_id, party.get_shares()));
682 }
683
684 let mut secret_errors = HashMap::new();
687 for party in signers.iter_mut() {
688 let mut party_shares = HashMap::new();
689 for key_id in party.key_ids.clone() {
690 let mut key_shares = HashMap::new();
691
692 for (id, shares) in &broadcast_shares {
693 if let Some(share) = shares.get(&key_id) {
694 key_shares.insert(*id, *share);
695 }
696 }
697
698 party_shares.insert(key_id, key_shares);
699 }
700
701 if let Err(secret_error) = party.compute_secret(&party_shares, &polys) {
702 secret_errors.insert(party.party_id, secret_error);
703 }
704 }
705
706 if secret_errors.is_empty() {
707 Ok(polys)
708 } else {
709 Err(secret_errors)
710 }
711 }
712
713 pub fn sign<RNG: RngCore + CryptoRng>(
715 msg: &[u8],
716 signers: &mut [v2::Party],
717 rng: &mut RNG,
718 ) -> (Vec<PublicNonce>, Vec<SignatureShare>, Vec<u32>) {
719 let party_ids: Vec<u32> = signers.iter().map(|s| s.party_id).collect();
720 let key_ids: Vec<u32> = signers.iter().flat_map(|s| s.key_ids.clone()).collect();
721 let nonces: Vec<PublicNonce> = signers.iter_mut().map(|s| s.gen_nonce(rng)).collect();
722 let shares = signers
723 .iter()
724 .map(|s| s.sign(msg, &party_ids, &key_ids, &nonces))
725 .collect();
726
727 (nonces, shares, key_ids)
728 }
729}
730
731#[cfg(test)]
732mod tests {
733 use hashbrown::{HashMap, HashSet};
734
735 use crate::util::create_rng;
736 use crate::{
737 traits::{
738 self, test_helpers::run_compute_secrets_missing_private_shares, Aggregator, Signer,
739 },
740 v2,
741 };
742
743 #[test]
744 fn party_save_load() {
745 let mut rng = create_rng();
746 let key_ids = [1, 2, 3];
747 let n: u32 = 10;
748 let t: u32 = 7;
749
750 let signer = v2::Party::new(0, &key_ids, 1, n, t, &mut rng);
751
752 let state = signer.save();
753 let loaded = v2::Party::load(&state);
754
755 assert_eq!(signer, loaded);
756 }
757
758 #[test]
759 fn clear_polys() {
760 let mut rng = create_rng();
761 let key_ids = [1, 2, 3];
762 let n: u32 = 10;
763 let t: u32 = 7;
764
765 let mut signer = v2::Party::new(0, &key_ids, 1, n, t, &mut rng);
766
767 assert_eq!(signer.get_poly_commitments(&mut rng).len(), 1);
768 assert_eq!(signer.get_shares().len(), usize::try_from(n).unwrap());
769
770 signer.clear_polys();
771
772 assert_eq!(signer.get_poly_commitments(&mut rng).len(), 0);
773 assert_eq!(signer.get_shares().len(), 0);
774 }
775
776 #[test]
777 fn aggregator_sign() {
778 let mut rng = create_rng();
779 let msg = "It was many and many a year ago".as_bytes();
780 let n_k: u32 = 10;
781 let t: u32 = 7;
782 let party_key_ids: Vec<Vec<u32>> = [
783 [1, 2, 3].to_vec(),
784 [4, 5].to_vec(),
785 [6, 7, 8].to_vec(),
786 [9, 10].to_vec(),
787 ]
788 .to_vec();
789 let n_p = party_key_ids.len().try_into().unwrap();
790 let mut signers: Vec<v2::Party> = party_key_ids
791 .iter()
792 .enumerate()
793 .map(|(pid, pkids)| {
794 v2::Party::new(pid.try_into().unwrap(), pkids, n_p, n_k, t, &mut rng)
795 })
796 .collect();
797
798 let comms = match traits::test_helpers::dkg(&mut signers, &mut rng) {
799 Ok(comms) => comms,
800 Err(secret_errors) => {
801 panic!("Got secret errors from DKG: {:?}", secret_errors);
802 }
803 };
804
805 {
807 let mut signers = [signers[0].clone(), signers[1].clone(), signers[3].clone()].to_vec();
808 let mut sig_agg = v2::Aggregator::new(n_k, t);
809
810 sig_agg.init(&comms).expect("aggregator init failed");
811
812 let (nonces, sig_shares, key_ids) = v2::test_helpers::sign(msg, &mut signers, &mut rng);
813 if let Err(e) = sig_agg.sign(msg, &nonces, &sig_shares, &key_ids) {
814 panic!("Aggregator sign failed: {:?}", e);
815 }
816 }
817 }
818
819 #[test]
820 pub fn run_compute_secrets_missing_shares() {
822 run_compute_secrets_missing_private_shares::<v2::Signer>()
823 }
824
825 #[test]
826 pub fn bad_polynomial_length() {
828 let gt = |t| t + 1;
829 let lt = |t| t - 1;
830 traits::test_helpers::bad_polynomial_length::<v2::Signer, _>(gt);
831 traits::test_helpers::bad_polynomial_length::<v2::Signer, _>(lt);
832 }
833
834 #[test]
835 pub fn bad_polynomial_commitment() {
837 traits::test_helpers::bad_polynomial_commitment::<v2::Signer>();
838 }
839
840 #[test]
841 fn validate_party_id() {
843 let mut signer_key_ids = HashMap::new();
844 let mut key_ids = HashSet::new();
845
846 key_ids.insert(1);
847 signer_key_ids.insert(0, key_ids);
848
849 assert!(v2::Signer::validate_party_id(0, 0, &signer_key_ids));
850 assert!(!v2::Signer::validate_party_id(0, 1, &signer_key_ids));
851 }
852}