1pub mod arbiter;
157pub use arbiter::Arbiter;
158pub mod dealer;
159pub use dealer::Dealer;
160pub mod ops;
161pub mod player;
162pub use player::Player;
163pub mod types;
164
165#[derive(thiserror::Error, Debug)]
166pub enum Error {
167 #[error("unexpected polynomial")]
168 UnexpectedPolynomial,
169 #[error("commitment has wrong degree")]
170 CommitmentWrongDegree,
171 #[error("misdirected share")]
172 MisdirectedShare,
173 #[error("share does not on commitment")]
174 ShareWrongCommitment,
175 #[error("insufficient dealings")]
176 InsufficientDealings,
177 #[error("reshare mismatch")]
178 ReshareMismatch,
179 #[error("share interpolation failed")]
180 ShareInterpolationFailed,
181 #[error("public key interpolation failed")]
182 PublicKeyInterpolationFailed,
183 #[error("dealer is invalid")]
184 DealerInvalid,
185 #[error("player invalid")]
186 PlayerInvalid,
187 #[error("missing share")]
188 MissingShare,
189 #[error("missing commitment")]
190 MissingCommitment,
191 #[error("too many commitments")]
192 TooManyCommitments,
193 #[error("duplicate commitment")]
194 DuplicateCommitment,
195 #[error("duplicate share")]
196 DuplicateShare,
197 #[error("duplicate ack")]
198 DuplicateAck,
199 #[error("mismatched commitment")]
200 MismatchedCommitment,
201 #[error("mismatched share")]
202 MismatchedShare,
203 #[error("too many reveals")]
204 TooManyReveals,
205 #[error("incorrect active")]
206 IncorrectActive,
207 #[error("already active")]
208 AlreadyActive,
209 #[error("invalid commitments")]
210 InvalidCommitments,
211 #[error("dealer disqualified")]
212 DealerDisqualified,
213}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218 use crate::{
219 bls12381::primitives::{
220 ops::{
221 partial_sign_proof_of_possession, threshold_signature_recover,
222 verify_proof_of_possession,
223 },
224 poly::{self, public},
225 variant::{MinPk, MinSig, Variant},
226 },
227 ed25519::{PrivateKey, PublicKey},
228 PrivateKeyExt as _, Signer as _,
229 };
230 use commonware_utils::{quorum, set::Ordered};
231 use rand::{rngs::StdRng, SeedableRng};
232 use std::collections::{BTreeMap, HashMap};
233
234 #[test]
235 fn test_invalid_commitment() {
236 let n = 5;
238 let mut rng = StdRng::seed_from_u64(0);
239
240 let contributors = (0..n)
242 .map(|i| PrivateKey::from_seed(i as u64).public_key())
243 .collect::<Ordered<_>>();
244
245 let (_, _, shares) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
247
248 let t = quorum(n);
250 let (public, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
251
252 let mut player = Player::<_, MinSig>::new(
254 contributors[0].clone(),
255 None,
256 contributors.clone(),
257 contributors.clone(),
258 1,
259 );
260
261 let result = player.share(contributors[0].clone(), public, shares[0].clone());
263 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
264 }
265
266 #[test]
267 fn test_mismatched_commitment() {
268 let n = 5;
270 let mut rng = StdRng::seed_from_u64(0);
271
272 let contributors = (0..n)
274 .map(|i| PrivateKey::from_seed(i as u64).public_key())
275 .collect::<Ordered<_>>();
276
277 let (_, commitment, shares) =
279 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
280
281 let t = quorum(n);
283 let (other_commitment, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
284
285 let mut player = Player::<_, MinSig>::new(
287 contributors[0].clone(),
288 None,
289 contributors.clone(),
290 contributors.clone(),
291 1,
292 );
293
294 player
296 .share(contributors[0].clone(), commitment, shares[0].clone())
297 .unwrap();
298
299 let result = player.share(contributors[0].clone(), other_commitment, shares[0].clone());
301 assert!(matches!(result, Err(Error::MismatchedCommitment)));
302 }
303
304 #[test]
305 fn test_mismatched_share() {
306 let n = 5;
308 let mut rng = StdRng::seed_from_u64(0);
309
310 let contributors = (0..n)
312 .map(|i| PrivateKey::from_seed(i as u64).public_key())
313 .collect::<Ordered<_>>();
314
315 let (_, commitment, shares) =
317 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
318
319 let t = quorum(n);
321 let (_, other_shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
322
323 let mut player = Player::<_, MinSig>::new(
325 contributors[0].clone(),
326 None,
327 contributors.clone(),
328 contributors.clone(),
329 1,
330 );
331
332 player
334 .share(
335 contributors[0].clone(),
336 commitment.clone(),
337 shares[0].clone(),
338 )
339 .unwrap();
340
341 let result = player.share(contributors[0].clone(), commitment, other_shares[0].clone());
343 assert!(matches!(result, Err(Error::MismatchedShare)));
344 }
345
346 #[test]
347 fn test_duplicate_share() {
348 let n = 5;
350 let mut rng = StdRng::seed_from_u64(0);
351
352 let contributors = (0..n)
354 .map(|i| PrivateKey::from_seed(i as u64).public_key())
355 .collect::<Ordered<_>>();
356
357 let (_, commitment, shares) =
359 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
360
361 let mut player = Player::<_, MinSig>::new(
363 contributors[0].clone(),
364 None,
365 contributors.clone(),
366 contributors.clone(),
367 1,
368 );
369
370 player
372 .share(
373 contributors[0].clone(),
374 commitment.clone(),
375 shares[0].clone(),
376 )
377 .unwrap();
378
379 let result = player.share(contributors[0].clone(), commitment, shares[0].clone());
381 assert!(matches!(result, Err(Error::DuplicateShare)));
382 }
383
384 #[test]
385 fn test_misdirected_share() {
386 let n = 5;
388 let mut rng = StdRng::seed_from_u64(0);
389
390 let contributors = (0..n)
392 .map(|i| PrivateKey::from_seed(i as u64).public_key())
393 .collect::<Ordered<_>>();
394
395 let (_, commitment, shares) =
397 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
398
399 let mut player = Player::<_, MinSig>::new(
401 contributors[0].clone(),
402 None,
403 contributors.clone(),
404 contributors.clone(),
405 1,
406 );
407
408 let result = player.share(
410 contributors[0].clone(),
411 commitment.clone(),
412 shares[1].clone(),
413 );
414 assert!(matches!(result, Err(Error::MisdirectedShare)));
415 }
416
417 #[test]
418 fn test_invalid_dealer() {
419 let n = 5;
421 let mut rng = StdRng::seed_from_u64(0);
422
423 let contributors = (0..n)
425 .map(|i| PrivateKey::from_seed(i as u64).public_key())
426 .collect::<Ordered<_>>();
427
428 let (_, commitment, shares) =
430 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
431
432 let mut player = Player::<_, MinSig>::new(
434 contributors[0].clone(),
435 None,
436 contributors.clone(),
437 contributors.clone(),
438 1,
439 );
440
441 let dealer = PrivateKey::from_seed(n as u64).public_key();
443 let result = player.share(dealer.clone(), commitment.clone(), shares[0].clone());
444 assert!(matches!(result, Err(Error::DealerInvalid)));
445
446 let mut arb =
448 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
449
450 let result = arb.commitment(dealer, commitment, vec![0, 1, 2, 3], Vec::new());
452 assert!(matches!(result, Err(Error::DealerInvalid)));
453 }
454
455 #[test]
456 fn test_invalid_commitment_degree() {
457 let n = 5;
459 let t = quorum(n);
460 let mut rng = StdRng::seed_from_u64(0);
461
462 let contributors = (0..n)
464 .map(|i| PrivateKey::from_seed(i as u64).public_key())
465 .collect::<Ordered<_>>();
466
467 let mut commitments = Vec::new();
469 let (public, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, 1);
470 commitments.push((public, shares));
471 let (public, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t - 1);
472 commitments.push((public, shares));
473 let (public, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t + 1);
474 commitments.push((public, shares));
475
476 for (public, shares) in commitments {
478 let mut player = Player::<_, MinSig>::new(
480 contributors[0].clone(),
481 None,
482 contributors.clone(),
483 contributors.clone(),
484 1,
485 );
486 let result = player.share(contributors[0].clone(), public.clone(), shares[0].clone());
487 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
488
489 let mut arb =
491 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
492 let result = arb.commitment(
493 contributors[0].clone(),
494 public,
495 vec![0, 1, 2, 3, 4],
496 Vec::new(),
497 );
498 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
499 }
500 }
501
502 #[test]
503 fn test_reveal() {
504 let n = 5;
506 let mut rng = StdRng::seed_from_u64(0);
507
508 let contributors = (0..n)
510 .map(|i| PrivateKey::from_seed(i as u64).public_key())
511 .collect::<Ordered<_>>();
512
513 let (_, commitment, shares) =
515 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
516
517 let mut arb =
519 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
520
521 arb.commitment(
523 contributors[0].clone(),
524 commitment,
525 vec![0, 1, 2, 3],
526 vec![shares[4].clone()],
527 )
528 .unwrap();
529 }
530
531 #[test]
532 fn test_arbiter_reveals() {
533 let n = 11;
535 let q = quorum(n as u32) as usize;
536 let mut rng = StdRng::seed_from_u64(0);
537
538 let contributors = (0..n)
540 .map(|i| PrivateKey::from_seed(i as u64).public_key())
541 .collect::<Ordered<_>>();
542
543 let mut arb =
545 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
546
547 let mut commitments = Vec::with_capacity(n);
549 let mut reveals = Vec::with_capacity(n);
550 for con in &contributors {
551 let (_, commitment, shares) =
553 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
554 commitments.push(commitment.clone());
555 reveals.push(shares[q].clone());
556
557 let acks: Vec<u32> = (0..q as u32).collect();
559 let reveals = shares[q..n].to_vec();
560 arb.commitment(con.clone(), commitment, acks, reveals)
561 .unwrap();
562 }
563
564 let (result, _) = arb.finalize();
566 let output = result.unwrap();
567
568 assert_eq!(output.commitments.len(), q);
570 for (dealer_idx, commitment) in commitments.iter().enumerate().take(q) {
571 let dealer_idx = dealer_idx as u32;
572 assert_eq!(output.commitments.get(&dealer_idx).unwrap(), commitment);
573 assert_eq!(
574 output.reveals.get(&dealer_idx).unwrap()[0],
575 reveals[dealer_idx as usize]
576 );
577 }
578 }
579
580 #[test]
581 fn test_duplicate_commitment() {
582 let n = 5;
584 let mut rng = StdRng::seed_from_u64(0);
585
586 let contributors = (0..n)
588 .map(|i| PrivateKey::from_seed(i as u64).public_key())
589 .collect::<Ordered<_>>();
590
591 let (_, commitment, shares) =
593 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
594
595 let mut arb =
597 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
598
599 arb.commitment(
601 contributors[0].clone(),
602 commitment.clone(),
603 vec![0, 1, 2, 3],
604 vec![shares[4].clone()],
605 )
606 .unwrap();
607
608 let result = arb.commitment(
610 contributors[0].clone(),
611 commitment,
612 vec![0, 1, 2, 3],
613 vec![shares[4].clone()],
614 );
615 assert!(matches!(result, Err(Error::DuplicateCommitment)));
616 }
617
618 #[test]
619 fn test_reveal_duplicate_player() {
620 let n = 5;
622 let mut rng = StdRng::seed_from_u64(0);
623
624 let contributors = (0..n)
626 .map(|i| PrivateKey::from_seed(i as u64).public_key())
627 .collect::<Ordered<_>>();
628
629 let (_, commitment, shares) =
631 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
632
633 let mut arb =
635 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
636
637 let result = arb.commitment(
639 contributors[0].clone(),
640 commitment,
641 vec![0, 1, 2, 3],
642 vec![shares[3].clone()],
643 );
644 assert!(matches!(result, Err(Error::AlreadyActive)));
645 }
646
647 #[test]
648 fn test_insufficient_active() {
649 let n = 5;
651 let mut rng = StdRng::seed_from_u64(0);
652
653 let contributors = (0..n)
655 .map(|i| PrivateKey::from_seed(i as u64).public_key())
656 .collect::<Ordered<_>>();
657
658 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
660
661 let mut arb =
663 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
664
665 let result = arb.commitment(
667 contributors[0].clone(),
668 commitment.clone(),
669 vec![0, 1, 2, 3],
670 Vec::new(),
671 );
672 assert!(matches!(result, Err(Error::IncorrectActive)));
673
674 let result = arb.commitment(
676 contributors[0].clone(),
677 commitment,
678 vec![0, 1, 2, 3, 4],
679 Vec::new(),
680 );
681 assert!(matches!(result, Err(Error::DealerDisqualified)));
682 }
683
684 #[test]
685 fn test_manual_disqualify() {
686 let n = 5;
688 let mut rng = StdRng::seed_from_u64(0);
689
690 let contributors = (0..n)
692 .map(|i| PrivateKey::from_seed(i as u64).public_key())
693 .collect::<Ordered<_>>();
694
695 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
697
698 let mut arb =
700 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
701
702 arb.disqualify(contributors[0].clone());
704
705 let result = arb.commitment(
707 contributors[0].clone(),
708 commitment,
709 vec![0, 1, 2, 3, 4],
710 Vec::new(),
711 );
712 assert!(matches!(result, Err(Error::DealerDisqualified)));
713 }
714
715 #[test]
716 fn test_too_many_reveals() {
717 let n = 5;
719 let mut rng = StdRng::seed_from_u64(0);
720
721 let contributors = (0..n)
723 .map(|i| PrivateKey::from_seed(i as u64).public_key())
724 .collect::<Ordered<_>>();
725
726 let (_, commitment, shares) =
728 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
729
730 let mut arb =
732 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
733
734 let result = arb.commitment(
736 contributors[0].clone(),
737 commitment,
738 vec![0, 1, 2],
739 vec![shares[3].clone(), shares[4].clone()],
740 );
741 assert!(matches!(result, Err(Error::TooManyReveals)));
742 }
743
744 #[test]
745 fn test_incorrect_reveal() {
746 let n = 5;
748 let mut rng = StdRng::seed_from_u64(0);
749
750 let contributors = (0..n)
752 .map(|i| PrivateKey::from_seed(i as u64).public_key())
753 .collect::<Ordered<_>>();
754
755 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
757
758 let t = quorum(n);
760 let (_, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
761
762 let mut arb =
764 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
765
766 let result = arb.commitment(
768 contributors[0].clone(),
769 commitment,
770 vec![0, 1, 2, 3],
771 vec![shares[4].clone()],
772 );
773 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
774 }
775
776 #[test]
777 fn test_reveal_corrupt_share() {
778 let n = 5;
780 let mut rng = StdRng::seed_from_u64(0);
781
782 let contributors = (0..n)
784 .map(|i| PrivateKey::from_seed(i as u64).public_key())
785 .collect::<Ordered<_>>();
786
787 let (_, commitment, shares) =
789 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
790
791 let mut arb =
793 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
794
795 let mut share = shares[3].clone();
797 share.index = 4;
798
799 let result = arb.commitment(
801 contributors[0].clone(),
802 commitment,
803 vec![0, 1, 2, 3],
804 vec![share],
805 );
806 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
807 }
808
809 #[test]
810 fn test_reveal_duplicate_ack() {
811 let n = 5;
813 let mut rng = StdRng::seed_from_u64(0);
814
815 let contributors = (0..n)
817 .map(|i| PrivateKey::from_seed(i as u64).public_key())
818 .collect::<Ordered<_>>();
819
820 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
822
823 let mut arb =
825 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
826
827 let result = arb.commitment(
829 contributors[0].clone(),
830 commitment,
831 vec![0, 1, 2, 2],
832 Vec::new(),
833 );
834 assert!(matches!(result, Err(Error::AlreadyActive)));
835 }
836
837 #[test]
838 fn test_reveal_invalid_ack() {
839 let n = 5;
841 let mut rng = StdRng::seed_from_u64(0);
842
843 let contributors = (0..n)
845 .map(|i| PrivateKey::from_seed(i as u64).public_key())
846 .collect::<Ordered<_>>();
847
848 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
850
851 let mut arb =
853 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
854
855 let result = arb.commitment(
857 contributors[0].clone(),
858 commitment,
859 vec![0, 1, 2, 10],
860 Vec::new(),
861 );
862 assert!(matches!(result, Err(Error::PlayerInvalid)));
863 }
864
865 #[test]
866 fn test_reveal_invalid_share() {
867 let n = 5;
869 let mut rng = StdRng::seed_from_u64(0);
870
871 let contributors = (0..n)
873 .map(|i| PrivateKey::from_seed(i as u64).public_key())
874 .collect::<Ordered<_>>();
875
876 let (_, commitment, shares) =
878 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
879
880 let mut arb =
882 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
883
884 let mut share = shares[3].clone();
886 share.index = 10;
887
888 let result = arb.commitment(
890 contributors[0].clone(),
891 commitment,
892 vec![0, 1, 2, 3],
893 vec![share],
894 );
895 assert!(matches!(result, Err(Error::PlayerInvalid)));
896 }
897
898 #[test]
899 fn test_dealer_acks() {
900 let n = 5;
902 let mut rng = StdRng::seed_from_u64(0);
903
904 let contributors = (0..n)
906 .map(|i| PrivateKey::from_seed(i as u64).public_key())
907 .collect::<Ordered<_>>();
908
909 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
911
912 for player in &contributors {
914 dealer.ack(player.clone()).unwrap();
915 }
916
917 let output = dealer.finalize().unwrap();
919 assert_eq!(Vec::from(output.active), vec![0, 1, 2, 3, 4]);
920 assert!(output.inactive.is_empty());
921 }
922
923 #[test]
924 fn test_dealer_inactive() {
925 let n = 5;
927 let mut rng = StdRng::seed_from_u64(0);
928
929 let contributors = (0..n)
931 .map(|i| PrivateKey::from_seed(i as u64).public_key())
932 .collect::<Ordered<_>>();
933
934 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
936
937 for player in contributors.iter().take(4) {
939 dealer.ack(player.clone()).unwrap();
940 }
941
942 let output = dealer.finalize().unwrap();
944 assert_eq!(Vec::from(output.active), vec![0, 1, 2, 3]);
945 assert_eq!(Vec::from(output.inactive), vec![4]);
946 }
947
948 #[test]
949 fn test_dealer_insufficient() {
950 let n = 5;
952 let mut rng = StdRng::seed_from_u64(0);
953
954 let contributors = (0..n)
956 .map(|i| PrivateKey::from_seed(i as u64).public_key())
957 .collect::<Ordered<_>>();
958
959 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
961
962 for player in contributors.iter().take(2) {
964 dealer.ack(player.clone()).unwrap();
965 }
966
967 assert!(dealer.finalize().is_none());
969 }
970
971 #[test]
972 fn test_dealer_duplicate_ack() {
973 let n = 5;
975 let mut rng = StdRng::seed_from_u64(0);
976
977 let contributors = (0..n)
979 .map(|i| PrivateKey::from_seed(i as u64).public_key())
980 .collect::<Ordered<_>>();
981
982 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
984
985 let player = contributors[0].clone();
987 dealer.ack(player.clone()).unwrap();
988
989 let result = dealer.ack(player);
991 assert!(matches!(result, Err(Error::DuplicateAck)));
992 }
993
994 #[test]
995 fn test_dealer_invalid_player() {
996 let n = 5;
998 let mut rng = StdRng::seed_from_u64(0);
999
1000 let contributors = (0..n)
1002 .map(|i| PrivateKey::from_seed(i as u64).public_key())
1003 .collect::<Ordered<_>>();
1004
1005 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1007
1008 let player = PrivateKey::from_seed(n as u64).public_key();
1010 let result = dealer.ack(player);
1011 assert!(matches!(result, Err(Error::PlayerInvalid)));
1012 }
1013
1014 #[test]
1015 fn test_player_reveals() {
1016 let n = 11;
1018 let q = quorum(n as u32) as usize;
1019 let mut rng = StdRng::seed_from_u64(0);
1020
1021 let contributors = (0..n)
1023 .map(|i| PrivateKey::from_seed(i as u64).public_key())
1024 .collect::<Ordered<_>>();
1025
1026 let mut player = Player::<_, MinSig>::new(
1028 contributors[0].clone(),
1029 None,
1030 contributors.clone(),
1031 contributors.clone(),
1032 1,
1033 );
1034
1035 let mut commitments = BTreeMap::new();
1037 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1038 let (_, commitment, shares) =
1039 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1040 player
1041 .share(con.clone(), commitment.clone(), shares[0].clone())
1042 .unwrap();
1043 commitments.insert(i as u32, commitment);
1044 }
1045
1046 let last = (q - 1) as u32;
1048 let (_, commitment, shares) =
1049 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1050 commitments.insert(last, commitment);
1051 let mut reveals = BTreeMap::new();
1052 reveals.insert(last, shares[0].clone());
1053 player.finalize(commitments, reveals).unwrap();
1054 }
1055
1056 #[test]
1057 fn test_player_missing_reveal() {
1058 let n = 11;
1060 let q = quorum(n as u32) as usize;
1061 let mut rng = StdRng::seed_from_u64(0);
1062
1063 let contributors = (0..n)
1065 .map(|i| PrivateKey::from_seed(i as u64).public_key())
1066 .collect::<Ordered<_>>();
1067
1068 let mut player = Player::<_, MinSig>::new(
1070 contributors[0].clone(),
1071 None,
1072 contributors.clone(),
1073 contributors.clone(),
1074 1,
1075 );
1076
1077 let mut commitments = BTreeMap::new();
1079 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1080 let (_, commitment, shares) =
1081 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1082 player
1083 .share(con.clone(), commitment.clone(), shares[0].clone())
1084 .unwrap();
1085 commitments.insert(i as u32, commitment);
1086 }
1087
1088 let last = (q - 1) as u32;
1090 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1091 commitments.insert(last, commitment);
1092 let result = player.finalize(commitments, BTreeMap::new());
1093 assert!(matches!(result, Err(Error::MissingShare)));
1094 }
1095
1096 #[test]
1097 fn test_player_insufficient_commitments() {
1098 let n = 5;
1100 let mut rng = StdRng::seed_from_u64(0);
1101
1102 let contributors = (0..n)
1104 .map(|i| PrivateKey::from_seed(i as u64).public_key())
1105 .collect::<Ordered<_>>();
1106
1107 let mut player = Player::<_, MinSig>::new(
1109 contributors[0].clone(),
1110 None,
1111 contributors.clone(),
1112 contributors.clone(),
1113 1,
1114 );
1115
1116 let mut commitments = BTreeMap::new();
1118 for (i, con) in contributors.iter().enumerate().take(2) {
1119 let (_, commitment, shares) =
1120 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1121 player
1122 .share(con.clone(), commitment.clone(), shares[0].clone())
1123 .unwrap();
1124 commitments.insert(i as u32, commitment);
1125 }
1126
1127 let result = player.finalize(commitments, BTreeMap::new());
1129 assert!(matches!(result, Err(Error::InvalidCommitments)));
1130 }
1131
1132 #[test]
1133 fn test_player_misdirected_reveal() {
1134 let n = 11;
1136 let q = quorum(n as u32) as usize;
1137 let mut rng = StdRng::seed_from_u64(0);
1138
1139 let contributors = (0..n)
1141 .map(|i| PrivateKey::from_seed(i as u64).public_key())
1142 .collect::<Ordered<_>>();
1143
1144 let mut player = Player::<_, MinSig>::new(
1146 contributors[0].clone(),
1147 None,
1148 contributors.clone(),
1149 contributors.clone(),
1150 1,
1151 );
1152
1153 let mut commitments = BTreeMap::new();
1155 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1156 let (_, commitment, shares) =
1157 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1158 player
1159 .share(con.clone(), commitment.clone(), shares[0].clone())
1160 .unwrap();
1161 commitments.insert(i as u32, commitment);
1162 }
1163
1164 let last = (q - 1) as u32;
1166 let (_, commitment, shares) =
1167 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1168 commitments.insert(last, commitment);
1169 let mut reveals = BTreeMap::new();
1170 reveals.insert(last, shares[1].clone());
1171 let result = player.finalize(commitments, reveals);
1172 assert!(matches!(result, Err(Error::MisdirectedShare)));
1173 }
1174
1175 #[test]
1176 fn test_player_invalid_commitment() {
1177 let n = 11;
1179 let q = quorum(n as u32) as usize;
1180 let mut rng = StdRng::seed_from_u64(0);
1181
1182 let contributors = (0..n)
1184 .map(|i| PrivateKey::from_seed(i as u64).public_key())
1185 .collect::<Ordered<_>>();
1186
1187 let mut player = Player::<_, MinSig>::new(
1189 contributors[0].clone(),
1190 None,
1191 contributors.clone(),
1192 contributors.clone(),
1193 1,
1194 );
1195
1196 let mut commitments = BTreeMap::new();
1198 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1199 let (_, commitment, shares) =
1200 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1201 player
1202 .share(con.clone(), commitment.clone(), shares[0].clone())
1203 .unwrap();
1204 commitments.insert(i as u32, commitment);
1205 }
1206
1207 let last = (q - 1) as u32;
1209 let (commitment, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n as u32, 1);
1210 commitments.insert(last, commitment);
1211 let mut reveals = BTreeMap::new();
1212 reveals.insert(last, shares[0].clone());
1213 let result = player.finalize(commitments, reveals);
1214 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
1215 }
1216
1217 #[test]
1218 fn test_player_invalid_reveal() {
1219 let n = 11;
1221 let q = quorum(n as u32) as usize;
1222 let mut rng = StdRng::seed_from_u64(0);
1223
1224 let contributors = (0..n)
1226 .map(|i| PrivateKey::from_seed(i as u64).public_key())
1227 .collect::<Ordered<_>>();
1228
1229 let mut player = Player::<_, MinSig>::new(
1231 contributors[0].clone(),
1232 None,
1233 contributors.clone(),
1234 contributors.clone(),
1235 1,
1236 );
1237
1238 let mut commitments = BTreeMap::new();
1240 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1241 let (_, commitment, shares) =
1242 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1243 player
1244 .share(con.clone(), commitment.clone(), shares[0].clone())
1245 .unwrap();
1246 commitments.insert(i as u32, commitment);
1247 }
1248
1249 let last = (q - 1) as u32;
1251 let (_, commitment, shares) =
1252 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1253 commitments.insert(last, commitment);
1254 let mut reveals = BTreeMap::new();
1255 let mut share = shares[1].clone();
1256 share.index = 0;
1257 reveals.insert(last, share);
1258 let result = player.finalize(commitments, reveals);
1259 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
1260 }
1261
1262 #[test]
1263 fn test_player_dealer_equivocation() {
1264 let n = 11;
1266 let q = quorum(n as u32) as usize;
1267 let mut rng = StdRng::seed_from_u64(0);
1268
1269 let contributors = (0..n)
1271 .map(|i| PrivateKey::from_seed(i as u64).public_key())
1272 .collect::<Ordered<_>>();
1273
1274 let mut player = Player::<_, MinSig>::new(
1276 contributors[0].clone(),
1277 None,
1278 contributors.clone(),
1279 contributors.clone(),
1280 1,
1281 );
1282
1283 let mut commitments = BTreeMap::new();
1285 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1286 let (_, commitment, shares) =
1287 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1288 player
1289 .share(con.clone(), commitment.clone(), shares[0].clone())
1290 .unwrap();
1291 commitments.insert(i as u32, commitment);
1292 }
1293
1294 let last = (q - 1) as u32;
1296 let (_, commitment, shares) =
1297 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1298 commitments.insert(last, commitment);
1299
1300 let mut public = poly::Public::<MinSig>::zero();
1302 for commitment in commitments.values() {
1303 public.add(commitment);
1304 }
1305
1306 let mut reveals = BTreeMap::new();
1308 reveals.insert(last, shares[0].clone());
1309 let result = player.finalize(commitments, reveals).unwrap();
1310 assert_eq!(result.public, public);
1311 }
1312
1313 #[test]
1314 fn test_player_dealer_equivocation_missing_reveal() {
1315 let n = 11;
1317 let q = quorum(n as u32) as usize;
1318 let mut rng = StdRng::seed_from_u64(0);
1319
1320 let contributors = (0..n)
1322 .map(|i| PrivateKey::from_seed(i as u64).public_key())
1323 .collect::<Ordered<_>>();
1324
1325 let mut player = Player::<_, MinSig>::new(
1327 contributors[0].clone(),
1328 None,
1329 contributors.clone(),
1330 contributors.clone(),
1331 1,
1332 );
1333
1334 let mut commitments = BTreeMap::new();
1336 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1337 let (_, commitment, shares) =
1338 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1339 player
1340 .share(con.clone(), commitment.clone(), shares[0].clone())
1341 .unwrap();
1342 commitments.insert(i as u32, commitment);
1343 }
1344
1345 let last = (q - 1) as u32;
1347 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1348 commitments.insert(last, commitment);
1349
1350 let result = player.finalize(commitments, BTreeMap::new());
1352 assert!(matches!(result, Err(Error::MissingShare)));
1353 }
1354
1355 #[derive(Clone)]
1357 struct Round {
1358 players: Vec<u64>,
1359 absent_dealers: Vec<u64>,
1360 absent_players: Vec<u64>,
1361 }
1362
1363 impl From<Vec<u64>> for Round {
1364 fn from(players: Vec<u64>) -> Self {
1365 Self {
1366 players,
1367 absent_dealers: Vec::new(),
1368 absent_players: Vec::new(),
1369 }
1370 }
1371 }
1372
1373 impl Round {
1374 fn with_absent_dealers(mut self, absent_dealers: Vec<u64>) -> Self {
1375 self.absent_dealers = absent_dealers;
1376 self
1377 }
1378
1379 fn with_absent_players(mut self, absent_players: Vec<u64>) -> Self {
1380 self.absent_players = absent_players;
1381 self
1382 }
1383 }
1384
1385 #[derive(Clone)]
1387 struct Plan {
1388 rounds: Vec<Round>,
1389 seed: u64,
1390 concurrency: usize,
1391 }
1392
1393 impl Plan {
1394 fn from(rounds: Vec<Round>) -> Self {
1395 Self {
1396 rounds,
1397 seed: 0,
1398 concurrency: 1,
1399 }
1400 }
1401
1402 fn with_concurrency(mut self, concurrency: usize) -> Self {
1403 self.concurrency = concurrency;
1404 self
1405 }
1406
1407 fn with_seed(mut self, seed: u64) -> Self {
1408 self.seed = seed;
1409 self
1410 }
1411
1412 fn run<V: Variant>(&self) -> V::Public {
1413 assert!(
1415 !self.rounds.is_empty(),
1416 "plan must contain at least one round"
1417 );
1418
1419 let mut rng = StdRng::seed_from_u64(self.seed);
1421 let mut current_public: Option<poly::Public<V>> = None;
1422 let mut participant_states: HashMap<PublicKey, player::Output<V>> = HashMap::new();
1423 let mut share_holders: Option<Ordered<PublicKey>> = None;
1424
1425 for (round_idx, round) in self.rounds.iter().enumerate() {
1427 assert!(
1429 !round.players.is_empty(),
1430 "round {round_idx} must include at least one player",
1431 );
1432 let player_set = participants(&round.players);
1433 let dealer_candidates = if let Some(ref registry) = share_holders {
1434 registry.clone()
1435 } else {
1436 player_set.clone()
1438 };
1439 assert!(
1440 !dealer_candidates.is_empty(),
1441 "round {round_idx} must have at least one dealer",
1442 );
1443
1444 let absent_dealers = participants(&round.absent_dealers);
1446 for absent in absent_dealers.iter() {
1447 assert!(
1448 dealer_candidates.position(absent).is_some(),
1449 "round {round_idx} absent dealer not in committee"
1450 );
1451 }
1452 let dealer_registry = if let Some(ref registry) = share_holders {
1453 for dealer in dealer_candidates.iter() {
1454 assert!(
1455 registry.position(dealer).is_some(),
1456 "round {round_idx} dealer not in previous committee",
1457 );
1458 }
1459 registry.clone()
1460 } else {
1461 dealer_candidates.clone()
1462 };
1463 let mut active_dealers = Vec::new();
1464 for dealer in dealer_candidates.iter() {
1465 if absent_dealers.position(dealer).is_some() {
1466 continue;
1467 }
1468 active_dealers.push(dealer.clone());
1469 }
1470 let active_len = active_dealers.len();
1471 let min_dealers = match current_public.as_ref() {
1472 None => quorum(player_set.len() as u32),
1473 Some(previous) => previous.required(),
1474 } as usize;
1475 assert!(
1476 active_len >= min_dealers,
1477 "round {} requires at least {} active dealers for {} players, got {}",
1478 round_idx,
1479 min_dealers,
1480 player_set.len(),
1481 active_len
1482 );
1483 let absent_players = participants(&round.absent_players);
1484 for absent in absent_players.iter() {
1485 assert!(
1486 player_set.position(absent).is_some(),
1487 "round {round_idx} absent player not in committee"
1488 );
1489 }
1490
1491 let mut dealers = BTreeMap::new();
1493 let mut dealer_outputs = BTreeMap::new();
1494 let mut expected_reveals = BTreeMap::new();
1495 let expected_inactive: Ordered<u32> = absent_players
1496 .iter()
1497 .map(|player_pk| player_set.position(player_pk).unwrap() as u32)
1498 .collect();
1499 for dealer_pk in active_dealers.iter() {
1500 let previous_share = participant_states
1501 .get(dealer_pk)
1502 .map(|out| out.share.clone());
1503 if current_public.is_some() && previous_share.is_none() {
1504 panic!("dealer missing share required for reshare in round {round_idx}",);
1505 }
1506
1507 let (dealer, commitment, shares) =
1508 Dealer::<_, V>::new(&mut rng, previous_share, player_set.clone());
1509 dealers.insert(dealer_pk.clone(), dealer);
1510 dealer_outputs.insert(dealer_pk.clone(), (commitment, shares));
1511 }
1512
1513 let mut players = BTreeMap::new();
1515 for player_pk in player_set.iter() {
1516 if absent_players.position(player_pk).is_some() {
1517 continue;
1518 }
1519 let player = Player::<_, V>::new(
1520 player_pk.clone(),
1521 current_public.clone(),
1522 dealer_registry.clone(),
1523 player_set.clone(),
1524 self.concurrency,
1525 );
1526 players.insert(player_pk.clone(), player);
1527 }
1528
1529 let mut arbiter = Arbiter::<_, V>::new(
1531 current_public.clone(),
1532 dealer_registry.clone(),
1533 player_set.clone(),
1534 self.concurrency,
1535 );
1536
1537 for dealer_pk in active_dealers.iter() {
1539 let (commitment, shares) = dealer_outputs
1540 .get(dealer_pk)
1541 .expect("missing dealer output");
1542 let commitment = commitment.clone();
1543 let shares = shares.clone();
1544 let mut dealer_reveals = Vec::new();
1545 {
1546 let dealer = dealers.get_mut(dealer_pk).expect("missing dealer instance");
1547 for (idx, player_pk) in player_set.iter().enumerate() {
1548 let share = shares[idx].clone();
1549 if absent_players.position(player_pk).is_some() {
1550 dealer_reveals.push(share);
1551 continue;
1552 }
1553 let player_obj = players
1554 .get_mut(player_pk)
1555 .expect("missing player for share delivery");
1556 if let Err(err) =
1557 player_obj.share(dealer_pk.clone(), commitment.clone(), share)
1558 {
1559 panic!(
1560 "failed to deliver share from dealer {dealer_pk:?} to player {player_pk:?}: {err:?}",
1561 );
1562 }
1563 dealer.ack(player_pk.clone()).unwrap();
1564 }
1565 }
1566
1567 let dealer = dealers
1568 .remove(dealer_pk)
1569 .expect("missing dealer instance after distribution");
1570 let dealer_output = dealer.finalize().expect("insufficient acknowledgements");
1571 assert_eq!(
1572 dealer_output.inactive, expected_inactive,
1573 "inactive set mismatch for dealer in round {round_idx}",
1574 );
1575 let dealer_pos = dealer_registry.position(dealer_pk).unwrap() as u32;
1576 if !dealer_reveals.is_empty() {
1577 expected_reveals.insert(dealer_pos, dealer_reveals.clone());
1578 }
1579 arbiter
1580 .commitment(
1581 dealer_pk.clone(),
1582 commitment,
1583 dealer_output.active.into(),
1584 dealer_reveals,
1585 )
1586 .unwrap();
1587 }
1588
1589 assert!(arbiter.ready(), "arbiter not ready in round {round_idx}");
1591 let (result, disqualified) = arbiter.finalize();
1592 let expected_disqualified =
1593 dealer_registry.len().saturating_sub(active_dealers.len());
1594 assert_eq!(
1595 disqualified.len(),
1596 expected_disqualified,
1597 "unexpected disqualified dealers in round {round_idx}",
1598 );
1599 let output = result.unwrap();
1600 for (&dealer_idx, _) in output.commitments.iter() {
1601 let expected = expected_reveals.remove(&dealer_idx).unwrap_or_default();
1602 match output.reveals.get(&dealer_idx) {
1603 Some(reveals) => assert_eq!(
1604 reveals, &expected,
1605 "unexpected reveal content for dealer {dealer_idx} in round {round_idx}",
1606 ),
1607 None => assert!(
1608 expected.is_empty(),
1609 "missing reveals for dealer {dealer_idx} in round {round_idx}",
1610 ),
1611 }
1612 }
1613 for dealer_idx in output.reveals.keys() {
1614 assert!(
1615 output.commitments.contains_key(dealer_idx),
1616 "reveals present for unselected dealer {dealer_idx} in round {round_idx}",
1617 );
1618 }
1619 let expected_commitments = quorum(dealer_registry.len() as u32) as usize;
1620 assert_eq!(
1621 output.commitments.len(),
1622 expected_commitments,
1623 "unexpected number of commitments in round {round_idx}",
1624 );
1625
1626 let mut round_results = Vec::new();
1628 let mut next_states = HashMap::new();
1629 for player_pk in player_set.iter() {
1630 if absent_players.position(player_pk).is_some() {
1631 continue;
1632 }
1633 let player_obj = players.remove(player_pk).unwrap();
1634 let result = player_obj
1635 .finalize(output.commitments.clone(), BTreeMap::new())
1636 .unwrap();
1637 assert_eq!(result.public, output.public);
1638 next_states.insert(player_pk.clone(), result.clone());
1639 round_results.push(result);
1640 }
1641 assert!(
1642 !round_results.is_empty(),
1643 "round {round_idx} produced no outputs",
1644 );
1645
1646 let public_key = public::<V>(&round_results[0].public);
1648 if let Some(previous) = current_public.as_ref() {
1649 assert_eq!(public_key, public::<V>(previous));
1650 }
1651
1652 let threshold = quorum(player_set.len() as u32);
1654 let partials = round_results
1655 .iter()
1656 .map(|res| partial_sign_proof_of_possession::<V>(&res.public, &res.share))
1657 .collect::<Vec<_>>();
1658 let signature = threshold_signature_recover::<V, _>(threshold, &partials)
1659 .expect("unable to recover threshold signature");
1660 verify_proof_of_possession::<V>(public_key, &signature)
1661 .expect("invalid proof of possession");
1662
1663 current_public = Some(round_results[0].public.clone());
1665 share_holders = Some(player_set);
1666 participant_states = next_states;
1667 }
1668
1669 *public::<V>(¤t_public.expect("plan must produce a public constant"))
1671 }
1672 }
1673
1674 fn participants(ids: &[u64]) -> Ordered<PublicKey> {
1676 ids.iter()
1677 .map(|id| PrivateKey::from_seed(*id).public_key())
1678 .collect::<Ordered<_>>()
1679 }
1680
1681 #[test]
1682 fn test_dkg() {
1683 let plan = Plan::from(vec![Round::from((0..5).collect::<Vec<_>>())]);
1684 plan.run::<MinPk>();
1685 plan.run::<MinSig>();
1686 }
1687
1688 #[test]
1689 fn test_dkg_with_absent_dealer() {
1690 let plan = Plan::from(vec![
1691 Round::from(vec![0, 1, 2, 3]).with_absent_dealers(vec![3])
1692 ]);
1693 plan.run::<MinPk>();
1694 plan.run::<MinSig>();
1695 }
1696
1697 #[test]
1698 fn test_dkg_with_absent_player() {
1699 let plan = Plan::from(vec![
1700 Round::from(vec![0, 1, 2, 3]).with_absent_players(vec![3])
1701 ]);
1702 plan.run::<MinPk>();
1703 plan.run::<MinSig>();
1704 }
1705
1706 #[test]
1707 fn test_dkg_determinism() {
1708 let plan_template = || Plan::from(vec![Round::from((0..5).collect::<Vec<_>>())]);
1709
1710 let public_a_pk = plan_template().with_seed(1).run::<MinPk>();
1711 assert_eq!(public_a_pk, plan_template().with_seed(1).run::<MinPk>());
1712 let public_b_pk = plan_template().with_seed(2).run::<MinPk>();
1713 assert_eq!(public_b_pk, plan_template().with_seed(2).run::<MinPk>());
1714 assert_ne!(public_a_pk, public_b_pk);
1715
1716 let public_a_sig = plan_template().with_seed(1).run::<MinSig>();
1717 assert_eq!(public_a_sig, plan_template().with_seed(1).run::<MinSig>());
1718 let public_b_sig = plan_template().with_seed(2).run::<MinSig>();
1719 assert_eq!(public_b_sig, plan_template().with_seed(2).run::<MinSig>());
1720 assert_ne!(public_a_sig, public_b_sig);
1721 }
1722
1723 #[test]
1724 fn test_reshare_distinct() {
1725 let plan = Plan::from(vec![
1726 Round::from((0..5).collect::<Vec<_>>()),
1727 Round::from((5..15).collect::<Vec<_>>()),
1728 Round::from((15..30).collect::<Vec<_>>()),
1729 ]);
1730 plan.run::<MinPk>();
1731 plan.run::<MinSig>();
1732 }
1733
1734 #[test]
1735 fn test_reshare_increasing_committee() {
1736 let plan = Plan::from(vec![
1737 Round::from(vec![0, 1, 2]),
1738 Round::from(vec![0, 1, 2, 3]),
1739 Round::from(vec![0, 1, 2, 3, 4]),
1740 Round::from(vec![0, 1, 2, 3, 4, 5]),
1741 ]);
1742 plan.run::<MinPk>();
1743 plan.run::<MinSig>();
1744 }
1745
1746 #[test]
1747 fn test_reshare_decreasing_committee() {
1748 let plan = Plan::from(vec![
1749 Round::from(vec![0, 1, 2, 3, 4, 5]),
1750 Round::from(vec![0, 1, 2, 3, 4]),
1751 Round::from(vec![0, 1, 2, 3]),
1752 Round::from(vec![0, 1, 2]),
1753 ]);
1754 plan.run::<MinPk>();
1755 plan.run::<MinSig>();
1756 }
1757
1758 #[test]
1759 fn test_reshare_with_absent_dealer() {
1760 let plan = Plan::from(vec![
1761 Round::from(vec![0, 1, 2, 3]),
1762 Round::from(vec![4, 5, 6, 7]).with_absent_dealers(vec![3]),
1763 ]);
1764 plan.run::<MinPk>();
1765 plan.run::<MinSig>();
1766 }
1767
1768 #[test]
1769 fn test_reshare_with_absent_player() {
1770 let plan = Plan::from(vec![
1771 Round::from(vec![0, 1, 2, 3]),
1772 Round::from(vec![4, 5, 6, 7]).with_absent_players(vec![4]),
1773 Round::from(vec![8, 9, 10, 11]).with_absent_dealers(vec![4]),
1774 ]);
1775 plan.run::<MinPk>();
1776 plan.run::<MinSig>();
1777 }
1778
1779 #[test]
1780 fn test_reshare_min_active() {
1781 let plan = Plan::from(vec![
1782 Round::from(vec![0, 1, 2, 3]).with_absent_players(vec![3]),
1783 Round::from(vec![4, 5, 6, 7]).with_absent_dealers(vec![3]),
1784 ]);
1785 plan.run::<MinPk>();
1786 plan.run::<MinSig>();
1787 }
1788
1789 #[test]
1790 fn test_reshare_min_active_different_sizes() {
1791 let plan = Plan::from(vec![
1792 Round::from(vec![0, 1, 2, 3]).with_absent_players(vec![3]),
1793 Round::from(vec![4, 5, 6, 7, 8, 9]).with_absent_dealers(vec![3]),
1794 ]);
1795 plan.run::<MinPk>();
1796 plan.run::<MinSig>();
1797 }
1798
1799 #[test]
1800 fn test_reshare_min_active_large() {
1801 let plan = Plan::from(vec![
1802 Round::from((0..20).collect::<Vec<_>>())
1803 .with_absent_dealers((14..20).collect::<Vec<_>>())
1804 .with_absent_players((14..20).collect::<Vec<_>>()),
1805 Round::from((100..200).collect::<Vec<_>>())
1806 .with_absent_dealers((14..20).collect::<Vec<_>>()),
1807 ])
1808 .with_concurrency(4);
1809 plan.run::<MinPk>();
1810 plan.run::<MinSig>();
1811 }
1812
1813 #[test]
1814 fn test_reshare_determinism() {
1815 let plan_template = || {
1816 Plan::from(vec![
1817 Round::from((0..5).collect::<Vec<_>>()),
1818 Round::from((5..10).collect::<Vec<_>>()),
1819 ])
1820 };
1821
1822 let public_a_pk = plan_template().with_seed(1).run::<MinPk>();
1823 assert_eq!(public_a_pk, plan_template().with_seed(1).run::<MinPk>());
1824 let public_b_pk = plan_template().with_seed(2).run::<MinPk>();
1825 assert_eq!(public_b_pk, plan_template().with_seed(2).run::<MinPk>());
1826 assert_ne!(public_a_pk, public_b_pk);
1827
1828 let public_a_sig = plan_template().with_seed(1).run::<MinSig>();
1829 assert_eq!(public_a_sig, plan_template().with_seed(1).run::<MinSig>());
1830 let public_b_sig = plan_template().with_seed(2).run::<MinSig>();
1831 assert_eq!(public_b_sig, plan_template().with_seed(2).run::<MinSig>());
1832 assert_ne!(public_a_sig, public_b_sig);
1833 }
1834}