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