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::{Ed25519, Signer};
195 use commonware_utils::quorum;
196 use rand::rngs::StdRng;
197 use rand::SeedableRng;
198 use std::collections::HashMap;
199
200 fn run_dkg_and_reshare(n_0: u32, dealers_0: u32, n_1: u32, dealers_1: u32, concurrency: usize) {
201 let mut rng = StdRng::seed_from_u64(0);
203
204 let mut contributors = Vec::new();
206 for i in 0..n_0 {
207 let signer = Ed25519::from_seed(i as u64).public_key();
208 contributors.push(signer);
209 }
210 contributors.sort();
211
212 let mut dealer_shares = HashMap::new();
214 let mut dealers = HashMap::new();
215 for con in contributors.iter().take(dealers_0 as usize) {
216 let (dealer, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
217 dealer_shares.insert(con.clone(), (commitment, shares));
218 dealers.insert(con.clone(), dealer);
219 }
220
221 let mut players = HashMap::new();
223 for con in &contributors {
224 let player = Player::new(
225 con.clone(),
226 None,
227 contributors.clone(),
228 contributors.clone(),
229 concurrency,
230 );
231 players.insert(con.clone(), player);
232 }
233
234 let mut arb = Arbiter::new(
236 None,
237 contributors.clone(),
238 contributors.clone(),
239 concurrency,
240 );
241
242 assert!(!arb.ready());
244
245 for (dealer, mut dealer_obj) in dealers {
247 let (commitment, shares) = dealer_shares.get(&dealer).unwrap().clone();
249 for (player_idx, player) in contributors.iter().enumerate() {
250 let player_obj = players.get_mut(player).unwrap();
252 player_obj
253 .share(
254 dealer.clone(),
255 commitment.clone(),
256 shares[player_idx].clone(),
257 )
258 .unwrap();
259
260 dealer_obj.ack(player.clone()).unwrap();
262 }
263
264 let output = dealer_obj.finalize().unwrap();
266
267 assert!(output.inactive.is_empty());
269
270 arb.commitment(dealer, commitment, output.active, Vec::new())
272 .unwrap();
273 }
274
275 assert!(arb.ready());
277
278 let (result, disqualified) = arb.finalize();
280
281 assert_eq!(disqualified.len(), (n_0 - dealers_0) as usize);
283
284 let output = result.unwrap();
286
287 let expected_commitments = quorum(n_0) as usize;
289 assert_eq!(output.commitments.len(), expected_commitments);
290
291 assert!(output.reveals.is_empty());
293
294 let mut outputs = HashMap::new();
296 for player in contributors.iter() {
297 let result = players
298 .remove(player)
299 .unwrap()
300 .finalize(output.commitments.clone(), HashMap::new())
301 .unwrap();
302 outputs.insert(player.clone(), result);
303 }
304
305 let t = quorum(n_0);
307 let partials = outputs
308 .values()
309 .map(|s| partial_sign_proof_of_possession(&s.public, &s.share))
310 .collect::<Vec<_>>();
311 let signature =
312 threshold_signature_recover(t, &partials).expect("unable to recover signature");
313 let public_key = public(&outputs.iter().next().unwrap().1.public);
314 verify_proof_of_possession(public_key, &signature).expect("invalid proof of possession");
315
316 let mut reshare_players = Vec::new();
318 for i in 0..n_1 {
319 let player = Ed25519::from_seed((i + n_0) as u64).public_key();
320 reshare_players.push(player);
321 }
322 reshare_players.sort();
323
324 let mut reshare_shares = HashMap::new();
326 let mut reshare_dealers = HashMap::new();
327 for con in contributors.iter().take(dealers_1 as usize) {
328 let output = outputs.get(con).unwrap();
329 let (dealer, commitment, shares) = Dealer::new(
330 &mut rng,
331 Some(output.share.clone()),
332 reshare_players.clone(),
333 );
334 reshare_shares.insert(con.clone(), (commitment, shares));
335 reshare_dealers.insert(con.clone(), dealer);
336 }
337
338 let mut reshare_player_objs = HashMap::new();
340 for con in &reshare_players {
341 let player = Player::new(
342 con.clone(),
343 Some(output.public.clone()),
344 contributors.clone(),
345 reshare_players.clone(),
346 concurrency,
347 );
348 reshare_player_objs.insert(con.clone(), player);
349 }
350
351 let mut arb = Arbiter::new(
353 Some(output.public),
354 contributors.clone(),
355 reshare_players.clone(),
356 concurrency,
357 );
358
359 assert!(!arb.ready());
361
362 for (dealer, mut dealer_obj) in reshare_dealers {
364 let (commitment, shares) = reshare_shares.get(&dealer).unwrap().clone();
366 for (player_idx, player) in reshare_players.iter().enumerate() {
367 let player_obj = reshare_player_objs.get_mut(player).unwrap();
369 player_obj
370 .share(
371 dealer.clone(),
372 commitment.clone(),
373 shares[player_idx].clone(),
374 )
375 .unwrap();
376
377 dealer_obj.ack(player.clone()).unwrap();
379 }
380
381 let output = dealer_obj.finalize().unwrap();
383
384 assert!(output.inactive.is_empty());
386
387 arb.commitment(dealer, commitment, output.active, Vec::new())
389 .unwrap();
390 }
391
392 assert!(arb.ready());
394
395 let (result, disqualified) = arb.finalize();
397
398 assert_eq!(disqualified.len(), (n_0 - dealers_1) as usize);
400
401 let output = result.unwrap();
403
404 let expected_commitments = quorum(n_0) as usize;
406 assert_eq!(output.commitments.len(), expected_commitments);
407
408 assert!(output.reveals.is_empty());
410
411 let mut outputs = Vec::new();
413 for player in reshare_players.iter() {
414 let result = reshare_player_objs
415 .remove(player)
416 .unwrap()
417 .finalize(output.commitments.clone(), HashMap::new())
418 .unwrap();
419 assert_eq!(result.public, output.public);
420 outputs.push(result);
421 }
422
423 let t = quorum(n_1);
425 let partials = outputs
426 .iter()
427 .map(|s| partial_sign_proof_of_possession(&s.public, &s.share))
428 .collect::<Vec<_>>();
429 let signature =
430 threshold_signature_recover(t, &partials).expect("unable to recover signature");
431 let public_key = public(&outputs[0].public);
432 verify_proof_of_possession(public_key, &signature).expect("invalid proof of possession");
433 }
434
435 #[test]
436 fn test_dkg_and_reshare_all_active() {
437 run_dkg_and_reshare(5, 5, 10, 5, 4);
438 }
439
440 #[test]
441 fn test_dkg_and_reshare_min_active() {
442 run_dkg_and_reshare(4, 3, 4, 3, 4);
443 }
444
445 #[test]
446 fn test_dkg_and_reshare_min_active_different_sizes() {
447 run_dkg_and_reshare(5, 4, 10, 4, 4);
448 }
449
450 #[test]
451 fn test_dkg_and_reshare_min_active_large() {
452 run_dkg_and_reshare(20, 14, 100, 14, 4);
453 }
454
455 #[test]
456 #[should_panic]
457 fn test_dkg_and_reshare_insufficient_active() {
458 run_dkg_and_reshare(5, 3, 10, 2, 4);
459 }
460
461 #[test]
462 fn test_invalid_commitment() {
463 let n = 5;
465 let mut rng = StdRng::seed_from_u64(0);
466
467 let mut contributors = Vec::new();
469 for i in 0..n {
470 let signer = Ed25519::from_seed(i as u64).public_key();
471 contributors.push(signer);
472 }
473 contributors.sort();
474
475 let (_, _, shares) = Dealer::new(&mut rng, None, contributors.clone());
477
478 let t = quorum(n);
480 let (public, _) = ops::generate_shares(&mut rng, None, n, t);
481
482 let mut player = Player::new(
484 contributors[0].clone(),
485 None,
486 contributors.clone(),
487 contributors.clone(),
488 1,
489 );
490
491 let result = player.share(contributors[0].clone(), public, shares[0].clone());
493 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
494 }
495
496 #[test]
497 fn test_mismatched_commitment() {
498 let n = 5;
500 let mut rng = StdRng::seed_from_u64(0);
501
502 let mut contributors = Vec::new();
504 for i in 0..n {
505 let signer = Ed25519::from_seed(i as u64).public_key();
506 contributors.push(signer);
507 }
508 contributors.sort();
509
510 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
512
513 let t = quorum(n);
515 let (other_commitment, _) = ops::generate_shares(&mut rng, None, n, t);
516
517 let mut player = Player::new(
519 contributors[0].clone(),
520 None,
521 contributors.clone(),
522 contributors.clone(),
523 1,
524 );
525
526 player
528 .share(contributors[0].clone(), commitment, shares[0].clone())
529 .unwrap();
530
531 let result = player.share(contributors[0].clone(), other_commitment, shares[0].clone());
533 assert!(matches!(result, Err(Error::MismatchedCommitment)));
534 }
535
536 #[test]
537 fn test_mismatched_share() {
538 let n = 5;
540 let mut rng = StdRng::seed_from_u64(0);
541
542 let mut contributors = Vec::new();
544 for i in 0..n {
545 let signer = Ed25519::from_seed(i as u64).public_key();
546 contributors.push(signer);
547 }
548 contributors.sort();
549
550 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
552
553 let t = quorum(n);
555 let (_, other_shares) = ops::generate_shares(&mut rng, None, n, t);
556
557 let mut player = Player::new(
559 contributors[0].clone(),
560 None,
561 contributors.clone(),
562 contributors.clone(),
563 1,
564 );
565
566 player
568 .share(
569 contributors[0].clone(),
570 commitment.clone(),
571 shares[0].clone(),
572 )
573 .unwrap();
574
575 let result = player.share(contributors[0].clone(), commitment, other_shares[0].clone());
577 assert!(matches!(result, Err(Error::MismatchedShare)));
578 }
579
580 #[test]
581 fn test_duplicate_share() {
582 let n = 5;
584 let mut rng = StdRng::seed_from_u64(0);
585
586 let mut contributors = Vec::new();
588 for i in 0..n {
589 let signer = Ed25519::from_seed(i as u64).public_key();
590 contributors.push(signer);
591 }
592 contributors.sort();
593
594 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
596
597 let mut player = Player::new(
599 contributors[0].clone(),
600 None,
601 contributors.clone(),
602 contributors.clone(),
603 1,
604 );
605
606 player
608 .share(
609 contributors[0].clone(),
610 commitment.clone(),
611 shares[0].clone(),
612 )
613 .unwrap();
614
615 let result = player.share(contributors[0].clone(), commitment, shares[0].clone());
617 assert!(matches!(result, Err(Error::DuplicateShare)));
618 }
619
620 #[test]
621 fn test_misdirected_share() {
622 let n = 5;
624 let mut rng = StdRng::seed_from_u64(0);
625
626 let mut contributors = Vec::new();
628 for i in 0..n {
629 let signer = Ed25519::from_seed(i as u64).public_key();
630 contributors.push(signer);
631 }
632 contributors.sort();
633
634 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
636
637 let mut player = Player::new(
639 contributors[0].clone(),
640 None,
641 contributors.clone(),
642 contributors.clone(),
643 1,
644 );
645
646 let result = player.share(
648 contributors[0].clone(),
649 commitment.clone(),
650 shares[1].clone(),
651 );
652 assert!(matches!(result, Err(Error::MisdirectedShare)));
653 }
654
655 #[test]
656 fn test_invalid_dealer() {
657 let n = 5;
659 let mut rng = StdRng::seed_from_u64(0);
660
661 let mut contributors = Vec::new();
663 for i in 0..n {
664 let signer = Ed25519::from_seed(i as u64).public_key();
665 contributors.push(signer);
666 }
667 contributors.sort();
668
669 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
671
672 let mut player = Player::new(
674 contributors[0].clone(),
675 None,
676 contributors.clone(),
677 contributors.clone(),
678 1,
679 );
680
681 let dealer = Ed25519::from_seed(n as u64).public_key();
683 let result = player.share(dealer.clone(), commitment.clone(), shares[0].clone());
684 assert!(matches!(result, Err(Error::DealerInvalid)));
685
686 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
688
689 let result = arb.commitment(dealer, commitment, vec![0, 1, 2, 3], Vec::new());
691 assert!(matches!(result, Err(Error::DealerInvalid)));
692 }
693
694 #[test]
695 fn test_invalid_commitment_degree() {
696 let n = 5;
698 let mut rng = StdRng::seed_from_u64(0);
699
700 let mut contributors = Vec::new();
702 for i in 0..n {
703 let signer = Ed25519::from_seed(i as u64).public_key();
704 contributors.push(signer);
705 }
706 contributors.sort();
707
708 let (_, _, shares) = Dealer::new(&mut rng, None, contributors.clone());
710
711 let (public, _) = ops::generate_shares(&mut rng, None, n * 2, 1);
713
714 let mut player = Player::new(
716 contributors[0].clone(),
717 None,
718 contributors.clone(),
719 contributors.clone(),
720 1,
721 );
722
723 let result = player.share(contributors[0].clone(), public.clone(), shares[0].clone());
725 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
726
727 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
729
730 let result = arb.commitment(
732 contributors[0].clone(),
733 public,
734 vec![0, 1, 2, 3, 4],
735 Vec::new(),
736 );
737 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
738 }
739
740 #[test]
741 fn test_reveal() {
742 let n = 5;
744 let mut rng = StdRng::seed_from_u64(0);
745
746 let mut contributors = Vec::new();
748 for i in 0..n {
749 let signer = Ed25519::from_seed(i as u64).public_key();
750 contributors.push(signer);
751 }
752 contributors.sort();
753
754 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
756
757 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
759
760 arb.commitment(
762 contributors[0].clone(),
763 commitment,
764 vec![0, 1, 2, 3],
765 vec![shares[4].clone()],
766 )
767 .unwrap();
768 }
769
770 #[test]
771 fn test_arbiter_reveals() {
772 let n = 11;
774 let q = quorum(n as u32) as usize;
775 let mut rng = StdRng::seed_from_u64(0);
776
777 let mut contributors = Vec::new();
779 for i in 0..n {
780 let signer = Ed25519::from_seed(i as u64).public_key();
781 contributors.push(signer);
782 }
783 contributors.sort();
784
785 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
787
788 let mut commitments = Vec::with_capacity(n);
790 let mut reveals = Vec::with_capacity(n);
791 for con in &contributors {
792 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
794 commitments.push(commitment.clone());
795 reveals.push(shares[q].clone());
796
797 let acks: Vec<u32> = (0..q as u32).collect();
799 let reveals = shares[q..n].to_vec();
800 arb.commitment(con.clone(), commitment, acks, reveals)
801 .unwrap();
802 }
803
804 let (result, _) = arb.finalize();
806 let output = result.unwrap();
807
808 assert_eq!(output.commitments.len(), q);
810 for (dealer_idx, commitment) in commitments.iter().enumerate().take(q) {
811 let dealer_idx = dealer_idx as u32;
812 assert_eq!(output.commitments.get(&dealer_idx).unwrap(), commitment);
813 assert_eq!(
814 output.reveals.get(&dealer_idx).unwrap()[0],
815 reveals[dealer_idx as usize]
816 );
817 }
818 }
819
820 #[test]
821 fn test_arbiter_best() {}
822
823 #[test]
824 fn test_duplicate_commitment() {
825 let n = 5;
827 let mut rng = StdRng::seed_from_u64(0);
828
829 let mut contributors = Vec::new();
831 for i in 0..n {
832 let signer = Ed25519::from_seed(i as u64).public_key();
833 contributors.push(signer);
834 }
835 contributors.sort();
836
837 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
839
840 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
842
843 arb.commitment(
845 contributors[0].clone(),
846 commitment.clone(),
847 vec![0, 1, 2, 3],
848 vec![shares[4].clone()],
849 )
850 .unwrap();
851
852 let result = arb.commitment(
854 contributors[0].clone(),
855 commitment,
856 vec![0, 1, 2, 3],
857 vec![shares[4].clone()],
858 );
859 assert!(matches!(result, Err(Error::DuplicateCommitment)));
860 }
861
862 #[test]
863 fn test_reveal_duplicate_player() {
864 let n = 5;
866 let mut rng = StdRng::seed_from_u64(0);
867
868 let mut contributors = Vec::new();
870 for i in 0..n {
871 let signer = Ed25519::from_seed(i as u64).public_key();
872 contributors.push(signer);
873 }
874 contributors.sort();
875
876 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
878
879 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
881
882 let result = arb.commitment(
884 contributors[0].clone(),
885 commitment,
886 vec![0, 1, 2, 3],
887 vec![shares[3].clone()],
888 );
889 assert!(matches!(result, Err(Error::AlreadyActive)));
890 }
891
892 #[test]
893 fn test_insufficient_active() {
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 = Ed25519::from_seed(i as u64).public_key();
902 contributors.push(signer);
903 }
904 contributors.sort();
905
906 let (_, commitment, _) = Dealer::new(&mut rng, None, contributors.clone());
908
909 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
911
912 let result = arb.commitment(
914 contributors[0].clone(),
915 commitment.clone(),
916 vec![0, 1, 2, 3],
917 Vec::new(),
918 );
919 assert!(matches!(result, Err(Error::IncorrectActive)));
920
921 let result = arb.commitment(
923 contributors[0].clone(),
924 commitment,
925 vec![0, 1, 2, 3, 4],
926 Vec::new(),
927 );
928 assert!(matches!(result, Err(Error::DealerDisqualified)));
929 }
930
931 #[test]
932 fn test_manual_disqualify() {
933 let n = 5;
935 let mut rng = StdRng::seed_from_u64(0);
936
937 let mut contributors = Vec::new();
939 for i in 0..n {
940 let signer = Ed25519::from_seed(i as u64).public_key();
941 contributors.push(signer);
942 }
943 contributors.sort();
944
945 let (_, commitment, _) = Dealer::new(&mut rng, None, contributors.clone());
947
948 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
950
951 arb.disqualify(contributors[0].clone());
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_too_many_reveals() {
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 = Ed25519::from_seed(i as u64).public_key();
974 contributors.push(signer);
975 }
976 contributors.sort();
977
978 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
980
981 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
983
984 let result = arb.commitment(
986 contributors[0].clone(),
987 commitment,
988 vec![0, 1, 2],
989 vec![shares[3].clone(), shares[4].clone()],
990 );
991 assert!(matches!(result, Err(Error::TooManyReveals)));
992 }
993
994 #[test]
995 fn test_incorrect_reveal() {
996 let n = 5;
998 let mut rng = StdRng::seed_from_u64(0);
999
1000 let mut contributors = Vec::new();
1002 for i in 0..n {
1003 let signer = Ed25519::from_seed(i as u64).public_key();
1004 contributors.push(signer);
1005 }
1006 contributors.sort();
1007
1008 let (_, commitment, _) = Dealer::new(&mut rng, None, contributors.clone());
1010
1011 let t = quorum(n);
1013 let (_, shares) = ops::generate_shares(&mut rng, None, n, t);
1014
1015 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
1017
1018 let result = arb.commitment(
1020 contributors[0].clone(),
1021 commitment,
1022 vec![0, 1, 2, 3],
1023 vec![shares[4].clone()],
1024 );
1025 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
1026 }
1027
1028 #[test]
1029 fn test_reveal_corrupt_share() {
1030 let n = 5;
1032 let mut rng = StdRng::seed_from_u64(0);
1033
1034 let mut contributors = Vec::new();
1036 for i in 0..n {
1037 let signer = Ed25519::from_seed(i as u64).public_key();
1038 contributors.push(signer);
1039 }
1040 contributors.sort();
1041
1042 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
1044
1045 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
1047
1048 let mut share = shares[3].clone();
1050 share.index = 4;
1051
1052 let result = arb.commitment(
1054 contributors[0].clone(),
1055 commitment,
1056 vec![0, 1, 2, 3],
1057 vec![share],
1058 );
1059 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
1060 }
1061
1062 #[test]
1063 fn test_reveal_duplicate_ack() {
1064 let n = 5;
1066 let mut rng = StdRng::seed_from_u64(0);
1067
1068 let mut contributors = Vec::new();
1070 for i in 0..n {
1071 let signer = Ed25519::from_seed(i as u64).public_key();
1072 contributors.push(signer);
1073 }
1074 contributors.sort();
1075
1076 let (_, commitment, _) = Dealer::new(&mut rng, None, contributors.clone());
1078
1079 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
1081
1082 let result = arb.commitment(
1084 contributors[0].clone(),
1085 commitment,
1086 vec![0, 1, 2, 2],
1087 Vec::new(),
1088 );
1089 assert!(matches!(result, Err(Error::AlreadyActive)));
1090 }
1091
1092 #[test]
1093 fn test_reveal_invalid_ack() {
1094 let n = 5;
1096 let mut rng = StdRng::seed_from_u64(0);
1097
1098 let mut contributors = Vec::new();
1100 for i in 0..n {
1101 let signer = Ed25519::from_seed(i as u64).public_key();
1102 contributors.push(signer);
1103 }
1104 contributors.sort();
1105
1106 let (_, commitment, _) = Dealer::new(&mut rng, None, contributors.clone());
1108
1109 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
1111
1112 let result = arb.commitment(
1114 contributors[0].clone(),
1115 commitment,
1116 vec![0, 1, 2, 10],
1117 Vec::new(),
1118 );
1119 assert!(matches!(result, Err(Error::PlayerInvalid)));
1120 }
1121
1122 #[test]
1123 fn test_reveal_invalid_share() {
1124 let n = 5;
1126 let mut rng = StdRng::seed_from_u64(0);
1127
1128 let mut contributors = Vec::new();
1130 for i in 0..n {
1131 let signer = Ed25519::from_seed(i as u64).public_key();
1132 contributors.push(signer);
1133 }
1134 contributors.sort();
1135
1136 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
1138
1139 let mut arb = Arbiter::new(None, contributors.clone(), contributors.clone(), 1);
1141
1142 let mut share = shares[3].clone();
1144 share.index = 10;
1145
1146 let result = arb.commitment(
1148 contributors[0].clone(),
1149 commitment,
1150 vec![0, 1, 2, 3],
1151 vec![share],
1152 );
1153 assert!(matches!(result, Err(Error::PlayerInvalid)));
1154 }
1155
1156 #[test]
1157 fn test_dealer_acks() {
1158 let n = 5;
1160 let mut rng = StdRng::seed_from_u64(0);
1161
1162 let mut contributors = Vec::new();
1164 for i in 0..n {
1165 let signer = Ed25519::from_seed(i as u64).public_key();
1166 contributors.push(signer);
1167 }
1168 contributors.sort();
1169
1170 let (mut dealer, _, _) = Dealer::new(&mut rng, None, contributors.clone());
1172
1173 for player in &contributors {
1175 dealer.ack(player.clone()).unwrap();
1176 }
1177
1178 let output = dealer.finalize().unwrap();
1180 assert_eq!(output.active, vec![0, 1, 2, 3, 4]);
1181 assert!(output.inactive.is_empty());
1182 }
1183
1184 #[test]
1185 fn test_dealer_inactive() {
1186 let n = 5;
1188 let mut rng = StdRng::seed_from_u64(0);
1189
1190 let mut contributors = Vec::new();
1192 for i in 0..n {
1193 let signer = Ed25519::from_seed(i as u64).public_key();
1194 contributors.push(signer);
1195 }
1196 contributors.sort();
1197
1198 let (mut dealer, _, _) = Dealer::new(&mut rng, None, contributors.clone());
1200
1201 for player in contributors.iter().take(4) {
1203 dealer.ack(player.clone()).unwrap();
1204 }
1205
1206 let output = dealer.finalize().unwrap();
1208 assert_eq!(output.active, vec![0, 1, 2, 3]);
1209 assert_eq!(output.inactive, vec![4]);
1210 }
1211
1212 #[test]
1213 fn test_dealer_insufficient() {
1214 let n = 5;
1216 let mut rng = StdRng::seed_from_u64(0);
1217
1218 let mut contributors = Vec::new();
1220 for i in 0..n {
1221 let signer = Ed25519::from_seed(i as u64).public_key();
1222 contributors.push(signer);
1223 }
1224 contributors.sort();
1225
1226 let (mut dealer, _, _) = Dealer::new(&mut rng, None, contributors.clone());
1228
1229 for player in contributors.iter().take(2) {
1231 dealer.ack(player.clone()).unwrap();
1232 }
1233
1234 assert!(dealer.finalize().is_none());
1236 }
1237
1238 #[test]
1239 fn test_dealer_duplicate_ack() {
1240 let n = 5;
1242 let mut rng = StdRng::seed_from_u64(0);
1243
1244 let mut contributors = Vec::new();
1246 for i in 0..n {
1247 let signer = Ed25519::from_seed(i as u64).public_key();
1248 contributors.push(signer);
1249 }
1250 contributors.sort();
1251
1252 let (mut dealer, _, _) = Dealer::new(&mut rng, None, contributors.clone());
1254
1255 let player = contributors[0].clone();
1257 dealer.ack(player.clone()).unwrap();
1258
1259 let result = dealer.ack(player);
1261 assert!(matches!(result, Err(Error::DuplicateAck)));
1262 }
1263
1264 #[test]
1265 fn test_dealer_invalid_player() {
1266 let n = 5;
1268 let mut rng = StdRng::seed_from_u64(0);
1269
1270 let mut contributors = Vec::new();
1272 for i in 0..n {
1273 let signer = Ed25519::from_seed(i as u64).public_key();
1274 contributors.push(signer);
1275 }
1276 contributors.sort();
1277
1278 let (mut dealer, _, _) = Dealer::new(&mut rng, None, contributors.clone());
1280
1281 let player = Ed25519::from_seed(n as u64).public_key();
1283 let result = dealer.ack(player);
1284 assert!(matches!(result, Err(Error::PlayerInvalid)));
1285 }
1286
1287 #[test]
1288 fn test_player_reveals() {
1289 let n = 11;
1291 let q = quorum(n as u32) as usize;
1292 let mut rng = StdRng::seed_from_u64(0);
1293
1294 let mut contributors = Vec::new();
1296 for i in 0..n {
1297 let signer = Ed25519::from_seed(i as u64).public_key();
1298 contributors.push(signer);
1299 }
1300 contributors.sort();
1301
1302 let mut player = Player::new(
1304 contributors[0].clone(),
1305 None,
1306 contributors.clone(),
1307 contributors.clone(),
1308 1,
1309 );
1310
1311 let mut commitments = HashMap::new();
1313 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1314 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
1315 player
1316 .share(con.clone(), commitment.clone(), shares[0].clone())
1317 .unwrap();
1318 commitments.insert(i as u32, commitment);
1319 }
1320
1321 let last = (q - 1) as u32;
1323 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
1324 commitments.insert(last, commitment);
1325 let mut reveals = HashMap::new();
1326 reveals.insert(last, shares[0].clone());
1327 player.finalize(commitments, reveals).unwrap();
1328 }
1329
1330 #[test]
1331 fn test_player_missing_reveal() {
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 = Ed25519::from_seed(i as u64).public_key();
1341 contributors.push(signer);
1342 }
1343 contributors.sort();
1344
1345 let mut player = Player::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) = Dealer::new(&mut rng, None, contributors.clone());
1358 player
1359 .share(con.clone(), commitment.clone(), shares[0].clone())
1360 .unwrap();
1361 commitments.insert(i as u32, commitment);
1362 }
1363
1364 let last = (q - 1) as u32;
1366 let (_, commitment, _) = Dealer::new(&mut rng, None, contributors.clone());
1367 commitments.insert(last, commitment);
1368 let result = player.finalize(commitments, HashMap::new());
1369 assert!(matches!(result, Err(Error::MissingShare)));
1370 }
1371
1372 #[test]
1373 fn test_player_insufficient_commitments() {
1374 let n = 5;
1376 let mut rng = StdRng::seed_from_u64(0);
1377
1378 let mut contributors = Vec::new();
1380 for i in 0..n {
1381 let signer = Ed25519::from_seed(i as u64).public_key();
1382 contributors.push(signer);
1383 }
1384 contributors.sort();
1385
1386 let mut player = Player::new(
1388 contributors[0].clone(),
1389 None,
1390 contributors.clone(),
1391 contributors.clone(),
1392 1,
1393 );
1394
1395 let mut commitments = HashMap::new();
1397 for (i, con) in contributors.iter().enumerate().take(2) {
1398 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
1399 player
1400 .share(con.clone(), commitment.clone(), shares[0].clone())
1401 .unwrap();
1402 commitments.insert(i as u32, commitment);
1403 }
1404
1405 let result = player.finalize(commitments, HashMap::new());
1407 assert!(matches!(result, Err(Error::InvalidCommitments)));
1408 }
1409
1410 #[test]
1411 fn test_player_misdirected_reveal() {
1412 let n = 11;
1414 let q = quorum(n as u32) as usize;
1415 let mut rng = StdRng::seed_from_u64(0);
1416
1417 let mut contributors = Vec::new();
1419 for i in 0..n {
1420 let signer = Ed25519::from_seed(i as u64).public_key();
1421 contributors.push(signer);
1422 }
1423 contributors.sort();
1424
1425 let mut player = Player::new(
1427 contributors[0].clone(),
1428 None,
1429 contributors.clone(),
1430 contributors.clone(),
1431 1,
1432 );
1433
1434 let mut commitments = HashMap::new();
1436 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1437 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
1438 player
1439 .share(con.clone(), commitment.clone(), shares[0].clone())
1440 .unwrap();
1441 commitments.insert(i as u32, commitment);
1442 }
1443
1444 let last = (q - 1) as u32;
1446 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
1447 commitments.insert(last, commitment);
1448 let mut reveals = HashMap::new();
1449 reveals.insert(last, shares[1].clone());
1450 let result = player.finalize(commitments, reveals);
1451 assert!(matches!(result, Err(Error::MisdirectedShare)));
1452 }
1453
1454 #[test]
1455 fn test_player_invalid_commitment() {
1456 let n = 11;
1458 let q = quorum(n as u32) as usize;
1459 let mut rng = StdRng::seed_from_u64(0);
1460
1461 let mut contributors = Vec::new();
1463 for i in 0..n {
1464 let signer = Ed25519::from_seed(i as u64).public_key();
1465 contributors.push(signer);
1466 }
1467 contributors.sort();
1468
1469 let mut player = Player::new(
1471 contributors[0].clone(),
1472 None,
1473 contributors.clone(),
1474 contributors.clone(),
1475 1,
1476 );
1477
1478 let mut commitments = HashMap::new();
1480 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1481 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
1482 player
1483 .share(con.clone(), commitment.clone(), shares[0].clone())
1484 .unwrap();
1485 commitments.insert(i as u32, commitment);
1486 }
1487
1488 let last = (q - 1) as u32;
1490 let (commitment, shares) = ops::generate_shares(&mut rng, None, n as u32, 1);
1491 commitments.insert(last, commitment);
1492 let mut reveals = HashMap::new();
1493 reveals.insert(last, shares[0].clone());
1494 let result = player.finalize(commitments, reveals);
1495 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
1496 }
1497
1498 #[test]
1499 fn test_player_invalid_reveal() {
1500 let n = 11;
1502 let q = quorum(n as u32) as usize;
1503 let mut rng = StdRng::seed_from_u64(0);
1504
1505 let mut contributors = Vec::new();
1507 for i in 0..n {
1508 let signer = Ed25519::from_seed(i as u64).public_key();
1509 contributors.push(signer);
1510 }
1511 contributors.sort();
1512
1513 let mut player = Player::new(
1515 contributors[0].clone(),
1516 None,
1517 contributors.clone(),
1518 contributors.clone(),
1519 1,
1520 );
1521
1522 let mut commitments = HashMap::new();
1524 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1525 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
1526 player
1527 .share(con.clone(), commitment.clone(), shares[0].clone())
1528 .unwrap();
1529 commitments.insert(i as u32, commitment);
1530 }
1531
1532 let last = (q - 1) as u32;
1534 let (_, commitment, shares) = Dealer::new(&mut rng, None, contributors.clone());
1535 commitments.insert(last, commitment);
1536 let mut reveals = HashMap::new();
1537 let mut share = shares[1].clone();
1538 share.index = 0;
1539 reveals.insert(last, share);
1540 let result = player.finalize(commitments, reveals);
1541 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
1542 }
1543}