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;
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        // Create shared RNG (for reproducibility)
214        let mut rng = StdRng::seed_from_u64(0);
215
216        // Create contributors (must be in sorted order)
217        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        // Create dealers
225        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        // Create players
235        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        // Create arbiter
248        let mut arb = Arbiter::<_, V>::new(
249            None,
250            contributors.clone(),
251            contributors.clone(),
252            concurrency,
253        );
254
255        // Check ready
256        assert!(!arb.ready());
257
258        // Send commitments and shares to players
259        for (dealer, mut dealer_obj) in dealers {
260            // Distribute shares to players
261            let (commitment, shares) = dealer_shares.get(&dealer).unwrap().clone();
262            for (player_idx, player) in contributors.iter().enumerate() {
263                // Process share
264                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                // Collect ack
274                dealer_obj.ack(player.clone()).unwrap();
275            }
276
277            // Finalize dealer
278            let output = dealer_obj.finalize().unwrap();
279
280            // Ensure no reveals required
281            assert!(output.inactive.is_empty());
282
283            // Send commitment and acks to arbiter
284            arb.commitment(dealer, commitment, output.active, Vec::new())
285                .unwrap();
286        }
287
288        // Check ready
289        assert!(arb.ready());
290
291        // Finalize arbiter
292        let (result, disqualified) = arb.finalize();
293
294        // Verify disqualifications are empty (only occurs if invalid commitment or missing)
295        assert_eq!(disqualified.len(), (n_0 - dealers_0) as usize);
296
297        // Verify result
298        let output: Output<V> = result.unwrap();
299
300        // Ensure right number of commitments picked
301        let expected_commitments = quorum(n_0) as usize;
302        assert_eq!(output.commitments.len(), expected_commitments);
303
304        // Ensure no reveals required
305        assert!(output.reveals.is_empty());
306
307        // Distribute commitments to players and recover public key
308        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        // Test that can generate proof-of-possession
319        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        // Create reshare players (assume no overlap)
331        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        // Create reshare dealers
339        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        // Create reshare player objects
353        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        // Create arbiter
366        let mut arb = Arbiter::<_, V>::new(
367            Some(output.public),
368            contributors.clone(),
369            reshare_players.clone(),
370            concurrency,
371        );
372
373        // Check ready
374        assert!(!arb.ready());
375
376        // Send commitments and shares to players
377        for (dealer, mut dealer_obj) in reshare_dealers {
378            // Distribute shares to players
379            let (commitment, shares) = reshare_shares.get(&dealer).unwrap().clone();
380            for (player_idx, player) in reshare_players.iter().enumerate() {
381                // Process share
382                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                // Collect ack
392                dealer_obj.ack(player.clone()).unwrap();
393            }
394
395            // Finalize dealer
396            let output = dealer_obj.finalize().unwrap();
397
398            // Ensure no reveals required
399            assert!(output.inactive.is_empty());
400
401            // Send commitment and acks to arbiter
402            arb.commitment(dealer, commitment, output.active, Vec::new())
403                .unwrap();
404        }
405
406        // Check ready
407        assert!(arb.ready());
408
409        // Finalize arbiter
410        let (result, disqualified) = arb.finalize();
411
412        // Verify disqualifications are empty (only occurs if invalid commitment)
413        assert_eq!(disqualified.len(), (n_0 - dealers_1) as usize);
414
415        // Verify result
416        let output: Output<V> = result.unwrap();
417
418        // Ensure right number of commitments picked
419        let expected_commitments = quorum(n_0) as usize;
420        assert_eq!(output.commitments.len(), expected_commitments);
421
422        // Ensure no reveals required
423        assert!(output.reveals.is_empty());
424
425        // Distribute commitments to players and recover public key
426        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        // Test that can generate proof-of-possession
438        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        // Initialize test
484        let n = 5;
485        let mut rng = StdRng::seed_from_u64(0);
486
487        // Create contributors (must be in sorted order)
488        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        // Create dealer
496        let (_, _, shares) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
497
498        // Create unrelated commitment of correct degree
499        let t = quorum(n);
500        let (public, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
501
502        // Create player
503        let mut player = Player::<_, MinSig>::new(
504            contributors[0].clone(),
505            None,
506            contributors.clone(),
507            contributors.clone(),
508            1,
509        );
510
511        // Send invalid commitment to player
512        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        // Initialize test
519        let n = 5;
520        let mut rng = StdRng::seed_from_u64(0);
521
522        // Create contributors (must be in sorted order)
523        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        // Create dealer
531        let (_, commitment, shares) =
532            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
533
534        // Create unrelated commitment of correct degree
535        let t = quorum(n);
536        let (other_commitment, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
537
538        // Create player
539        let mut player = Player::<_, MinSig>::new(
540            contributors[0].clone(),
541            None,
542            contributors.clone(),
543            contributors.clone(),
544            1,
545        );
546
547        // Send valid commitment to player
548        player
549            .share(contributors[0].clone(), commitment, shares[0].clone())
550            .unwrap();
551
552        // Send alternative commitment to player
553        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        // Initialize test
560        let n = 5;
561        let mut rng = StdRng::seed_from_u64(0);
562
563        // Create contributors (must be in sorted order)
564        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        // Create dealer
572        let (_, commitment, shares) =
573            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
574
575        // Create unrelated commitment of correct degree
576        let t = quorum(n);
577        let (_, other_shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
578
579        // Create player
580        let mut player = Player::<_, MinSig>::new(
581            contributors[0].clone(),
582            None,
583            contributors.clone(),
584            contributors.clone(),
585            1,
586        );
587
588        // Send valid share to player
589        player
590            .share(
591                contributors[0].clone(),
592                commitment.clone(),
593                shares[0].clone(),
594            )
595            .unwrap();
596
597        // Send alternative share to player
598        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        // Initialize test
605        let n = 5;
606        let mut rng = StdRng::seed_from_u64(0);
607
608        // Create contributors (must be in sorted order)
609        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        // Create dealer
617        let (_, commitment, shares) =
618            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
619
620        // Create player
621        let mut player = Player::<_, MinSig>::new(
622            contributors[0].clone(),
623            None,
624            contributors.clone(),
625            contributors.clone(),
626            1,
627        );
628
629        // Send valid share to player
630        player
631            .share(
632                contributors[0].clone(),
633                commitment.clone(),
634                shares[0].clone(),
635            )
636            .unwrap();
637
638        // Send alternative share to player
639        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        // Initialize test
646        let n = 5;
647        let mut rng = StdRng::seed_from_u64(0);
648
649        // Create contributors (must be in sorted order)
650        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        // Create dealer
658        let (_, commitment, shares) =
659            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
660
661        // Create player
662        let mut player = Player::<_, MinSig>::new(
663            contributors[0].clone(),
664            None,
665            contributors.clone(),
666            contributors.clone(),
667            1,
668        );
669
670        // Send misdirected share to player
671        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        // Initialize test
682        let n = 5;
683        let mut rng = StdRng::seed_from_u64(0);
684
685        // Create contributors (must be in sorted order)
686        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        // Create dealer
694        let (_, commitment, shares) =
695            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
696
697        // Create player
698        let mut player = Player::<_, MinSig>::new(
699            contributors[0].clone(),
700            None,
701            contributors.clone(),
702            contributors.clone(),
703            1,
704        );
705
706        // Send share from invalid dealer
707        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        // Create arbiter
712        let mut arb =
713            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
714
715        // Send commitment from invalid dealer
716        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        // Initialize test
723        let n = 5;
724        let mut rng = StdRng::seed_from_u64(0);
725
726        // Create contributors (must be in sorted order)
727        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        // Create dealer
735        let (_, _, shares) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
736
737        // Create invalid commitment
738        let (public, _) = ops::generate_shares::<_, MinSig>(&mut rng, None, n * 2, 1);
739
740        // Create player
741        let mut player = Player::<_, MinSig>::new(
742            contributors[0].clone(),
743            None,
744            contributors.clone(),
745            contributors.clone(),
746            1,
747        );
748
749        // Send invalid commitment to player
750        let result = player.share(contributors[0].clone(), public.clone(), shares[0].clone());
751        assert!(matches!(result, Err(Error::CommitmentWrongDegree)));
752
753        // Create arbiter
754        let mut arb =
755            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
756
757        // Send invalid commitment to arbiter
758        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        // Initialize test
770        let n = 5;
771        let mut rng = StdRng::seed_from_u64(0);
772
773        // Create contributors (must be in sorted order)
774        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        // Create dealer
782        let (_, commitment, shares) =
783            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
784
785        // Create arbiter
786        let mut arb =
787            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
788
789        // Add commitment to arbiter
790        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        // Initialize test
802        let n = 11;
803        let q = quorum(n as u32) as usize;
804        let mut rng = StdRng::seed_from_u64(0);
805
806        // Create contributors (must be in sorted order)
807        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        // Create arbiter
815        let mut arb =
816            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
817
818        // Create dealers
819        let mut commitments = Vec::with_capacity(n);
820        let mut reveals = Vec::with_capacity(n);
821        for con in &contributors {
822            // Create dealer
823            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            // Add commitment to arbiter
829            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        // Finalize arbiter
836        let (result, _) = arb.finalize();
837        let output = result.unwrap();
838
839        // Ensure commitments and reveals are correct
840        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        // Initialize test
857        let n = 5;
858        let mut rng = StdRng::seed_from_u64(0);
859
860        // Create contributors (must be in sorted order)
861        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        // Create dealer
869        let (_, commitment, shares) =
870            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
871
872        // Create arbiter
873        let mut arb =
874            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
875
876        // Add commitment to arbiter
877        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        // Add commitment to arbiter (again)
886        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        // Initialize test
898        let n = 5;
899        let mut rng = StdRng::seed_from_u64(0);
900
901        // Create contributors (must be in sorted order)
902        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        // Create dealer
910        let (_, commitment, shares) =
911            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
912
913        // Create arbiter
914        let mut arb =
915            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
916
917        // Add commitment to arbiter
918        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        // Initialize test
930        let n = 5;
931        let mut rng = StdRng::seed_from_u64(0);
932
933        // Create contributors (must be in sorted order)
934        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        // Create dealer
942        let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
943
944        // Create arbiter
945        let mut arb =
946            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
947
948        // Add commitment to arbiter
949        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        // Add valid commitment to arbiter after disqualified
958        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        // Initialize test
970        let n = 5;
971        let mut rng = StdRng::seed_from_u64(0);
972
973        // Create contributors (must be in sorted order)
974        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        // Create dealer
982        let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
983
984        // Create arbiter
985        let mut arb =
986            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
987
988        // Disqualify dealer
989        arb.disqualify(contributors[0].clone());
990
991        // Add valid commitment to arbiter after disqualified
992        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        // Initialize test
1004        let n = 5;
1005        let mut rng = StdRng::seed_from_u64(0);
1006
1007        // Create contributors (must be in sorted order)
1008        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        // Create dealer
1016        let (_, commitment, shares) =
1017            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1018
1019        // Create arbiter
1020        let mut arb =
1021            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1022
1023        // Add commitment to arbiter
1024        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        // Initialize test
1036        let n = 5;
1037        let mut rng = StdRng::seed_from_u64(0);
1038
1039        // Create contributors (must be in sorted order)
1040        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        // Create dealer
1048        let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1049
1050        // Create invalid shares
1051        let t = quorum(n);
1052        let (_, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, n, t);
1053
1054        // Create arbiter
1055        let mut arb =
1056            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1057
1058        // Add commitment to arbiter
1059        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        // Initialize test
1071        let n = 5;
1072        let mut rng = StdRng::seed_from_u64(0);
1073
1074        // Create contributors (must be in sorted order)
1075        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        // Create dealer
1083        let (_, commitment, shares) =
1084            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1085
1086        // Create arbiter
1087        let mut arb =
1088            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1089
1090        // Swap share value
1091        let mut share = shares[3].clone();
1092        share.index = 4;
1093
1094        // Add commitment to arbiter
1095        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        // Initialize test
1107        let n = 5;
1108        let mut rng = StdRng::seed_from_u64(0);
1109
1110        // Create contributors (must be in sorted order)
1111        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        // Create dealer
1119        let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1120
1121        // Create arbiter
1122        let mut arb =
1123            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1124
1125        // Add commitment to arbiter
1126        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        // Initialize test
1138        let n = 5;
1139        let mut rng = StdRng::seed_from_u64(0);
1140
1141        // Create contributors (must be in sorted order)
1142        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        // Create dealer
1150        let (_, commitment, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1151
1152        // Create arbiter
1153        let mut arb =
1154            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1155
1156        // Add commitment to arbiter
1157        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        // Initialize test
1169        let n = 5;
1170        let mut rng = StdRng::seed_from_u64(0);
1171
1172        // Create contributors (must be in sorted order)
1173        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        // Create dealer
1181        let (_, commitment, shares) =
1182            Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1183
1184        // Create arbiter
1185        let mut arb =
1186            Arbiter::<_, MinSig>::new(None, contributors.clone(), contributors.clone(), 1);
1187
1188        // Swap share value
1189        let mut share = shares[3].clone();
1190        share.index = 10;
1191
1192        // Add commitment to arbiter
1193        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        // Initialize test
1205        let n = 5;
1206        let mut rng = StdRng::seed_from_u64(0);
1207
1208        // Create contributors (must be in sorted order)
1209        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        // Create dealer
1217        let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1218
1219        // Ack all players
1220        for player in &contributors {
1221            dealer.ack(player.clone()).unwrap();
1222        }
1223
1224        // Finalize dealer
1225        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        // Initialize test
1233        let n = 5;
1234        let mut rng = StdRng::seed_from_u64(0);
1235
1236        // Create contributors (must be in sorted order)
1237        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        // Create dealer
1245        let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1246
1247        // Ack all players
1248        for player in contributors.iter().take(4) {
1249            dealer.ack(player.clone()).unwrap();
1250        }
1251
1252        // Finalize dealer
1253        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        // Initialize test
1261        let n = 5;
1262        let mut rng = StdRng::seed_from_u64(0);
1263
1264        // Create contributors (must be in sorted order)
1265        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        // Create dealer
1273        let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1274
1275        // Ack all players
1276        for player in contributors.iter().take(2) {
1277            dealer.ack(player.clone()).unwrap();
1278        }
1279
1280        // Finalize dealer
1281        assert!(dealer.finalize().is_none());
1282    }
1283
1284    #[test]
1285    fn test_dealer_duplicate_ack() {
1286        // Initialize test
1287        let n = 5;
1288        let mut rng = StdRng::seed_from_u64(0);
1289
1290        // Create contributors (must be in sorted order)
1291        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        // Create dealer
1299        let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1300
1301        // Ack player
1302        let player = contributors[0].clone();
1303        dealer.ack(player.clone()).unwrap();
1304
1305        // Ack player (again)
1306        let result = dealer.ack(player);
1307        assert!(matches!(result, Err(Error::DuplicateAck)));
1308    }
1309
1310    #[test]
1311    fn test_dealer_invalid_player() {
1312        // Initialize test
1313        let n = 5;
1314        let mut rng = StdRng::seed_from_u64(0);
1315
1316        // Create contributors (must be in sorted order)
1317        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        // Create dealer
1325        let (mut dealer, _, _) = Dealer::<_, MinSig>::new(&mut rng, None, contributors.clone());
1326
1327        // Ack invalid player
1328        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        // Initialize test
1336        let n = 11;
1337        let q = quorum(n as u32) as usize;
1338        let mut rng = StdRng::seed_from_u64(0);
1339
1340        // Create contributors (must be in sorted order)
1341        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        // Create player
1349        let mut player = Player::<_, MinSig>::new(
1350            contributors[0].clone(),
1351            None,
1352            contributors.clone(),
1353            contributors.clone(),
1354            1,
1355        );
1356
1357        // Send shares to player
1358        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        // Finalize player with reveal
1369        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        // Initialize test
1381        let n = 11;
1382        let q = quorum(n as u32) as usize;
1383        let mut rng = StdRng::seed_from_u64(0);
1384
1385        // Create contributors (must be in sorted order)
1386        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        // Create player
1394        let mut player = Player::<_, MinSig>::new(
1395            contributors[0].clone(),
1396            None,
1397            contributors.clone(),
1398            contributors.clone(),
1399            1,
1400        );
1401
1402        // Send shares to player
1403        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        // Finalize player with reveal
1414        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        // Initialize test
1424        let n = 5;
1425        let mut rng = StdRng::seed_from_u64(0);
1426
1427        // Create contributors (must be in sorted order)
1428        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        // Create player
1436        let mut player = Player::<_, MinSig>::new(
1437            contributors[0].clone(),
1438            None,
1439            contributors.clone(),
1440            contributors.clone(),
1441            1,
1442        );
1443
1444        // Send shares to player
1445        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        // Finalize player with reveal
1456        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        // Initialize test
1463        let n = 11;
1464        let q = quorum(n as u32) as usize;
1465        let mut rng = StdRng::seed_from_u64(0);
1466
1467        // Create contributors (must be in sorted order)
1468        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        // Create player
1476        let mut player = Player::<_, MinSig>::new(
1477            contributors[0].clone(),
1478            None,
1479            contributors.clone(),
1480            contributors.clone(),
1481            1,
1482        );
1483
1484        // Send shares to player
1485        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        // Finalize player with reveal
1496        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        // Initialize test
1509        let n = 11;
1510        let q = quorum(n as u32) as usize;
1511        let mut rng = StdRng::seed_from_u64(0);
1512
1513        // Create contributors (must be in sorted order)
1514        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        // Create player
1522        let mut player = Player::<_, MinSig>::new(
1523            contributors[0].clone(),
1524            None,
1525            contributors.clone(),
1526            contributors.clone(),
1527            1,
1528        );
1529
1530        // Send shares to player
1531        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        // Finalize player with reveal
1542        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        // Initialize test
1554        let n = 11;
1555        let q = quorum(n as u32) as usize;
1556        let mut rng = StdRng::seed_from_u64(0);
1557
1558        // Create contributors (must be in sorted order)
1559        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        // Create player
1567        let mut player = Player::<_, MinSig>::new(
1568            contributors[0].clone(),
1569            None,
1570            contributors.clone(),
1571            contributors.clone(),
1572            1,
1573        );
1574
1575        // Send shares to player
1576        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        // Finalize player with reveal
1587        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}