1pub mod arbiter;
128pub use arbiter::Arbiter;
129pub mod dealer;
130pub use dealer::Dealer;
131pub mod ops;
132pub mod player;
133pub use player::Player;
134
135use thiserror::Error;
136
137#[derive(Error, Debug)]
138pub enum Error {
139 #[error("unexpected polynomial")]
140 UnexpectedPolynomial,
141 #[error("commitment has wrong degree")]
142 CommitmentWrongDegree,
143 #[error("misdirected share")]
144 MisdirectedShare,
145 #[error("share does not on commitment")]
146 ShareWrongCommitment,
147 #[error("insufficient dealings")]
148 InsufficientDealings,
149 #[error("reshare mismatch")]
150 ReshareMismatch,
151 #[error("share interpolation failed")]
152 ShareInterpolationFailed,
153 #[error("public key interpolation failed")]
154 PublicKeyInterpolationFailed,
155 #[error("dealer is invalid")]
156 DealerInvalid,
157 #[error("player invalid")]
158 PlayerInvalid,
159 #[error("missing share")]
160 MissingShare,
161 #[error("missing commitment")]
162 MissingCommitment,
163 #[error("too many commitments")]
164 TooManyCommitments,
165 #[error("duplicate commitment")]
166 DuplicateCommitment,
167 #[error("duplicate share")]
168 DuplicateShare,
169 #[error("duplicate ack")]
170 DuplicateAck,
171 #[error("mismatched commitment")]
172 MismatchedCommitment,
173 #[error("mismatched share")]
174 MismatchedShare,
175 #[error("too many reveals")]
176 TooManyReveals,
177 #[error("incorrect active")]
178 IncorrectActive,
179 #[error("already active")]
180 AlreadyActive,
181 #[error("invalid commitments")]
182 InvalidCommitments,
183 #[error("dealer disqualified")]
184 DealerDisqualified,
185}
186
187#[cfg(test)]
188mod tests {
189 use super::*;
190 use crate::bls12381::primitives::ops::{
191 partial_sign_proof_of_possession, threshold_signature_recover, verify_proof_of_possession,
192 };
193 use crate::bls12381::primitives::poly::public;
194 use crate::bls12381::primitives::variant::{MinPk, MinSig, Variant};
195 use crate::Signer as _;
196 use crate::{ed25519::PrivateKey, PrivateKeyExt as _};
197 use arbiter::Output;
198 use commonware_utils::quorum;
199 use rand::rngs::StdRng;
200 use rand::SeedableRng;
201 use std::collections::HashMap;
202
203 fn run_dkg_and_reshare<V: Variant>(
204 n_0: u32,
205 dealers_0: u32,
206 n_1: u32,
207 dealers_1: u32,
208 concurrency: usize,
209 ) {
210 let mut rng = StdRng::seed_from_u64(0);
212
213 let mut contributors = Vec::new();
215 for i in 0..n_0 {
216 let signer = PrivateKey::from_seed(i as u64).public_key();
217 contributors.push(signer);
218 }
219 contributors.sort();
220
221 let mut dealer_shares = HashMap::new();
223 let mut dealers = HashMap::new();
224 for con in contributors.iter().take(dealers_0 as usize) {
225 let (dealer, commitment, shares) =
226 Dealer::<_, V>::new(&mut rng, None, contributors.clone());
227 dealer_shares.insert(con.clone(), (commitment, shares));
228 dealers.insert(con.clone(), dealer);
229 }
230
231 let mut players = HashMap::new();
233 for con in &contributors {
234 let player = Player::<_, V>::new(
235 con.clone(),
236 None,
237 contributors.clone(),
238 contributors.clone(),
239 concurrency,
240 );
241 players.insert(con.clone(), player);
242 }
243
244 let mut arb = Arbiter::<_, V>::new(
246 None,
247 contributors.clone(),
248 contributors.clone(),
249 concurrency,
250 );
251
252 assert!(!arb.ready());
254
255 for (dealer, mut dealer_obj) in dealers {
257 let (commitment, shares) = dealer_shares.get(&dealer).unwrap().clone();
259 for (player_idx, player) in contributors.iter().enumerate() {
260 let player_obj = players.get_mut(player).unwrap();
262 player_obj
263 .share(
264 dealer.clone(),
265 commitment.clone(),
266 shares[player_idx].clone(),
267 )
268 .unwrap();
269
270 dealer_obj.ack(player.clone()).unwrap();
272 }
273
274 let output = dealer_obj.finalize().unwrap();
276
277 assert!(output.inactive.is_empty());
279
280 arb.commitment(dealer, commitment, output.active, Vec::new())
282 .unwrap();
283 }
284
285 assert!(arb.ready());
287
288 let (result, disqualified) = arb.finalize();
290
291 assert_eq!(disqualified.len(), (n_0 - dealers_0) as usize);
293
294 let output: Output<V> = result.unwrap();
296
297 let expected_commitments = quorum(n_0) as usize;
299 assert_eq!(output.commitments.len(), expected_commitments);
300
301 assert!(output.reveals.is_empty());
303
304 let mut outputs = HashMap::new();
306 for player in contributors.iter() {
307 let result = players
308 .remove(player)
309 .unwrap()
310 .finalize(output.commitments.clone(), HashMap::new())
311 .unwrap();
312 outputs.insert(player.clone(), result);
313 }
314
315 let t = quorum(n_0);
317 let partials = outputs
318 .values()
319 .map(|s| partial_sign_proof_of_possession::<V>(&s.public, &s.share))
320 .collect::<Vec<_>>();
321 let signature =
322 threshold_signature_recover::<V, _>(t, &partials).expect("unable to recover signature");
323 let public_key = public::<V>(&outputs.iter().next().unwrap().1.public);
324 verify_proof_of_possession::<V>(public_key, &signature)
325 .expect("invalid proof of possession");
326
327 let mut reshare_players = Vec::new();
329 for i in 0..n_1 {
330 let player = PrivateKey::from_seed((i + n_0) as u64).public_key();
331 reshare_players.push(player);
332 }
333 reshare_players.sort();
334
335 let mut reshare_shares = HashMap::new();
337 let mut reshare_dealers = HashMap::new();
338 for con in contributors.iter().take(dealers_1 as usize) {
339 let output = outputs.get(con).unwrap();
340 let (dealer, commitment, shares) = Dealer::<_, V>::new(
341 &mut rng,
342 Some(output.share.clone()),
343 reshare_players.clone(),
344 );
345 reshare_shares.insert(con.clone(), (commitment, shares));
346 reshare_dealers.insert(con.clone(), dealer);
347 }
348
349 let mut reshare_player_objs = HashMap::new();
351 for con in &reshare_players {
352 let player = Player::<_, V>::new(
353 con.clone(),
354 Some(output.public.clone()),
355 contributors.clone(),
356 reshare_players.clone(),
357 concurrency,
358 );
359 reshare_player_objs.insert(con.clone(), player);
360 }
361
362 let mut arb = Arbiter::<_, V>::new(
364 Some(output.public),
365 contributors.clone(),
366 reshare_players.clone(),
367 concurrency,
368 );
369
370 assert!(!arb.ready());
372
373 for (dealer, mut dealer_obj) in reshare_dealers {
375 let (commitment, shares) = reshare_shares.get(&dealer).unwrap().clone();
377 for (player_idx, player) in reshare_players.iter().enumerate() {
378 let player_obj = reshare_player_objs.get_mut(player).unwrap();
380 player_obj
381 .share(
382 dealer.clone(),
383 commitment.clone(),
384 shares[player_idx].clone(),
385 )
386 .unwrap();
387
388 dealer_obj.ack(player.clone()).unwrap();
390 }
391
392 let output = dealer_obj.finalize().unwrap();
394
395 assert!(output.inactive.is_empty());
397
398 arb.commitment(dealer, commitment, output.active, Vec::new())
400 .unwrap();
401 }
402
403 assert!(arb.ready());
405
406 let (result, disqualified) = arb.finalize();
408
409 assert_eq!(disqualified.len(), (n_0 - dealers_1) as usize);
411
412 let output: Output<V> = result.unwrap();
414
415 let expected_commitments = quorum(n_0) as usize;
417 assert_eq!(output.commitments.len(), expected_commitments);
418
419 assert!(output.reveals.is_empty());
421
422 let mut outputs = Vec::new();
424 for player in reshare_players.iter() {
425 let result = reshare_player_objs
426 .remove(player)
427 .unwrap()
428 .finalize(output.commitments.clone(), HashMap::new())
429 .unwrap();
430 assert_eq!(result.public, output.public);
431 outputs.push(result);
432 }
433
434 let t = quorum(n_1);
436 let partials = outputs
437 .iter()
438 .map(|s| partial_sign_proof_of_possession::<V>(&s.public, &s.share))
439 .collect::<Vec<_>>();
440 let signature =
441 threshold_signature_recover::<V, _>(t, &partials).expect("unable to recover signature");
442 let public_key = public::<V>(&outputs[0].public);
443 verify_proof_of_possession::<V>(public_key, &signature)
444 .expect("invalid proof of possession");
445 }
446
447 #[test]
448 fn test_dkg_and_reshare_all_active() {
449 run_dkg_and_reshare::<MinPk>(5, 5, 10, 5, 4);
450 run_dkg_and_reshare::<MinSig>(5, 5, 10, 5, 4);
451 }
452
453 #[test]
454 fn test_dkg_and_reshare_min_active() {
455 run_dkg_and_reshare::<MinPk>(4, 3, 4, 3, 4);
456 run_dkg_and_reshare::<MinSig>(4, 3, 4, 3, 4);
457 }
458
459 #[test]
460 fn test_dkg_and_reshare_min_active_different_sizes() {
461 run_dkg_and_reshare::<MinPk>(5, 4, 10, 4, 4);
462 run_dkg_and_reshare::<MinSig>(5, 4, 10, 4, 4);
463 }
464
465 #[test]
466 fn test_dkg_and_reshare_min_active_large() {
467 run_dkg_and_reshare::<MinPk>(20, 14, 100, 14, 4);
468 run_dkg_and_reshare::<MinSig>(20, 14, 100, 14, 4);
469 }
470
471 #[test]
472 #[should_panic]
473 fn test_dkg_and_reshare_insufficient_active() {
474 run_dkg_and_reshare::<MinPk>(5, 3, 10, 2, 4);
475 run_dkg_and_reshare::<MinSig>(5, 3, 10, 2, 4);
476 }
477
478 #[test]
479 fn test_invalid_commitment() {
480 let n = 5;
482 let mut rng = StdRng::seed_from_u64(0);
483
484 let mut contributors = Vec::new();
486 for i in 0..n {
487 let signer = PrivateKey::from_seed(i as u64).public_key();
488 contributors.push(signer);
489 }
490 contributors.sort();
491
492 let (_, _, shares) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
494
495 let t = quorum(n);
497 let (public, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
498
499 let mut player = Player::<_, MinSig>::new(
501 contributors[0].clone(),
502 None,
503 contributors.clone(),
504 contributors.clone(),
505 1,
506 );
507
508 let result = player.share(contributors[0].clone(), public, shares[0].clone());
510 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
511 }
512
513 #[test]
514 fn test_mismatched_commitment() {
515 let n = 5;
517 let mut rng = StdRng::seed_from_u64(0);
518
519 let mut contributors = Vec::new();
521 for i in 0..n {
522 let signer = PrivateKey::from_seed(i as u64).public_key();
523 contributors.push(signer);
524 }
525 contributors.sort();
526
527 let (_, commitment, shares) =
529 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
530
531 let t = quorum(n);
533 let (other_commitment, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
534
535 let mut player = Player::<_, MinSig>::new(
537 contributors[0].clone(),
538 None,
539 contributors.clone(),
540 contributors.clone(),
541 1,
542 );
543
544 player
546 .share(contributors[0].clone(), commitment, shares[0].clone())
547 .unwrap();
548
549 let result = player.share(contributors[0].clone(), other_commitment, shares[0].clone());
551 assert!(matches!(result, Err(Error::MismatchedCommitment)));
552 }
553
554 #[test]
555 fn test_mismatched_share() {
556 let n = 5;
558 let mut rng = StdRng::seed_from_u64(0);
559
560 let mut contributors = Vec::new();
562 for i in 0..n {
563 let signer = PrivateKey::from_seed(i as u64).public_key();
564 contributors.push(signer);
565 }
566 contributors.sort();
567
568 let (_, commitment, shares) =
570 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
571
572 let t = quorum(n);
574 let (_, other_shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
575
576 let mut player = Player::<_, MinSig>::new(
578 contributors[0].clone(),
579 None,
580 contributors.clone(),
581 contributors.clone(),
582 1,
583 );
584
585 player
587 .share(
588 contributors[0].clone(),
589 commitment.clone(),
590 shares[0].clone(),
591 )
592 .unwrap();
593
594 let result = player.share(contributors[0].clone(), commitment, other_shares[0].clone());
596 assert!(matches!(result, Err(Error::MismatchedShare)));
597 }
598
599 #[test]
600 fn test_duplicate_share() {
601 let n = 5;
603 let mut rng = StdRng::seed_from_u64(0);
604
605 let mut contributors = Vec::new();
607 for i in 0..n {
608 let signer = PrivateKey::from_seed(i as u64).public_key();
609 contributors.push(signer);
610 }
611 contributors.sort();
612
613 let (_, commitment, shares) =
615 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
616
617 let mut player = Player::<_, MinSig>::new(
619 contributors[0].clone(),
620 None,
621 contributors.clone(),
622 contributors.clone(),
623 1,
624 );
625
626 player
628 .share(
629 contributors[0].clone(),
630 commitment.clone(),
631 shares[0].clone(),
632 )
633 .unwrap();
634
635 let result = player.share(contributors[0].clone(), commitment, shares[0].clone());
637 assert!(matches!(result, Err(Error::DuplicateShare)));
638 }
639
640 #[test]
641 fn test_misdirected_share() {
642 let n = 5;
644 let mut rng = StdRng::seed_from_u64(0);
645
646 let mut contributors = Vec::new();
648 for i in 0..n {
649 let signer = PrivateKey::from_seed(i as u64).public_key();
650 contributors.push(signer);
651 }
652 contributors.sort();
653
654 let (_, commitment, shares) =
656 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
657
658 let mut player = Player::<_, MinSig>::new(
660 contributors[0].clone(),
661 None,
662 contributors.clone(),
663 contributors.clone(),
664 1,
665 );
666
667 let result = player.share(
669 contributors[0].clone(),
670 commitment.clone(),
671 shares[1].clone(),
672 );
673 assert!(matches!(result, Err(Error::MisdirectedShare)));
674 }
675
676 #[test]
677 fn test_invalid_dealer() {
678 let n = 5;
680 let mut rng = StdRng::seed_from_u64(0);
681
682 let mut contributors = Vec::new();
684 for i in 0..n {
685 let signer = PrivateKey::from_seed(i as u64).public_key();
686 contributors.push(signer);
687 }
688 contributors.sort();
689
690 let (_, commitment, shares) =
692 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
693
694 let mut player = Player::<_, MinSig>::new(
696 contributors[0].clone(),
697 None,
698 contributors.clone(),
699 contributors.clone(),
700 1,
701 );
702
703 let dealer = PrivateKey::from_seed(n as u64).public_key();
705 let result = player.share(dealer.clone(), commitment.clone(), shares[0].clone());
706 assert!(matches!(result, Err(Error::DealerInvalid)));
707
708 let mut arb =
710 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
711
712 let result = arb.commitment(dealer, commitment, vec![0, 1, 2, 3], Vec::new());
714 assert!(matches!(result, Err(Error::DealerInvalid)));
715 }
716
717 #[test]
718 fn test_invalid_commitment_degree() {
719 let n = 5;
721 let mut rng = StdRng::seed_from_u64(0);
722
723 let mut contributors = Vec::new();
725 for i in 0..n {
726 let signer = PrivateKey::from_seed(i as u64).public_key();
727 contributors.push(signer);
728 }
729 contributors.sort();
730
731 let (_, _, shares) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
733
734 let (public, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n * 2, 1);
736
737 let mut player = Player::<_, MinSig>::new(
739 contributors[0].clone(),
740 None,
741 contributors.clone(),
742 contributors.clone(),
743 1,
744 );
745
746 let result = player.share(contributors[0].clone(), public.clone(), shares[0].clone());
748 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
749
750 let mut arb =
752 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
753
754 let result = arb.commitment(
756 contributors[0].clone(),
757 public,
758 vec![0, 1, 2, 3, 4],
759 Vec::new(),
760 );
761 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
762 }
763
764 #[test]
765 fn test_reveal() {
766 let n = 5;
768 let mut rng = StdRng::seed_from_u64(0);
769
770 let mut contributors = Vec::new();
772 for i in 0..n {
773 let signer = PrivateKey::from_seed(i as u64).public_key();
774 contributors.push(signer);
775 }
776 contributors.sort();
777
778 let (_, commitment, shares) =
780 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
781
782 let mut arb =
784 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
785
786 arb.commitment(
788 contributors[0].clone(),
789 commitment,
790 vec![0, 1, 2, 3],
791 vec![shares[4].clone()],
792 )
793 .unwrap();
794 }
795
796 #[test]
797 fn test_arbiter_reveals() {
798 let n = 11;
800 let q = quorum(n as u32) as usize;
801 let mut rng = StdRng::seed_from_u64(0);
802
803 let mut contributors = Vec::new();
805 for i in 0..n {
806 let signer = PrivateKey::from_seed(i as u64).public_key();
807 contributors.push(signer);
808 }
809 contributors.sort();
810
811 let mut arb =
813 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
814
815 let mut commitments = Vec::with_capacity(n);
817 let mut reveals = Vec::with_capacity(n);
818 for con in &contributors {
819 let (_, commitment, shares) =
821 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
822 commitments.push(commitment.clone());
823 reveals.push(shares[q].clone());
824
825 let acks: Vec<u32> = (0..q as u32).collect();
827 let reveals = shares[q..n].to_vec();
828 arb.commitment(con.clone(), commitment, acks, reveals)
829 .unwrap();
830 }
831
832 let (result, _) = arb.finalize();
834 let output = result.unwrap();
835
836 assert_eq!(output.commitments.len(), q);
838 for (dealer_idx, commitment) in commitments.iter().enumerate().take(q) {
839 let dealer_idx = dealer_idx as u32;
840 assert_eq!(output.commitments.get(&dealer_idx).unwrap(), commitment);
841 assert_eq!(
842 output.reveals.get(&dealer_idx).unwrap()[0],
843 reveals[dealer_idx as usize]
844 );
845 }
846 }
847
848 #[test]
849 fn test_arbiter_best() {}
850
851 #[test]
852 fn test_duplicate_commitment() {
853 let n = 5;
855 let mut rng = StdRng::seed_from_u64(0);
856
857 let mut contributors = Vec::new();
859 for i in 0..n {
860 let signer = PrivateKey::from_seed(i as u64).public_key();
861 contributors.push(signer);
862 }
863 contributors.sort();
864
865 let (_, commitment, shares) =
867 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
868
869 let mut arb =
871 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
872
873 arb.commitment(
875 contributors[0].clone(),
876 commitment.clone(),
877 vec![0, 1, 2, 3],
878 vec![shares[4].clone()],
879 )
880 .unwrap();
881
882 let result = arb.commitment(
884 contributors[0].clone(),
885 commitment,
886 vec![0, 1, 2, 3],
887 vec![shares[4].clone()],
888 );
889 assert!(matches!(result, Err(Error::DuplicateCommitment)));
890 }
891
892 #[test]
893 fn test_reveal_duplicate_player() {
894 let n = 5;
896 let mut rng = StdRng::seed_from_u64(0);
897
898 let mut contributors = Vec::new();
900 for i in 0..n {
901 let signer = PrivateKey::from_seed(i as u64).public_key();
902 contributors.push(signer);
903 }
904 contributors.sort();
905
906 let (_, commitment, shares) =
908 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
909
910 let mut arb =
912 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
913
914 let result = arb.commitment(
916 contributors[0].clone(),
917 commitment,
918 vec![0, 1, 2, 3],
919 vec![shares[3].clone()],
920 );
921 assert!(matches!(result, Err(Error::AlreadyActive)));
922 }
923
924 #[test]
925 fn test_insufficient_active() {
926 let n = 5;
928 let mut rng = StdRng::seed_from_u64(0);
929
930 let mut contributors = Vec::new();
932 for i in 0..n {
933 let signer = PrivateKey::from_seed(i as u64).public_key();
934 contributors.push(signer);
935 }
936 contributors.sort();
937
938 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
940
941 let mut arb =
943 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
944
945 let result = arb.commitment(
947 contributors[0].clone(),
948 commitment.clone(),
949 vec![0, 1, 2, 3],
950 Vec::new(),
951 );
952 assert!(matches!(result, Err(Error::IncorrectActive)));
953
954 let result = arb.commitment(
956 contributors[0].clone(),
957 commitment,
958 vec![0, 1, 2, 3, 4],
959 Vec::new(),
960 );
961 assert!(matches!(result, Err(Error::DealerDisqualified)));
962 }
963
964 #[test]
965 fn test_manual_disqualify() {
966 let n = 5;
968 let mut rng = StdRng::seed_from_u64(0);
969
970 let mut contributors = Vec::new();
972 for i in 0..n {
973 let signer = PrivateKey::from_seed(i as u64).public_key();
974 contributors.push(signer);
975 }
976 contributors.sort();
977
978 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
980
981 let mut arb =
983 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
984
985 arb.disqualify(contributors[0].clone());
987
988 let result = arb.commitment(
990 contributors[0].clone(),
991 commitment,
992 vec![0, 1, 2, 3, 4],
993 Vec::new(),
994 );
995 assert!(matches!(result, Err(Error::DealerDisqualified)));
996 }
997
998 #[test]
999 fn test_too_many_reveals() {
1000 let n = 5;
1002 let mut rng = StdRng::seed_from_u64(0);
1003
1004 let mut contributors = Vec::new();
1006 for i in 0..n {
1007 let signer = PrivateKey::from_seed(i as u64).public_key();
1008 contributors.push(signer);
1009 }
1010 contributors.sort();
1011
1012 let (_, commitment, shares) =
1014 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1015
1016 let mut arb =
1018 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1019
1020 let result = arb.commitment(
1022 contributors[0].clone(),
1023 commitment,
1024 vec![0, 1, 2],
1025 vec![shares[3].clone(), shares[4].clone()],
1026 );
1027 assert!(matches!(result, Err(Error::TooManyReveals)));
1028 }
1029
1030 #[test]
1031 fn test_incorrect_reveal() {
1032 let n = 5;
1034 let mut rng = StdRng::seed_from_u64(0);
1035
1036 let mut contributors = Vec::new();
1038 for i in 0..n {
1039 let signer = PrivateKey::from_seed(i as u64).public_key();
1040 contributors.push(signer);
1041 }
1042 contributors.sort();
1043
1044 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1046
1047 let t = quorum(n);
1049 let (_, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
1050
1051 let mut arb =
1053 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1054
1055 let result = arb.commitment(
1057 contributors[0].clone(),
1058 commitment,
1059 vec![0, 1, 2, 3],
1060 vec![shares[4].clone()],
1061 );
1062 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
1063 }
1064
1065 #[test]
1066 fn test_reveal_corrupt_share() {
1067 let n = 5;
1069 let mut rng = StdRng::seed_from_u64(0);
1070
1071 let mut contributors = Vec::new();
1073 for i in 0..n {
1074 let signer = PrivateKey::from_seed(i as u64).public_key();
1075 contributors.push(signer);
1076 }
1077 contributors.sort();
1078
1079 let (_, commitment, shares) =
1081 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1082
1083 let mut arb =
1085 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1086
1087 let mut share = shares[3].clone();
1089 share.index = 4;
1090
1091 let result = arb.commitment(
1093 contributors[0].clone(),
1094 commitment,
1095 vec![0, 1, 2, 3],
1096 vec![share],
1097 );
1098 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
1099 }
1100
1101 #[test]
1102 fn test_reveal_duplicate_ack() {
1103 let n = 5;
1105 let mut rng = StdRng::seed_from_u64(0);
1106
1107 let mut contributors = Vec::new();
1109 for i in 0..n {
1110 let signer = PrivateKey::from_seed(i as u64).public_key();
1111 contributors.push(signer);
1112 }
1113 contributors.sort();
1114
1115 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1117
1118 let mut arb =
1120 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1121
1122 let result = arb.commitment(
1124 contributors[0].clone(),
1125 commitment,
1126 vec![0, 1, 2, 2],
1127 Vec::new(),
1128 );
1129 assert!(matches!(result, Err(Error::AlreadyActive)));
1130 }
1131
1132 #[test]
1133 fn test_reveal_invalid_ack() {
1134 let n = 5;
1136 let mut rng = StdRng::seed_from_u64(0);
1137
1138 let mut contributors = Vec::new();
1140 for i in 0..n {
1141 let signer = PrivateKey::from_seed(i as u64).public_key();
1142 contributors.push(signer);
1143 }
1144 contributors.sort();
1145
1146 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1148
1149 let mut arb =
1151 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1152
1153 let result = arb.commitment(
1155 contributors[0].clone(),
1156 commitment,
1157 vec![0, 1, 2, 10],
1158 Vec::new(),
1159 );
1160 assert!(matches!(result, Err(Error::PlayerInvalid)));
1161 }
1162
1163 #[test]
1164 fn test_reveal_invalid_share() {
1165 let n = 5;
1167 let mut rng = StdRng::seed_from_u64(0);
1168
1169 let mut contributors = Vec::new();
1171 for i in 0..n {
1172 let signer = PrivateKey::from_seed(i as u64).public_key();
1173 contributors.push(signer);
1174 }
1175 contributors.sort();
1176
1177 let (_, commitment, shares) =
1179 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1180
1181 let mut arb =
1183 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1184
1185 let mut share = shares[3].clone();
1187 share.index = 10;
1188
1189 let result = arb.commitment(
1191 contributors[0].clone(),
1192 commitment,
1193 vec![0, 1, 2, 3],
1194 vec![share],
1195 );
1196 assert!(matches!(result, Err(Error::PlayerInvalid)));
1197 }
1198
1199 #[test]
1200 fn test_dealer_acks() {
1201 let n = 5;
1203 let mut rng = StdRng::seed_from_u64(0);
1204
1205 let mut contributors = Vec::new();
1207 for i in 0..n {
1208 let signer = PrivateKey::from_seed(i as u64).public_key();
1209 contributors.push(signer);
1210 }
1211 contributors.sort();
1212
1213 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1215
1216 for player in &contributors {
1218 dealer.ack(player.clone()).unwrap();
1219 }
1220
1221 let output = dealer.finalize().unwrap();
1223 assert_eq!(output.active, vec![0, 1, 2, 3, 4]);
1224 assert!(output.inactive.is_empty());
1225 }
1226
1227 #[test]
1228 fn test_dealer_inactive() {
1229 let n = 5;
1231 let mut rng = StdRng::seed_from_u64(0);
1232
1233 let mut contributors = Vec::new();
1235 for i in 0..n {
1236 let signer = PrivateKey::from_seed(i as u64).public_key();
1237 contributors.push(signer);
1238 }
1239 contributors.sort();
1240
1241 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1243
1244 for player in contributors.iter().take(4) {
1246 dealer.ack(player.clone()).unwrap();
1247 }
1248
1249 let output = dealer.finalize().unwrap();
1251 assert_eq!(output.active, vec![0, 1, 2, 3]);
1252 assert_eq!(output.inactive, vec![4]);
1253 }
1254
1255 #[test]
1256 fn test_dealer_insufficient() {
1257 let n = 5;
1259 let mut rng = StdRng::seed_from_u64(0);
1260
1261 let mut contributors = Vec::new();
1263 for i in 0..n {
1264 let signer = PrivateKey::from_seed(i as u64).public_key();
1265 contributors.push(signer);
1266 }
1267 contributors.sort();
1268
1269 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1271
1272 for player in contributors.iter().take(2) {
1274 dealer.ack(player.clone()).unwrap();
1275 }
1276
1277 assert!(dealer.finalize().is_none());
1279 }
1280
1281 #[test]
1282 fn test_dealer_duplicate_ack() {
1283 let n = 5;
1285 let mut rng = StdRng::seed_from_u64(0);
1286
1287 let mut contributors = Vec::new();
1289 for i in 0..n {
1290 let signer = PrivateKey::from_seed(i as u64).public_key();
1291 contributors.push(signer);
1292 }
1293 contributors.sort();
1294
1295 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1297
1298 let player = contributors[0].clone();
1300 dealer.ack(player.clone()).unwrap();
1301
1302 let result = dealer.ack(player);
1304 assert!(matches!(result, Err(Error::DuplicateAck)));
1305 }
1306
1307 #[test]
1308 fn test_dealer_invalid_player() {
1309 let n = 5;
1311 let mut rng = StdRng::seed_from_u64(0);
1312
1313 let mut contributors = Vec::new();
1315 for i in 0..n {
1316 let signer = PrivateKey::from_seed(i as u64).public_key();
1317 contributors.push(signer);
1318 }
1319 contributors.sort();
1320
1321 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1323
1324 let player = PrivateKey::from_seed(n as u64).public_key();
1326 let result = dealer.ack(player);
1327 assert!(matches!(result, Err(Error::PlayerInvalid)));
1328 }
1329
1330 #[test]
1331 fn test_player_reveals() {
1332 let n = 11;
1334 let q = quorum(n as u32) as usize;
1335 let mut rng = StdRng::seed_from_u64(0);
1336
1337 let mut contributors = Vec::new();
1339 for i in 0..n {
1340 let signer = PrivateKey::from_seed(i as u64).public_key();
1341 contributors.push(signer);
1342 }
1343 contributors.sort();
1344
1345 let mut player = Player::<_, MinSig>::new(
1347 contributors[0].clone(),
1348 None,
1349 contributors.clone(),
1350 contributors.clone(),
1351 1,
1352 );
1353
1354 let mut commitments = HashMap::new();
1356 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1357 let (_, commitment, shares) =
1358 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1359 player
1360 .share(con.clone(), commitment.clone(), shares[0].clone())
1361 .unwrap();
1362 commitments.insert(i as u32, commitment);
1363 }
1364
1365 let last = (q - 1) as u32;
1367 let (_, commitment, shares) =
1368 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1369 commitments.insert(last, commitment);
1370 let mut reveals = HashMap::new();
1371 reveals.insert(last, shares[0].clone());
1372 player.finalize(commitments, reveals).unwrap();
1373 }
1374
1375 #[test]
1376 fn test_player_missing_reveal() {
1377 let n = 11;
1379 let q = quorum(n as u32) as usize;
1380 let mut rng = StdRng::seed_from_u64(0);
1381
1382 let mut contributors = Vec::new();
1384 for i in 0..n {
1385 let signer = PrivateKey::from_seed(i as u64).public_key();
1386 contributors.push(signer);
1387 }
1388 contributors.sort();
1389
1390 let mut player = Player::<_, MinSig>::new(
1392 contributors[0].clone(),
1393 None,
1394 contributors.clone(),
1395 contributors.clone(),
1396 1,
1397 );
1398
1399 let mut commitments = HashMap::new();
1401 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1402 let (_, commitment, shares) =
1403 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1404 player
1405 .share(con.clone(), commitment.clone(), shares[0].clone())
1406 .unwrap();
1407 commitments.insert(i as u32, commitment);
1408 }
1409
1410 let last = (q - 1) as u32;
1412 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1413 commitments.insert(last, commitment);
1414 let result = player.finalize(commitments, HashMap::new());
1415 assert!(matches!(result, Err(Error::MissingShare)));
1416 }
1417
1418 #[test]
1419 fn test_player_insufficient_commitments() {
1420 let n = 5;
1422 let mut rng = StdRng::seed_from_u64(0);
1423
1424 let mut contributors = Vec::new();
1426 for i in 0..n {
1427 let signer = PrivateKey::from_seed(i as u64).public_key();
1428 contributors.push(signer);
1429 }
1430 contributors.sort();
1431
1432 let mut player = Player::<_, MinSig>::new(
1434 contributors[0].clone(),
1435 None,
1436 contributors.clone(),
1437 contributors.clone(),
1438 1,
1439 );
1440
1441 let mut commitments = HashMap::new();
1443 for (i, con) in contributors.iter().enumerate().take(2) {
1444 let (_, commitment, shares) =
1445 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1446 player
1447 .share(con.clone(), commitment.clone(), shares[0].clone())
1448 .unwrap();
1449 commitments.insert(i as u32, commitment);
1450 }
1451
1452 let result = player.finalize(commitments, HashMap::new());
1454 assert!(matches!(result, Err(Error::InvalidCommitments)));
1455 }
1456
1457 #[test]
1458 fn test_player_misdirected_reveal() {
1459 let n = 11;
1461 let q = quorum(n as u32) as usize;
1462 let mut rng = StdRng::seed_from_u64(0);
1463
1464 let mut contributors = Vec::new();
1466 for i in 0..n {
1467 let signer = PrivateKey::from_seed(i as u64).public_key();
1468 contributors.push(signer);
1469 }
1470 contributors.sort();
1471
1472 let mut player = Player::<_, MinSig>::new(
1474 contributors[0].clone(),
1475 None,
1476 contributors.clone(),
1477 contributors.clone(),
1478 1,
1479 );
1480
1481 let mut commitments = HashMap::new();
1483 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1484 let (_, commitment, shares) =
1485 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1486 player
1487 .share(con.clone(), commitment.clone(), shares[0].clone())
1488 .unwrap();
1489 commitments.insert(i as u32, commitment);
1490 }
1491
1492 let last = (q - 1) as u32;
1494 let (_, commitment, shares) =
1495 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1496 commitments.insert(last, commitment);
1497 let mut reveals = HashMap::new();
1498 reveals.insert(last, shares[1].clone());
1499 let result = player.finalize(commitments, reveals);
1500 assert!(matches!(result, Err(Error::MisdirectedShare)));
1501 }
1502
1503 #[test]
1504 fn test_player_invalid_commitment() {
1505 let n = 11;
1507 let q = quorum(n as u32) as usize;
1508 let mut rng = StdRng::seed_from_u64(0);
1509
1510 let mut contributors = Vec::new();
1512 for i in 0..n {
1513 let signer = PrivateKey::from_seed(i as u64).public_key();
1514 contributors.push(signer);
1515 }
1516 contributors.sort();
1517
1518 let mut player = Player::<_, MinSig>::new(
1520 contributors[0].clone(),
1521 None,
1522 contributors.clone(),
1523 contributors.clone(),
1524 1,
1525 );
1526
1527 let mut commitments = HashMap::new();
1529 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1530 let (_, commitment, shares) =
1531 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1532 player
1533 .share(con.clone(), commitment.clone(), shares[0].clone())
1534 .unwrap();
1535 commitments.insert(i as u32, commitment);
1536 }
1537
1538 let last = (q - 1) as u32;
1540 let (commitment, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n as u32, 1);
1541 commitments.insert(last, commitment);
1542 let mut reveals = HashMap::new();
1543 reveals.insert(last, shares[0].clone());
1544 let result = player.finalize(commitments, reveals);
1545 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
1546 }
1547
1548 #[test]
1549 fn test_player_invalid_reveal() {
1550 let n = 11;
1552 let q = quorum(n as u32) as usize;
1553 let mut rng = StdRng::seed_from_u64(0);
1554
1555 let mut contributors = Vec::new();
1557 for i in 0..n {
1558 let signer = PrivateKey::from_seed(i as u64).public_key();
1559 contributors.push(signer);
1560 }
1561 contributors.sort();
1562
1563 let mut player = Player::<_, MinSig>::new(
1565 contributors[0].clone(),
1566 None,
1567 contributors.clone(),
1568 contributors.clone(),
1569 1,
1570 );
1571
1572 let mut commitments = HashMap::new();
1574 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1575 let (_, commitment, shares) =
1576 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1577 player
1578 .share(con.clone(), commitment.clone(), shares[0].clone())
1579 .unwrap();
1580 commitments.insert(i as u32, commitment);
1581 }
1582
1583 let last = (q - 1) as u32;
1585 let (_, commitment, shares) =
1586 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1587 commitments.insert(last, commitment);
1588 let mut reveals = HashMap::new();
1589 let mut share = shares[1].clone();
1590 share.index = 0;
1591 reveals.insert(last, share);
1592 let result = player.finalize(commitments, reveals);
1593 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
1594 }
1595}