1pub mod arbiter;
128pub use arbiter::Arbiter;
129pub mod dealer;
130pub use dealer::Dealer;
131pub mod ops;
132pub mod player;
133pub use player::Player;
134use thiserror::Error;
135
136#[derive(Error, Debug)]
137pub enum Error {
138 #[error("unexpected polynomial")]
139 UnexpectedPolynomial,
140 #[error("commitment has wrong degree")]
141 CommitmentWrongDegree,
142 #[error("misdirected share")]
143 MisdirectedShare,
144 #[error("share does not on commitment")]
145 ShareWrongCommitment,
146 #[error("insufficient dealings")]
147 InsufficientDealings,
148 #[error("reshare mismatch")]
149 ReshareMismatch,
150 #[error("share interpolation failed")]
151 ShareInterpolationFailed,
152 #[error("public key interpolation failed")]
153 PublicKeyInterpolationFailed,
154 #[error("dealer is invalid")]
155 DealerInvalid,
156 #[error("player invalid")]
157 PlayerInvalid,
158 #[error("missing share")]
159 MissingShare,
160 #[error("missing commitment")]
161 MissingCommitment,
162 #[error("too many commitments")]
163 TooManyCommitments,
164 #[error("duplicate commitment")]
165 DuplicateCommitment,
166 #[error("duplicate share")]
167 DuplicateShare,
168 #[error("duplicate ack")]
169 DuplicateAck,
170 #[error("mismatched commitment")]
171 MismatchedCommitment,
172 #[error("mismatched share")]
173 MismatchedShare,
174 #[error("too many reveals")]
175 TooManyReveals,
176 #[error("incorrect active")]
177 IncorrectActive,
178 #[error("already active")]
179 AlreadyActive,
180 #[error("invalid commitments")]
181 InvalidCommitments,
182 #[error("dealer disqualified")]
183 DealerDisqualified,
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189 use crate::{
190 bls12381::primitives::{
191 ops::{
192 partial_sign_proof_of_possession, threshold_signature_recover,
193 verify_proof_of_possession,
194 },
195 poly::public,
196 variant::{MinPk, MinSig, Variant},
197 },
198 ed25519::PrivateKey,
199 PrivateKeyExt as _, Signer as _,
200 };
201 use arbiter::Output;
202 use commonware_utils::quorum;
203 use rand::{rngs::StdRng, SeedableRng};
204 use std::collections::HashMap;
205
206 fn run_dkg_and_reshare<V: Variant>(
207 n_0: u32,
208 dealers_0: u32,
209 n_1: u32,
210 dealers_1: u32,
211 concurrency: usize,
212 ) {
213 let mut rng = StdRng::seed_from_u64(0);
215
216 let mut contributors = Vec::new();
218 for i in 0..n_0 {
219 let signer = PrivateKey::from_seed(i as u64).public_key();
220 contributors.push(signer);
221 }
222 contributors.sort();
223
224 let mut dealer_shares = HashMap::new();
226 let mut dealers = HashMap::new();
227 for con in contributors.iter().take(dealers_0 as usize) {
228 let (dealer, commitment, shares) =
229 Dealer::<_, V>::new(&mut rng, None, contributors.clone());
230 dealer_shares.insert(con.clone(), (commitment, shares));
231 dealers.insert(con.clone(), dealer);
232 }
233
234 let mut players = HashMap::new();
236 for con in &contributors {
237 let player = Player::<_, V>::new(
238 con.clone(),
239 None,
240 contributors.clone(),
241 contributors.clone(),
242 concurrency,
243 );
244 players.insert(con.clone(), player);
245 }
246
247 let mut arb = Arbiter::<_, V>::new(
249 None,
250 contributors.clone(),
251 contributors.clone(),
252 concurrency,
253 );
254
255 assert!(!arb.ready());
257
258 for (dealer, mut dealer_obj) in dealers {
260 let (commitment, shares) = dealer_shares.get(&dealer).unwrap().clone();
262 for (player_idx, player) in contributors.iter().enumerate() {
263 let player_obj = players.get_mut(player).unwrap();
265 player_obj
266 .share(
267 dealer.clone(),
268 commitment.clone(),
269 shares[player_idx].clone(),
270 )
271 .unwrap();
272
273 dealer_obj.ack(player.clone()).unwrap();
275 }
276
277 let output = dealer_obj.finalize().unwrap();
279
280 assert!(output.inactive.is_empty());
282
283 arb.commitment(dealer, commitment, output.active, Vec::new())
285 .unwrap();
286 }
287
288 assert!(arb.ready());
290
291 let (result, disqualified) = arb.finalize();
293
294 assert_eq!(disqualified.len(), (n_0 - dealers_0) as usize);
296
297 let output: Output<V> = result.unwrap();
299
300 let expected_commitments = quorum(n_0) as usize;
302 assert_eq!(output.commitments.len(), expected_commitments);
303
304 assert!(output.reveals.is_empty());
306
307 let mut outputs = HashMap::new();
309 for player in contributors.iter() {
310 let result = players
311 .remove(player)
312 .unwrap()
313 .finalize(output.commitments.clone(), HashMap::new())
314 .unwrap();
315 outputs.insert(player.clone(), result);
316 }
317
318 let t = quorum(n_0);
320 let partials = outputs
321 .values()
322 .map(|s| partial_sign_proof_of_possession::<V>(&s.public, &s.share))
323 .collect::<Vec<_>>();
324 let signature =
325 threshold_signature_recover::<V, _>(t, &partials).expect("unable to recover signature");
326 let public_key = public::<V>(&outputs.iter().next().unwrap().1.public);
327 verify_proof_of_possession::<V>(public_key, &signature)
328 .expect("invalid proof of possession");
329
330 let mut reshare_players = Vec::new();
332 for i in 0..n_1 {
333 let player = PrivateKey::from_seed((i + n_0) as u64).public_key();
334 reshare_players.push(player);
335 }
336 reshare_players.sort();
337
338 let mut reshare_shares = HashMap::new();
340 let mut reshare_dealers = HashMap::new();
341 for con in contributors.iter().take(dealers_1 as usize) {
342 let output = outputs.get(con).unwrap();
343 let (dealer, commitment, shares) = Dealer::<_, V>::new(
344 &mut rng,
345 Some(output.share.clone()),
346 reshare_players.clone(),
347 );
348 reshare_shares.insert(con.clone(), (commitment, shares));
349 reshare_dealers.insert(con.clone(), dealer);
350 }
351
352 let mut reshare_player_objs = HashMap::new();
354 for con in &reshare_players {
355 let player = Player::<_, V>::new(
356 con.clone(),
357 Some(output.public.clone()),
358 contributors.clone(),
359 reshare_players.clone(),
360 concurrency,
361 );
362 reshare_player_objs.insert(con.clone(), player);
363 }
364
365 let mut arb = Arbiter::<_, V>::new(
367 Some(output.public),
368 contributors.clone(),
369 reshare_players.clone(),
370 concurrency,
371 );
372
373 assert!(!arb.ready());
375
376 for (dealer, mut dealer_obj) in reshare_dealers {
378 let (commitment, shares) = reshare_shares.get(&dealer).unwrap().clone();
380 for (player_idx, player) in reshare_players.iter().enumerate() {
381 let player_obj = reshare_player_objs.get_mut(player).unwrap();
383 player_obj
384 .share(
385 dealer.clone(),
386 commitment.clone(),
387 shares[player_idx].clone(),
388 )
389 .unwrap();
390
391 dealer_obj.ack(player.clone()).unwrap();
393 }
394
395 let output = dealer_obj.finalize().unwrap();
397
398 assert!(output.inactive.is_empty());
400
401 arb.commitment(dealer, commitment, output.active, Vec::new())
403 .unwrap();
404 }
405
406 assert!(arb.ready());
408
409 let (result, disqualified) = arb.finalize();
411
412 assert_eq!(disqualified.len(), (n_0 - dealers_1) as usize);
414
415 let output: Output<V> = result.unwrap();
417
418 let expected_commitments = quorum(n_0) as usize;
420 assert_eq!(output.commitments.len(), expected_commitments);
421
422 assert!(output.reveals.is_empty());
424
425 let mut outputs = Vec::new();
427 for player in reshare_players.iter() {
428 let result = reshare_player_objs
429 .remove(player)
430 .unwrap()
431 .finalize(output.commitments.clone(), HashMap::new())
432 .unwrap();
433 assert_eq!(result.public, output.public);
434 outputs.push(result);
435 }
436
437 let t = quorum(n_1);
439 let partials = outputs
440 .iter()
441 .map(|s| partial_sign_proof_of_possession::<V>(&s.public, &s.share))
442 .collect::<Vec<_>>();
443 let signature =
444 threshold_signature_recover::<V, _>(t, &partials).expect("unable to recover signature");
445 let public_key = public::<V>(&outputs[0].public);
446 verify_proof_of_possession::<V>(public_key, &signature)
447 .expect("invalid proof of possession");
448 }
449
450 #[test]
451 fn test_dkg_and_reshare_all_active() {
452 run_dkg_and_reshare::<MinPk>(5, 5, 10, 5, 4);
453 run_dkg_and_reshare::<MinSig>(5, 5, 10, 5, 4);
454 }
455
456 #[test]
457 fn test_dkg_and_reshare_min_active() {
458 run_dkg_and_reshare::<MinPk>(4, 3, 4, 3, 4);
459 run_dkg_and_reshare::<MinSig>(4, 3, 4, 3, 4);
460 }
461
462 #[test]
463 fn test_dkg_and_reshare_min_active_different_sizes() {
464 run_dkg_and_reshare::<MinPk>(5, 4, 10, 4, 4);
465 run_dkg_and_reshare::<MinSig>(5, 4, 10, 4, 4);
466 }
467
468 #[test]
469 fn test_dkg_and_reshare_min_active_large() {
470 run_dkg_and_reshare::<MinPk>(20, 14, 100, 14, 4);
471 run_dkg_and_reshare::<MinSig>(20, 14, 100, 14, 4);
472 }
473
474 #[test]
475 #[should_panic]
476 fn test_dkg_and_reshare_insufficient_active() {
477 run_dkg_and_reshare::<MinPk>(5, 3, 10, 2, 4);
478 run_dkg_and_reshare::<MinSig>(5, 3, 10, 2, 4);
479 }
480
481 #[test]
482 fn test_invalid_commitment() {
483 let n = 5;
485 let mut rng = StdRng::seed_from_u64(0);
486
487 let mut contributors = Vec::new();
489 for i in 0..n {
490 let signer = PrivateKey::from_seed(i as u64).public_key();
491 contributors.push(signer);
492 }
493 contributors.sort();
494
495 let (_, _, shares) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
497
498 let t = quorum(n);
500 let (public, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
501
502 let mut player = Player::<_, MinSig>::new(
504 contributors[0].clone(),
505 None,
506 contributors.clone(),
507 contributors.clone(),
508 1,
509 );
510
511 let result = player.share(contributors[0].clone(), public, shares[0].clone());
513 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
514 }
515
516 #[test]
517 fn test_mismatched_commitment() {
518 let n = 5;
520 let mut rng = StdRng::seed_from_u64(0);
521
522 let mut contributors = Vec::new();
524 for i in 0..n {
525 let signer = PrivateKey::from_seed(i as u64).public_key();
526 contributors.push(signer);
527 }
528 contributors.sort();
529
530 let (_, commitment, shares) =
532 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
533
534 let t = quorum(n);
536 let (other_commitment, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
537
538 let mut player = Player::<_, MinSig>::new(
540 contributors[0].clone(),
541 None,
542 contributors.clone(),
543 contributors.clone(),
544 1,
545 );
546
547 player
549 .share(contributors[0].clone(), commitment, shares[0].clone())
550 .unwrap();
551
552 let result = player.share(contributors[0].clone(), other_commitment, shares[0].clone());
554 assert!(matches!(result, Err(Error::MismatchedCommitment)));
555 }
556
557 #[test]
558 fn test_mismatched_share() {
559 let n = 5;
561 let mut rng = StdRng::seed_from_u64(0);
562
563 let mut contributors = Vec::new();
565 for i in 0..n {
566 let signer = PrivateKey::from_seed(i as u64).public_key();
567 contributors.push(signer);
568 }
569 contributors.sort();
570
571 let (_, commitment, shares) =
573 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
574
575 let t = quorum(n);
577 let (_, other_shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
578
579 let mut player = Player::<_, MinSig>::new(
581 contributors[0].clone(),
582 None,
583 contributors.clone(),
584 contributors.clone(),
585 1,
586 );
587
588 player
590 .share(
591 contributors[0].clone(),
592 commitment.clone(),
593 shares[0].clone(),
594 )
595 .unwrap();
596
597 let result = player.share(contributors[0].clone(), commitment, other_shares[0].clone());
599 assert!(matches!(result, Err(Error::MismatchedShare)));
600 }
601
602 #[test]
603 fn test_duplicate_share() {
604 let n = 5;
606 let mut rng = StdRng::seed_from_u64(0);
607
608 let mut contributors = Vec::new();
610 for i in 0..n {
611 let signer = PrivateKey::from_seed(i as u64).public_key();
612 contributors.push(signer);
613 }
614 contributors.sort();
615
616 let (_, commitment, shares) =
618 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
619
620 let mut player = Player::<_, MinSig>::new(
622 contributors[0].clone(),
623 None,
624 contributors.clone(),
625 contributors.clone(),
626 1,
627 );
628
629 player
631 .share(
632 contributors[0].clone(),
633 commitment.clone(),
634 shares[0].clone(),
635 )
636 .unwrap();
637
638 let result = player.share(contributors[0].clone(), commitment, shares[0].clone());
640 assert!(matches!(result, Err(Error::DuplicateShare)));
641 }
642
643 #[test]
644 fn test_misdirected_share() {
645 let n = 5;
647 let mut rng = StdRng::seed_from_u64(0);
648
649 let mut contributors = Vec::new();
651 for i in 0..n {
652 let signer = PrivateKey::from_seed(i as u64).public_key();
653 contributors.push(signer);
654 }
655 contributors.sort();
656
657 let (_, commitment, shares) =
659 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
660
661 let mut player = Player::<_, MinSig>::new(
663 contributors[0].clone(),
664 None,
665 contributors.clone(),
666 contributors.clone(),
667 1,
668 );
669
670 let result = player.share(
672 contributors[0].clone(),
673 commitment.clone(),
674 shares[1].clone(),
675 );
676 assert!(matches!(result, Err(Error::MisdirectedShare)));
677 }
678
679 #[test]
680 fn test_invalid_dealer() {
681 let n = 5;
683 let mut rng = StdRng::seed_from_u64(0);
684
685 let mut contributors = Vec::new();
687 for i in 0..n {
688 let signer = PrivateKey::from_seed(i as u64).public_key();
689 contributors.push(signer);
690 }
691 contributors.sort();
692
693 let (_, commitment, shares) =
695 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
696
697 let mut player = Player::<_, MinSig>::new(
699 contributors[0].clone(),
700 None,
701 contributors.clone(),
702 contributors.clone(),
703 1,
704 );
705
706 let dealer = PrivateKey::from_seed(n as u64).public_key();
708 let result = player.share(dealer.clone(), commitment.clone(), shares[0].clone());
709 assert!(matches!(result, Err(Error::DealerInvalid)));
710
711 let mut arb =
713 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
714
715 let result = arb.commitment(dealer, commitment, vec![0, 1, 2, 3], Vec::new());
717 assert!(matches!(result, Err(Error::DealerInvalid)));
718 }
719
720 #[test]
721 fn test_invalid_commitment_degree() {
722 let n = 5;
724 let mut rng = StdRng::seed_from_u64(0);
725
726 let mut contributors = Vec::new();
728 for i in 0..n {
729 let signer = PrivateKey::from_seed(i as u64).public_key();
730 contributors.push(signer);
731 }
732 contributors.sort();
733
734 let (_, _, shares) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
736
737 let (public, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n * 2, 1);
739
740 let mut player = Player::<_, MinSig>::new(
742 contributors[0].clone(),
743 None,
744 contributors.clone(),
745 contributors.clone(),
746 1,
747 );
748
749 let result = player.share(contributors[0].clone(), public.clone(), shares[0].clone());
751 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
752
753 let mut arb =
755 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
756
757 let result = arb.commitment(
759 contributors[0].clone(),
760 public,
761 vec![0, 1, 2, 3, 4],
762 Vec::new(),
763 );
764 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
765 }
766
767 #[test]
768 fn test_reveal() {
769 let n = 5;
771 let mut rng = StdRng::seed_from_u64(0);
772
773 let mut contributors = Vec::new();
775 for i in 0..n {
776 let signer = PrivateKey::from_seed(i as u64).public_key();
777 contributors.push(signer);
778 }
779 contributors.sort();
780
781 let (_, commitment, shares) =
783 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
784
785 let mut arb =
787 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
788
789 arb.commitment(
791 contributors[0].clone(),
792 commitment,
793 vec![0, 1, 2, 3],
794 vec![shares[4].clone()],
795 )
796 .unwrap();
797 }
798
799 #[test]
800 fn test_arbiter_reveals() {
801 let n = 11;
803 let q = quorum(n as u32) as usize;
804 let mut rng = StdRng::seed_from_u64(0);
805
806 let mut contributors = Vec::new();
808 for i in 0..n {
809 let signer = PrivateKey::from_seed(i as u64).public_key();
810 contributors.push(signer);
811 }
812 contributors.sort();
813
814 let mut arb =
816 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
817
818 let mut commitments = Vec::with_capacity(n);
820 let mut reveals = Vec::with_capacity(n);
821 for con in &contributors {
822 let (_, commitment, shares) =
824 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
825 commitments.push(commitment.clone());
826 reveals.push(shares[q].clone());
827
828 let acks: Vec<u32> = (0..q as u32).collect();
830 let reveals = shares[q..n].to_vec();
831 arb.commitment(con.clone(), commitment, acks, reveals)
832 .unwrap();
833 }
834
835 let (result, _) = arb.finalize();
837 let output = result.unwrap();
838
839 assert_eq!(output.commitments.len(), q);
841 for (dealer_idx, commitment) in commitments.iter().enumerate().take(q) {
842 let dealer_idx = dealer_idx as u32;
843 assert_eq!(output.commitments.get(&dealer_idx).unwrap(), commitment);
844 assert_eq!(
845 output.reveals.get(&dealer_idx).unwrap()[0],
846 reveals[dealer_idx as usize]
847 );
848 }
849 }
850
851 #[test]
852 fn test_arbiter_best() {}
853
854 #[test]
855 fn test_duplicate_commitment() {
856 let n = 5;
858 let mut rng = StdRng::seed_from_u64(0);
859
860 let mut contributors = Vec::new();
862 for i in 0..n {
863 let signer = PrivateKey::from_seed(i as u64).public_key();
864 contributors.push(signer);
865 }
866 contributors.sort();
867
868 let (_, commitment, shares) =
870 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
871
872 let mut arb =
874 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
875
876 arb.commitment(
878 contributors[0].clone(),
879 commitment.clone(),
880 vec![0, 1, 2, 3],
881 vec![shares[4].clone()],
882 )
883 .unwrap();
884
885 let result = arb.commitment(
887 contributors[0].clone(),
888 commitment,
889 vec![0, 1, 2, 3],
890 vec![shares[4].clone()],
891 );
892 assert!(matches!(result, Err(Error::DuplicateCommitment)));
893 }
894
895 #[test]
896 fn test_reveal_duplicate_player() {
897 let n = 5;
899 let mut rng = StdRng::seed_from_u64(0);
900
901 let mut contributors = Vec::new();
903 for i in 0..n {
904 let signer = PrivateKey::from_seed(i as u64).public_key();
905 contributors.push(signer);
906 }
907 contributors.sort();
908
909 let (_, commitment, shares) =
911 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
912
913 let mut arb =
915 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
916
917 let result = arb.commitment(
919 contributors[0].clone(),
920 commitment,
921 vec![0, 1, 2, 3],
922 vec![shares[3].clone()],
923 );
924 assert!(matches!(result, Err(Error::AlreadyActive)));
925 }
926
927 #[test]
928 fn test_insufficient_active() {
929 let n = 5;
931 let mut rng = StdRng::seed_from_u64(0);
932
933 let mut contributors = Vec::new();
935 for i in 0..n {
936 let signer = PrivateKey::from_seed(i as u64).public_key();
937 contributors.push(signer);
938 }
939 contributors.sort();
940
941 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
943
944 let mut arb =
946 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
947
948 let result = arb.commitment(
950 contributors[0].clone(),
951 commitment.clone(),
952 vec![0, 1, 2, 3],
953 Vec::new(),
954 );
955 assert!(matches!(result, Err(Error::IncorrectActive)));
956
957 let result = arb.commitment(
959 contributors[0].clone(),
960 commitment,
961 vec![0, 1, 2, 3, 4],
962 Vec::new(),
963 );
964 assert!(matches!(result, Err(Error::DealerDisqualified)));
965 }
966
967 #[test]
968 fn test_manual_disqualify() {
969 let n = 5;
971 let mut rng = StdRng::seed_from_u64(0);
972
973 let mut contributors = Vec::new();
975 for i in 0..n {
976 let signer = PrivateKey::from_seed(i as u64).public_key();
977 contributors.push(signer);
978 }
979 contributors.sort();
980
981 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
983
984 let mut arb =
986 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
987
988 arb.disqualify(contributors[0].clone());
990
991 let result = arb.commitment(
993 contributors[0].clone(),
994 commitment,
995 vec![0, 1, 2, 3, 4],
996 Vec::new(),
997 );
998 assert!(matches!(result, Err(Error::DealerDisqualified)));
999 }
1000
1001 #[test]
1002 fn test_too_many_reveals() {
1003 let n = 5;
1005 let mut rng = StdRng::seed_from_u64(0);
1006
1007 let mut contributors = Vec::new();
1009 for i in 0..n {
1010 let signer = PrivateKey::from_seed(i as u64).public_key();
1011 contributors.push(signer);
1012 }
1013 contributors.sort();
1014
1015 let (_, commitment, shares) =
1017 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1018
1019 let mut arb =
1021 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1022
1023 let result = arb.commitment(
1025 contributors[0].clone(),
1026 commitment,
1027 vec![0, 1, 2],
1028 vec![shares[3].clone(), shares[4].clone()],
1029 );
1030 assert!(matches!(result, Err(Error::TooManyReveals)));
1031 }
1032
1033 #[test]
1034 fn test_incorrect_reveal() {
1035 let n = 5;
1037 let mut rng = StdRng::seed_from_u64(0);
1038
1039 let mut contributors = Vec::new();
1041 for i in 0..n {
1042 let signer = PrivateKey::from_seed(i as u64).public_key();
1043 contributors.push(signer);
1044 }
1045 contributors.sort();
1046
1047 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1049
1050 let t = quorum(n);
1052 let (_, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
1053
1054 let mut arb =
1056 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1057
1058 let result = arb.commitment(
1060 contributors[0].clone(),
1061 commitment,
1062 vec![0, 1, 2, 3],
1063 vec![shares[4].clone()],
1064 );
1065 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
1066 }
1067
1068 #[test]
1069 fn test_reveal_corrupt_share() {
1070 let n = 5;
1072 let mut rng = StdRng::seed_from_u64(0);
1073
1074 let mut contributors = Vec::new();
1076 for i in 0..n {
1077 let signer = PrivateKey::from_seed(i as u64).public_key();
1078 contributors.push(signer);
1079 }
1080 contributors.sort();
1081
1082 let (_, commitment, shares) =
1084 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1085
1086 let mut arb =
1088 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1089
1090 let mut share = shares[3].clone();
1092 share.index = 4;
1093
1094 let result = arb.commitment(
1096 contributors[0].clone(),
1097 commitment,
1098 vec![0, 1, 2, 3],
1099 vec![share],
1100 );
1101 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
1102 }
1103
1104 #[test]
1105 fn test_reveal_duplicate_ack() {
1106 let n = 5;
1108 let mut rng = StdRng::seed_from_u64(0);
1109
1110 let mut contributors = Vec::new();
1112 for i in 0..n {
1113 let signer = PrivateKey::from_seed(i as u64).public_key();
1114 contributors.push(signer);
1115 }
1116 contributors.sort();
1117
1118 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1120
1121 let mut arb =
1123 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1124
1125 let result = arb.commitment(
1127 contributors[0].clone(),
1128 commitment,
1129 vec![0, 1, 2, 2],
1130 Vec::new(),
1131 );
1132 assert!(matches!(result, Err(Error::AlreadyActive)));
1133 }
1134
1135 #[test]
1136 fn test_reveal_invalid_ack() {
1137 let n = 5;
1139 let mut rng = StdRng::seed_from_u64(0);
1140
1141 let mut contributors = Vec::new();
1143 for i in 0..n {
1144 let signer = PrivateKey::from_seed(i as u64).public_key();
1145 contributors.push(signer);
1146 }
1147 contributors.sort();
1148
1149 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1151
1152 let mut arb =
1154 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1155
1156 let result = arb.commitment(
1158 contributors[0].clone(),
1159 commitment,
1160 vec![0, 1, 2, 10],
1161 Vec::new(),
1162 );
1163 assert!(matches!(result, Err(Error::PlayerInvalid)));
1164 }
1165
1166 #[test]
1167 fn test_reveal_invalid_share() {
1168 let n = 5;
1170 let mut rng = StdRng::seed_from_u64(0);
1171
1172 let mut contributors = Vec::new();
1174 for i in 0..n {
1175 let signer = PrivateKey::from_seed(i as u64).public_key();
1176 contributors.push(signer);
1177 }
1178 contributors.sort();
1179
1180 let (_, commitment, shares) =
1182 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1183
1184 let mut arb =
1186 Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1187
1188 let mut share = shares[3].clone();
1190 share.index = 10;
1191
1192 let result = arb.commitment(
1194 contributors[0].clone(),
1195 commitment,
1196 vec![0, 1, 2, 3],
1197 vec![share],
1198 );
1199 assert!(matches!(result, Err(Error::PlayerInvalid)));
1200 }
1201
1202 #[test]
1203 fn test_dealer_acks() {
1204 let n = 5;
1206 let mut rng = StdRng::seed_from_u64(0);
1207
1208 let mut contributors = Vec::new();
1210 for i in 0..n {
1211 let signer = PrivateKey::from_seed(i as u64).public_key();
1212 contributors.push(signer);
1213 }
1214 contributors.sort();
1215
1216 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1218
1219 for player in &contributors {
1221 dealer.ack(player.clone()).unwrap();
1222 }
1223
1224 let output = dealer.finalize().unwrap();
1226 assert_eq!(output.active, vec![0, 1, 2, 3, 4]);
1227 assert!(output.inactive.is_empty());
1228 }
1229
1230 #[test]
1231 fn test_dealer_inactive() {
1232 let n = 5;
1234 let mut rng = StdRng::seed_from_u64(0);
1235
1236 let mut contributors = Vec::new();
1238 for i in 0..n {
1239 let signer = PrivateKey::from_seed(i as u64).public_key();
1240 contributors.push(signer);
1241 }
1242 contributors.sort();
1243
1244 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1246
1247 for player in contributors.iter().take(4) {
1249 dealer.ack(player.clone()).unwrap();
1250 }
1251
1252 let output = dealer.finalize().unwrap();
1254 assert_eq!(output.active, vec![0, 1, 2, 3]);
1255 assert_eq!(output.inactive, vec![4]);
1256 }
1257
1258 #[test]
1259 fn test_dealer_insufficient() {
1260 let n = 5;
1262 let mut rng = StdRng::seed_from_u64(0);
1263
1264 let mut contributors = Vec::new();
1266 for i in 0..n {
1267 let signer = PrivateKey::from_seed(i as u64).public_key();
1268 contributors.push(signer);
1269 }
1270 contributors.sort();
1271
1272 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1274
1275 for player in contributors.iter().take(2) {
1277 dealer.ack(player.clone()).unwrap();
1278 }
1279
1280 assert!(dealer.finalize().is_none());
1282 }
1283
1284 #[test]
1285 fn test_dealer_duplicate_ack() {
1286 let n = 5;
1288 let mut rng = StdRng::seed_from_u64(0);
1289
1290 let mut contributors = Vec::new();
1292 for i in 0..n {
1293 let signer = PrivateKey::from_seed(i as u64).public_key();
1294 contributors.push(signer);
1295 }
1296 contributors.sort();
1297
1298 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1300
1301 let player = contributors[0].clone();
1303 dealer.ack(player.clone()).unwrap();
1304
1305 let result = dealer.ack(player);
1307 assert!(matches!(result, Err(Error::DuplicateAck)));
1308 }
1309
1310 #[test]
1311 fn test_dealer_invalid_player() {
1312 let n = 5;
1314 let mut rng = StdRng::seed_from_u64(0);
1315
1316 let mut contributors = Vec::new();
1318 for i in 0..n {
1319 let signer = PrivateKey::from_seed(i as u64).public_key();
1320 contributors.push(signer);
1321 }
1322 contributors.sort();
1323
1324 let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1326
1327 let player = PrivateKey::from_seed(n as u64).public_key();
1329 let result = dealer.ack(player);
1330 assert!(matches!(result, Err(Error::PlayerInvalid)));
1331 }
1332
1333 #[test]
1334 fn test_player_reveals() {
1335 let n = 11;
1337 let q = quorum(n as u32) as usize;
1338 let mut rng = StdRng::seed_from_u64(0);
1339
1340 let mut contributors = Vec::new();
1342 for i in 0..n {
1343 let signer = PrivateKey::from_seed(i as u64).public_key();
1344 contributors.push(signer);
1345 }
1346 contributors.sort();
1347
1348 let mut player = Player::<_, MinSig>::new(
1350 contributors[0].clone(),
1351 None,
1352 contributors.clone(),
1353 contributors.clone(),
1354 1,
1355 );
1356
1357 let mut commitments = HashMap::new();
1359 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1360 let (_, commitment, shares) =
1361 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1362 player
1363 .share(con.clone(), commitment.clone(), shares[0].clone())
1364 .unwrap();
1365 commitments.insert(i as u32, commitment);
1366 }
1367
1368 let last = (q - 1) as u32;
1370 let (_, commitment, shares) =
1371 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1372 commitments.insert(last, commitment);
1373 let mut reveals = HashMap::new();
1374 reveals.insert(last, shares[0].clone());
1375 player.finalize(commitments, reveals).unwrap();
1376 }
1377
1378 #[test]
1379 fn test_player_missing_reveal() {
1380 let n = 11;
1382 let q = quorum(n as u32) as usize;
1383 let mut rng = StdRng::seed_from_u64(0);
1384
1385 let mut contributors = Vec::new();
1387 for i in 0..n {
1388 let signer = PrivateKey::from_seed(i as u64).public_key();
1389 contributors.push(signer);
1390 }
1391 contributors.sort();
1392
1393 let mut player = Player::<_, MinSig>::new(
1395 contributors[0].clone(),
1396 None,
1397 contributors.clone(),
1398 contributors.clone(),
1399 1,
1400 );
1401
1402 let mut commitments = HashMap::new();
1404 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1405 let (_, commitment, shares) =
1406 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1407 player
1408 .share(con.clone(), commitment.clone(), shares[0].clone())
1409 .unwrap();
1410 commitments.insert(i as u32, commitment);
1411 }
1412
1413 let last = (q - 1) as u32;
1415 let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1416 commitments.insert(last, commitment);
1417 let result = player.finalize(commitments, HashMap::new());
1418 assert!(matches!(result, Err(Error::MissingShare)));
1419 }
1420
1421 #[test]
1422 fn test_player_insufficient_commitments() {
1423 let n = 5;
1425 let mut rng = StdRng::seed_from_u64(0);
1426
1427 let mut contributors = Vec::new();
1429 for i in 0..n {
1430 let signer = PrivateKey::from_seed(i as u64).public_key();
1431 contributors.push(signer);
1432 }
1433 contributors.sort();
1434
1435 let mut player = Player::<_, MinSig>::new(
1437 contributors[0].clone(),
1438 None,
1439 contributors.clone(),
1440 contributors.clone(),
1441 1,
1442 );
1443
1444 let mut commitments = HashMap::new();
1446 for (i, con) in contributors.iter().enumerate().take(2) {
1447 let (_, commitment, shares) =
1448 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1449 player
1450 .share(con.clone(), commitment.clone(), shares[0].clone())
1451 .unwrap();
1452 commitments.insert(i as u32, commitment);
1453 }
1454
1455 let result = player.finalize(commitments, HashMap::new());
1457 assert!(matches!(result, Err(Error::InvalidCommitments)));
1458 }
1459
1460 #[test]
1461 fn test_player_misdirected_reveal() {
1462 let n = 11;
1464 let q = quorum(n as u32) as usize;
1465 let mut rng = StdRng::seed_from_u64(0);
1466
1467 let mut contributors = Vec::new();
1469 for i in 0..n {
1470 let signer = PrivateKey::from_seed(i as u64).public_key();
1471 contributors.push(signer);
1472 }
1473 contributors.sort();
1474
1475 let mut player = Player::<_, MinSig>::new(
1477 contributors[0].clone(),
1478 None,
1479 contributors.clone(),
1480 contributors.clone(),
1481 1,
1482 );
1483
1484 let mut commitments = HashMap::new();
1486 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1487 let (_, commitment, shares) =
1488 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1489 player
1490 .share(con.clone(), commitment.clone(), shares[0].clone())
1491 .unwrap();
1492 commitments.insert(i as u32, commitment);
1493 }
1494
1495 let last = (q - 1) as u32;
1497 let (_, commitment, shares) =
1498 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1499 commitments.insert(last, commitment);
1500 let mut reveals = HashMap::new();
1501 reveals.insert(last, shares[1].clone());
1502 let result = player.finalize(commitments, reveals);
1503 assert!(matches!(result, Err(Error::MisdirectedShare)));
1504 }
1505
1506 #[test]
1507 fn test_player_invalid_commitment() {
1508 let n = 11;
1510 let q = quorum(n as u32) as usize;
1511 let mut rng = StdRng::seed_from_u64(0);
1512
1513 let mut contributors = Vec::new();
1515 for i in 0..n {
1516 let signer = PrivateKey::from_seed(i as u64).public_key();
1517 contributors.push(signer);
1518 }
1519 contributors.sort();
1520
1521 let mut player = Player::<_, MinSig>::new(
1523 contributors[0].clone(),
1524 None,
1525 contributors.clone(),
1526 contributors.clone(),
1527 1,
1528 );
1529
1530 let mut commitments = HashMap::new();
1532 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1533 let (_, commitment, shares) =
1534 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1535 player
1536 .share(con.clone(), commitment.clone(), shares[0].clone())
1537 .unwrap();
1538 commitments.insert(i as u32, commitment);
1539 }
1540
1541 let last = (q - 1) as u32;
1543 let (commitment, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n as u32, 1);
1544 commitments.insert(last, commitment);
1545 let mut reveals = HashMap::new();
1546 reveals.insert(last, shares[0].clone());
1547 let result = player.finalize(commitments, reveals);
1548 assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
1549 }
1550
1551 #[test]
1552 fn test_player_invalid_reveal() {
1553 let n = 11;
1555 let q = quorum(n as u32) as usize;
1556 let mut rng = StdRng::seed_from_u64(0);
1557
1558 let mut contributors = Vec::new();
1560 for i in 0..n {
1561 let signer = PrivateKey::from_seed(i as u64).public_key();
1562 contributors.push(signer);
1563 }
1564 contributors.sort();
1565
1566 let mut player = Player::<_, MinSig>::new(
1568 contributors[0].clone(),
1569 None,
1570 contributors.clone(),
1571 contributors.clone(),
1572 1,
1573 );
1574
1575 let mut commitments = HashMap::new();
1577 for (i, con) in contributors.iter().enumerate().take(q - 1) {
1578 let (_, commitment, shares) =
1579 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1580 player
1581 .share(con.clone(), commitment.clone(), shares[0].clone())
1582 .unwrap();
1583 commitments.insert(i as u32, commitment);
1584 }
1585
1586 let last = (q - 1) as u32;
1588 let (_, commitment, shares) =
1589 Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1590 commitments.insert(last, commitment);
1591 let mut reveals = HashMap::new();
1592 let mut share = shares[1].clone();
1593 share.index = 0;
1594 reveals.insert(last, share);
1595 let result = player.finalize(commitments, reveals);
1596 assert!(matches!(result, Err(Error::ShareWrongCommitment)));
1597 }
1598}