commonware_cryptography/bls12381/dkg/
mod.rs

1//! Distributed Key Generation (DKG) and Resharing protocol for the BLS12-381 curve.
2//!
3//! This crate implements an interactive Distributed Key Generation (DKG) and Resharing protocol
4//! for the BLS12-381 curve. Unlike other constructions, this construction does not require encrypted
5//! shares to be publicly broadcast to complete a DKG/Reshare. Shares, instead, are sent directly
6//! between dealers and players over an encrypted channel (which can be instantiated
7//! with [commonware-p2p](https://docs.rs/commonware-p2p)).
8//!
9//! The DKG is based on the "Joint-Feldman" construction from "Secure Distributed Key
10//! Generation for Discrete-Log Based Cryptosystems" (GJKR99) and Resharing is based
11//! on the construction described in "Redistributing secret shares to new access structures
12//! and its applications" (Desmedt97).
13//!
14//! # Overview
15//!
16//! The protocol has three types of participants: arbiters, dealers, and players. The arbiter
17//! serves as an orchestrator that collects commitments, acknowledgements, and reveals from
18//! dealers/players and replicates them to all dealers/players. The arbiter can be implemented as
19//! a standalone process or by some consensus protocol. Dealers generate commitments/shares and collect
20//! acknowledgements from players. Players receive shares from dealers, validate them, and send acknowledgements
21//! back to dealers. It is possible to be both a dealer and a player in the protocol.
22//!
23//! Whether or not the protocol succeeds, the dealers that did not post valid commitments/acks/reveals are
24//! identified and returned. If the protocol succeeds, any dealers that did not post valid commitments/acks/reveals
25//! are identified (and still returned). It is expected that the set of participants would punish/exclude
26//! "bad" dealers prior to a future round (to eventually make progress).
27//!
28//! # Specification
29//!
30//! ## Assumptions
31//!
32//! * Let `t` be the maximum amount of time it takes for a message to be sent between any two participants.
33//! * Each participant has an encrypted channel to every other participant.
34//! * There exist `3f + 1` participants and at most `f` static Byzantine faults.
35//!
36//! ## [Arbiter] Step 0: Start Round
37//!
38//! Send a message to all participants to start a round. If this is a reshare, include the group polynomial from
39//! the last successful round.
40//!
41//! ## [Dealer] Step 1: Generate Commitment and Dealings
42//!
43//! Upon receiving start message from arbiter, generate commitment and dealings. If it is a DKG, the commitment is
44//! a random polynomial of degree `2f`. If it is a reshare, the commitment must be consistent with the
45//! previous group polynomial.
46//!
47//! ## [Dealer] Step 2: Distribute Commitment and Dealings
48//!
49//! Distribute generated commitment and corresponding dealings to each player over an encrypted channel.
50//!
51//! ## [Player] Step 3: Verify Dealing and Send Acknowledgement
52//!
53//! Verify incoming dealing against provided commitment (additionally comparing the commitment to the previous group
54//! polynomial, if reshare). If the dealing is valid, send an acknowledgement back to the dealer.
55//!
56//! To protect against a dealer sending different commitments to different players, players must sign this
57//! acknowledgement over `(dealer, commitment)`.
58//!
59//! ## [Dealer] Step 4: Collect Acknowledgements and Send to Arbiter
60//!
61//! Collect acknowledgements from players. After `2t` has elapsed since Step 1 (up to `3t` from Step 0), check to
62//! see if at least `2f + 1` acknowledgements have been received (including self, if a player as well). If so, send the
63//! commitment, acknowledgements, and unencrypted dealings of players that did not send an acknowledgement to the
64//! arbiter. If not, exit.
65//!
66//! ## [Arbiter] Step 5: Select Commitments and Forward Reveals
67//!
68//! Select the first `2f + 1` commitments with at most `f` reveals. Forward these `2f + 1` commitments
69//! (and any reveals associated with each) to all players. If there do not exist `2f + 1` commitments with
70//! at most `f` reveals by time `4t`, exit.
71//!
72//! ## [Player] Step 6: Recover Group Polynomial and Derive Share
73//!
74//! If the round is successful, each player will receive `2f + 1` commitments and any dealings associated with said
75//! commitments they did not acknowledge (or that the dealer said they didn't acknowledge). With this, they can recover
76//! the new group polynomial and derive their share of the secret. If this distribution is not received by time `5t`, exit.
77//!
78//! # Synchrony Assumption
79//!
80//! Under synchrony (where `t` is the maximum amount of time it takes for a message to be sent between any two participants),
81//! this construction can be used to maintain a shared secret where at least `f + 1` honest players must participate to
82//! recover the shared secret (`2f + 1` threshold where at most `f` players are Byzantine). To see how this is true,
83//! first consider that in any successful round there must exist `2f + 1` commitments with at most `f` reveals. This implies
84//! that all players must have acknowledged or have access to a reveal for each of the `2f + 1` selected commitments (allowing
85//! them to derive their share). Next, consider that when the network is synchronous that all `2f + 1` honest players send
86//! acknowledgements to honest dealers before `2t`. Because `2f + 1` commitments must be chosen, at least `f + 1` commitments
87//! must be from honest dealers (where no honest player dealing is revealed). Even if the remaining `f` commitments are from
88//! Byzantine dealers, there will not be enough dealings to recover the derived share of any honest player (at most `f` of
89//! `2f + 1` dealings publicly revealed). Given all `2f + 1` honest players have access to their shares and it is not possible
90//! for a Byzantine player to derive any honest player's share, this claim holds.
91//!
92//! If the network is not synchronous, however, Byzantine players can collude to recover a shared secret with the
93//! participation of a single honest player (rather than `f + 1`) and `f + 1` honest players will each be able to derive
94//! the shared secret (if the Byzantine players reveal their shares). To see how this could be, consider a network where
95//! `f` honest participants are in one partition and (`f + 1` honest and `f` Byzantine participants) are in another. All
96//! `f` Byzantine players acknowledge dealings from the `f + 1` honest dealers. Participants in the second partition will
97//! complete a round and all the reveals will belong to the same set of `f` honest players (that are in the first partition).
98//! A colluding Byzantine adversary will then have access to their acknowledged `f` shares and the revealed `f` shares
99//! (requiring only the participation of a single honest player that was in their partition to recover the shared secret).
100//! If the Byzantine adversary reveals all of their (still private) shares at this time, each of the `f + 1` honest players
101//! that were in the second partition will be able to derive the shared secret without collusion (using their private share
102//! and the `2f` public shares). It will not be possible for any external observer, however, to recover the shared secret.
103//!
104//! ## Future Work: Dropping the Synchrony Assumption?
105//!
106//! It is possible to design a DKG/Resharing scheme that maintains a shared secret where at least `f + 1` honest players
107//! must participate to recover the shared secret that doesn't require a synchrony assumption (`2f + 1` threshold
108//! where at most `f` players are Byzantine). However, known constructions that satisfy this requirement require both
109//! broadcasting encrypted dealings publicly and employing Zero-Knowledge Proofs (ZKPs) to attest that encrypted dealings
110//! were generated correctly ([Groth21](https://eprint.iacr.org/2021/339), [Kate23](https://eprint.iacr.org/2023/451)).
111//!
112//! As of January 2025, these constructions are still considered novel (2-3 years in production), require stronger
113//! cryptographic assumptions, don't scale to hundreds of participants (unless dealers have powerful hardware), and provide
114//! observers the opportunity to brute force decrypt shares (even if honest players are online).
115//!
116//! # Tracking Complaints
117//!
118//! This crate does not provide an integrated mechanism for tracking complaints from players (of malicious dealers). However, it is
119//! possible to implement your own mechanism and to manually disqualify dealers from a given round in the arbiter. This decision was made
120//! because the mechanism for communicating commitments/shares/acknowledgements is highly dependent on the context in which this
121//! construction is used.
122//!
123//! # Example
124//!
125//! For a complete example of how to instantiate this crate, check out [commonware-vrf](https://docs.rs/commonware-vrf).
126
127pub 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        // Create shared RNG (for reproducibility)
211        let mut rng = StdRng::seed_from_u64(0);
212
213        // Create contributors (must be in sorted order)
214        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        // Create dealers
222        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        // Create players
232        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        // Create arbiter
245        let mut arb = Arbiter::<_, V>::new(
246            None,
247            contributors.clone(),
248            contributors.clone(),
249            concurrency,
250        );
251
252        // Check ready
253        assert!(!arb.ready());
254
255        // Send commitments and shares to players
256        for (dealer, mut dealer_obj) in dealers {
257            // Distribute shares to players
258            let (commitment, shares) = dealer_shares.get(&dealer).unwrap().clone();
259            for (player_idx, player) in contributors.iter().enumerate() {
260                // Process share
261                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                // Collect ack
271                dealer_obj.ack(player.clone()).unwrap();
272            }
273
274            // Finalize dealer
275            let output = dealer_obj.finalize().unwrap();
276
277            // Ensure no reveals required
278            assert!(output.inactive.is_empty());
279
280            // Send commitment and acks to arbiter
281            arb.commitment(dealer, commitment, output.active, Vec::new())
282                .unwrap();
283        }
284
285        // Check ready
286        assert!(arb.ready());
287
288        // Finalize arbiter
289        let (result, disqualified) = arb.finalize();
290
291        // Verify disqualifications are empty (only occurs if invalid commitment or missing)
292        assert_eq!(disqualified.len(), (n_0 - dealers_0) as usize);
293
294        // Verify result
295        let output: Output<V> = result.unwrap();
296
297        // Ensure right number of commitments picked
298        let expected_commitments = quorum(n_0) as usize;
299        assert_eq!(output.commitments.len(), expected_commitments);
300
301        // Ensure no reveals required
302        assert!(output.reveals.is_empty());
303
304        // Distribute commitments to players and recover public key
305        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        // Test that can generate proof-of-possession
316        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        // Create reshare players (assume no overlap)
328        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        // Create reshare dealers
336        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        // Create reshare player objects
350        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        // Create arbiter
363        let mut arb = Arbiter::<_, V>::new(
364            Some(output.public),
365            contributors.clone(),
366            reshare_players.clone(),
367            concurrency,
368        );
369
370        // Check ready
371        assert!(!arb.ready());
372
373        // Send commitments and shares to players
374        for (dealer, mut dealer_obj) in reshare_dealers {
375            // Distribute shares to players
376            let (commitment, shares) = reshare_shares.get(&dealer).unwrap().clone();
377            for (player_idx, player) in reshare_players.iter().enumerate() {
378                // Process share
379                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                // Collect ack
389                dealer_obj.ack(player.clone()).unwrap();
390            }
391
392            // Finalize dealer
393            let output = dealer_obj.finalize().unwrap();
394
395            // Ensure no reveals required
396            assert!(output.inactive.is_empty());
397
398            // Send commitment and acks to arbiter
399            arb.commitment(dealer, commitment, output.active, Vec::new())
400                .unwrap();
401        }
402
403        // Check ready
404        assert!(arb.ready());
405
406        // Finalize arbiter
407        let (result, disqualified) = arb.finalize();
408
409        // Verify disqualifications are empty (only occurs if invalid commitment)
410        assert_eq!(disqualified.len(), (n_0 - dealers_1) as usize);
411
412        // Verify result
413        let output: Output<V> = result.unwrap();
414
415        // Ensure right number of commitments picked
416        let expected_commitments = quorum(n_0) as usize;
417        assert_eq!(output.commitments.len(), expected_commitments);
418
419        // Ensure no reveals required
420        assert!(output.reveals.is_empty());
421
422        // Distribute commitments to players and recover public key
423        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        // Test that can generate proof-of-possession
435        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        // Initialize test
481        let n = 5;
482        let mut rng = StdRng::seed_from_u64(0);
483
484        // Create contributors (must be in sorted order)
485        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        // Create dealer
493        let (_, _, shares) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
494
495        // Create unrelated commitment of correct degree
496        let t = quorum(n);
497        let (public, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
498
499        // Create player
500        let mut player = Player::<_, MinSig>::new(
501            contributors[0].clone(),
502            None,
503            contributors.clone(),
504            contributors.clone(),
505            1,
506        );
507
508        // Send invalid commitment to player
509        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        // Initialize test
516        let n = 5;
517        let mut rng = StdRng::seed_from_u64(0);
518
519        // Create contributors (must be in sorted order)
520        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        // Create dealer
528        let (_, commitment, shares) =
529            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
530
531        // Create unrelated commitment of correct degree
532        let t = quorum(n);
533        let (other_commitment, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
534
535        // Create player
536        let mut player = Player::<_, MinSig>::new(
537            contributors[0].clone(),
538            None,
539            contributors.clone(),
540            contributors.clone(),
541            1,
542        );
543
544        // Send valid commitment to player
545        player
546            .share(contributors[0].clone(), commitment, shares[0].clone())
547            .unwrap();
548
549        // Send alternative commitment to player
550        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        // Initialize test
557        let n = 5;
558        let mut rng = StdRng::seed_from_u64(0);
559
560        // Create contributors (must be in sorted order)
561        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        // Create dealer
569        let (_, commitment, shares) =
570            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
571
572        // Create unrelated commitment of correct degree
573        let t = quorum(n);
574        let (_, other_shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
575
576        // Create player
577        let mut player = Player::<_, MinSig>::new(
578            contributors[0].clone(),
579            None,
580            contributors.clone(),
581            contributors.clone(),
582            1,
583        );
584
585        // Send valid share to player
586        player
587            .share(
588                contributors[0].clone(),
589                commitment.clone(),
590                shares[0].clone(),
591            )
592            .unwrap();
593
594        // Send alternative share to player
595        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        // Initialize test
602        let n = 5;
603        let mut rng = StdRng::seed_from_u64(0);
604
605        // Create contributors (must be in sorted order)
606        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        // Create dealer
614        let (_, commitment, shares) =
615            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
616
617        // Create player
618        let mut player = Player::<_, MinSig>::new(
619            contributors[0].clone(),
620            None,
621            contributors.clone(),
622            contributors.clone(),
623            1,
624        );
625
626        // Send valid share to player
627        player
628            .share(
629                contributors[0].clone(),
630                commitment.clone(),
631                shares[0].clone(),
632            )
633            .unwrap();
634
635        // Send alternative share to player
636        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        // Initialize test
643        let n = 5;
644        let mut rng = StdRng::seed_from_u64(0);
645
646        // Create contributors (must be in sorted order)
647        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        // Create dealer
655        let (_, commitment, shares) =
656            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
657
658        // Create player
659        let mut player = Player::<_, MinSig>::new(
660            contributors[0].clone(),
661            None,
662            contributors.clone(),
663            contributors.clone(),
664            1,
665        );
666
667        // Send misdirected share to player
668        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        // Initialize test
679        let n = 5;
680        let mut rng = StdRng::seed_from_u64(0);
681
682        // Create contributors (must be in sorted order)
683        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        // Create dealer
691        let (_, commitment, shares) =
692            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
693
694        // Create player
695        let mut player = Player::<_, MinSig>::new(
696            contributors[0].clone(),
697            None,
698            contributors.clone(),
699            contributors.clone(),
700            1,
701        );
702
703        // Send share from invalid dealer
704        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        // Create arbiter
709        let mut arb =
710            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
711
712        // Send commitment from invalid dealer
713        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        // Initialize test
720        let n = 5;
721        let mut rng = StdRng::seed_from_u64(0);
722
723        // Create contributors (must be in sorted order)
724        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        // Create dealer
732        let (_, _, shares) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
733
734        // Create invalid commitment
735        let (public, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n * 2, 1);
736
737        // Create player
738        let mut player = Player::<_, MinSig>::new(
739            contributors[0].clone(),
740            None,
741            contributors.clone(),
742            contributors.clone(),
743            1,
744        );
745
746        // Send invalid commitment to player
747        let result = player.share(contributors[0].clone(), public.clone(), shares[0].clone());
748        assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
749
750        // Create arbiter
751        let mut arb =
752            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
753
754        // Send invalid commitment to arbiter
755        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        // Initialize test
767        let n = 5;
768        let mut rng = StdRng::seed_from_u64(0);
769
770        // Create contributors (must be in sorted order)
771        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        // Create dealer
779        let (_, commitment, shares) =
780            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
781
782        // Create arbiter
783        let mut arb =
784            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
785
786        // Add commitment to arbiter
787        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        // Initialize test
799        let n = 11;
800        let q = quorum(n as u32) as usize;
801        let mut rng = StdRng::seed_from_u64(0);
802
803        // Create contributors (must be in sorted order)
804        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        // Create arbiter
812        let mut arb =
813            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
814
815        // Create dealers
816        let mut commitments = Vec::with_capacity(n);
817        let mut reveals = Vec::with_capacity(n);
818        for con in &contributors {
819            // Create dealer
820            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            // Add commitment to arbiter
826            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        // Finalize arbiter
833        let (result, _) = arb.finalize();
834        let output = result.unwrap();
835
836        // Ensure commitments and reveals are correct
837        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        // Initialize test
854        let n = 5;
855        let mut rng = StdRng::seed_from_u64(0);
856
857        // Create contributors (must be in sorted order)
858        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        // Create dealer
866        let (_, commitment, shares) =
867            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
868
869        // Create arbiter
870        let mut arb =
871            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
872
873        // Add commitment to arbiter
874        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        // Add commitment to arbiter (again)
883        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        // Initialize test
895        let n = 5;
896        let mut rng = StdRng::seed_from_u64(0);
897
898        // Create contributors (must be in sorted order)
899        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        // Create dealer
907        let (_, commitment, shares) =
908            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
909
910        // Create arbiter
911        let mut arb =
912            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
913
914        // Add commitment to arbiter
915        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        // Initialize test
927        let n = 5;
928        let mut rng = StdRng::seed_from_u64(0);
929
930        // Create contributors (must be in sorted order)
931        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        // Create dealer
939        let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
940
941        // Create arbiter
942        let mut arb =
943            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
944
945        // Add commitment to arbiter
946        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        // Add valid commitment to arbiter after disqualified
955        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        // Initialize test
967        let n = 5;
968        let mut rng = StdRng::seed_from_u64(0);
969
970        // Create contributors (must be in sorted order)
971        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        // Create dealer
979        let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
980
981        // Create arbiter
982        let mut arb =
983            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
984
985        // Disqualify dealer
986        arb.disqualify(contributors[0].clone());
987
988        // Add valid commitment to arbiter after disqualified
989        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        // Initialize test
1001        let n = 5;
1002        let mut rng = StdRng::seed_from_u64(0);
1003
1004        // Create contributors (must be in sorted order)
1005        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        // Create dealer
1013        let (_, commitment, shares) =
1014            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1015
1016        // Create arbiter
1017        let mut arb =
1018            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1019
1020        // Add commitment to arbiter
1021        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        // Initialize test
1033        let n = 5;
1034        let mut rng = StdRng::seed_from_u64(0);
1035
1036        // Create contributors (must be in sorted order)
1037        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        // Create dealer
1045        let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1046
1047        // Create invalid shares
1048        let t = quorum(n);
1049        let (_, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
1050
1051        // Create arbiter
1052        let mut arb =
1053            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1054
1055        // Add commitment to arbiter
1056        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        // Initialize test
1068        let n = 5;
1069        let mut rng = StdRng::seed_from_u64(0);
1070
1071        // Create contributors (must be in sorted order)
1072        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        // Create dealer
1080        let (_, commitment, shares) =
1081            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1082
1083        // Create arbiter
1084        let mut arb =
1085            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1086
1087        // Swap share value
1088        let mut share = shares[3].clone();
1089        share.index = 4;
1090
1091        // Add commitment to arbiter
1092        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        // Initialize test
1104        let n = 5;
1105        let mut rng = StdRng::seed_from_u64(0);
1106
1107        // Create contributors (must be in sorted order)
1108        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        // Create dealer
1116        let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1117
1118        // Create arbiter
1119        let mut arb =
1120            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1121
1122        // Add commitment to arbiter
1123        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        // Initialize test
1135        let n = 5;
1136        let mut rng = StdRng::seed_from_u64(0);
1137
1138        // Create contributors (must be in sorted order)
1139        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        // Create dealer
1147        let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1148
1149        // Create arbiter
1150        let mut arb =
1151            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1152
1153        // Add commitment to arbiter
1154        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        // Initialize test
1166        let n = 5;
1167        let mut rng = StdRng::seed_from_u64(0);
1168
1169        // Create contributors (must be in sorted order)
1170        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        // Create dealer
1178        let (_, commitment, shares) =
1179            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1180
1181        // Create arbiter
1182        let mut arb =
1183            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1184
1185        // Swap share value
1186        let mut share = shares[3].clone();
1187        share.index = 10;
1188
1189        // Add commitment to arbiter
1190        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        // Initialize test
1202        let n = 5;
1203        let mut rng = StdRng::seed_from_u64(0);
1204
1205        // Create contributors (must be in sorted order)
1206        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        // Create dealer
1214        let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1215
1216        // Ack all players
1217        for player in &contributors {
1218            dealer.ack(player.clone()).unwrap();
1219        }
1220
1221        // Finalize dealer
1222        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        // Initialize test
1230        let n = 5;
1231        let mut rng = StdRng::seed_from_u64(0);
1232
1233        // Create contributors (must be in sorted order)
1234        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        // Create dealer
1242        let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1243
1244        // Ack all players
1245        for player in contributors.iter().take(4) {
1246            dealer.ack(player.clone()).unwrap();
1247        }
1248
1249        // Finalize dealer
1250        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        // Initialize test
1258        let n = 5;
1259        let mut rng = StdRng::seed_from_u64(0);
1260
1261        // Create contributors (must be in sorted order)
1262        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        // Create dealer
1270        let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1271
1272        // Ack all players
1273        for player in contributors.iter().take(2) {
1274            dealer.ack(player.clone()).unwrap();
1275        }
1276
1277        // Finalize dealer
1278        assert!(dealer.finalize().is_none());
1279    }
1280
1281    #[test]
1282    fn test_dealer_duplicate_ack() {
1283        // Initialize test
1284        let n = 5;
1285        let mut rng = StdRng::seed_from_u64(0);
1286
1287        // Create contributors (must be in sorted order)
1288        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        // Create dealer
1296        let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1297
1298        // Ack player
1299        let player = contributors[0].clone();
1300        dealer.ack(player.clone()).unwrap();
1301
1302        // Ack player (again)
1303        let result = dealer.ack(player);
1304        assert!(matches!(result, Err(Error::DuplicateAck)));
1305    }
1306
1307    #[test]
1308    fn test_dealer_invalid_player() {
1309        // Initialize test
1310        let n = 5;
1311        let mut rng = StdRng::seed_from_u64(0);
1312
1313        // Create contributors (must be in sorted order)
1314        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        // Create dealer
1322        let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1323
1324        // Ack invalid player
1325        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        // Initialize test
1333        let n = 11;
1334        let q = quorum(n as u32) as usize;
1335        let mut rng = StdRng::seed_from_u64(0);
1336
1337        // Create contributors (must be in sorted order)
1338        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        // Create player
1346        let mut player = Player::<_, MinSig>::new(
1347            contributors[0].clone(),
1348            None,
1349            contributors.clone(),
1350            contributors.clone(),
1351            1,
1352        );
1353
1354        // Send shares to player
1355        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        // Finalize player with reveal
1366        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        // Initialize test
1378        let n = 11;
1379        let q = quorum(n as u32) as usize;
1380        let mut rng = StdRng::seed_from_u64(0);
1381
1382        // Create contributors (must be in sorted order)
1383        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        // Create player
1391        let mut player = Player::<_, MinSig>::new(
1392            contributors[0].clone(),
1393            None,
1394            contributors.clone(),
1395            contributors.clone(),
1396            1,
1397        );
1398
1399        // Send shares to player
1400        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        // Finalize player with reveal
1411        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        // Initialize test
1421        let n = 5;
1422        let mut rng = StdRng::seed_from_u64(0);
1423
1424        // Create contributors (must be in sorted order)
1425        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        // Create player
1433        let mut player = Player::<_, MinSig>::new(
1434            contributors[0].clone(),
1435            None,
1436            contributors.clone(),
1437            contributors.clone(),
1438            1,
1439        );
1440
1441        // Send shares to player
1442        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        // Finalize player with reveal
1453        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        // Initialize test
1460        let n = 11;
1461        let q = quorum(n as u32) as usize;
1462        let mut rng = StdRng::seed_from_u64(0);
1463
1464        // Create contributors (must be in sorted order)
1465        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        // Create player
1473        let mut player = Player::<_, MinSig>::new(
1474            contributors[0].clone(),
1475            None,
1476            contributors.clone(),
1477            contributors.clone(),
1478            1,
1479        );
1480
1481        // Send shares to player
1482        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        // Finalize player with reveal
1493        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        // Initialize test
1506        let n = 11;
1507        let q = quorum(n as u32) as usize;
1508        let mut rng = StdRng::seed_from_u64(0);
1509
1510        // Create contributors (must be in sorted order)
1511        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        // Create player
1519        let mut player = Player::<_, MinSig>::new(
1520            contributors[0].clone(),
1521            None,
1522            contributors.clone(),
1523            contributors.clone(),
1524            1,
1525        );
1526
1527        // Send shares to player
1528        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        // Finalize player with reveal
1539        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        // Initialize test
1551        let n = 11;
1552        let q = quorum(n as u32) as usize;
1553        let mut rng = StdRng::seed_from_u64(0);
1554
1555        // Create contributors (must be in sorted order)
1556        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        // Create player
1564        let mut player = Player::<_, MinSig>::new(
1565            contributors[0].clone(),
1566            None,
1567            contributors.clone(),
1568            contributors.clone(),
1569            1,
1570        );
1571
1572        // Send shares to player
1573        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        // Finalize player with reveal
1584        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}