wsts/state_machine/coordinator/
mod.rs

1use crate::{
2    common::{PolyCommitment, Signature, SignatureShare},
3    curve::{
4        ecdsa,
5        point::{Error as PointError, Point},
6        scalar::Scalar,
7    },
8    errors::AggregatorError,
9    net::{DkgEnd, DkgPrivateShares, DkgPublicShares, NonceResponse, Packet, SignatureType},
10    state_machine::{DkgFailure, OperationResult, PublicKeys, StateMachine},
11    taproot::SchnorrProof,
12};
13use core::{cmp::PartialEq, fmt::Debug, num::TryFromIntError};
14use hashbrown::{HashMap, HashSet};
15use std::{
16    collections::BTreeMap,
17    fmt,
18    time::{Duration, Instant},
19};
20
21#[derive(Clone, Default, Debug, PartialEq)]
22/// Coordinator states
23pub enum State {
24    /// The coordinator is idle
25    #[default]
26    Idle,
27    /// The coordinator is asking signers to send public shares
28    DkgPublicDistribute,
29    /// The coordinator is gathering public shares
30    DkgPublicGather,
31    /// The coordinator is asking signers to send private shares
32    DkgPrivateDistribute,
33    /// The coordinator is gathering private shares
34    DkgPrivateGather,
35    /// The coordinator is asking signers to compute shares and send end
36    DkgEndDistribute,
37    /// The coordinator is gathering DKG End messages
38    DkgEndGather,
39    /// The coordinator is requesting nonces
40    NonceRequest(SignatureType),
41    /// The coordinator is gathering nonces
42    NonceGather(SignatureType),
43    /// The coordinator is requesting signature shares
44    SigShareRequest(SignatureType),
45    /// The coordinator is gathering signature shares
46    SigShareGather(SignatureType),
47}
48
49#[derive(thiserror::Error, Clone, Debug)]
50#[allow(clippy::large_enum_variant)]
51/// The error type for the coordinator
52pub enum Error {
53    /// A bad state change was made
54    #[error("Bad State Change: {0}")]
55    BadStateChange(String),
56    /// A bad dkg_id in received message
57    #[error("Bad dkg_id: got {0} expected {1}")]
58    BadDkgId(u64, u64),
59    /// A bad sign_id in received message
60    #[error("Bad sign_id: got {0} expected {1}")]
61    BadSignId(u64, u64),
62    /// A bad sign_iter_id in received message
63    #[error("Bad sign_iter_id: got {0} expected {1}")]
64    BadSignIterId(u64, u64),
65    /// A malicious signer sent the received message
66    #[error("Malicious signer {0}")]
67    MaliciousSigner(u32),
68    /// SignatureAggregator error
69    #[error("Aggregator: {0}")]
70    Aggregator(AggregatorError),
71    /// Schnorr proof failed to verify
72    #[error("Schnorr Proof failed to verify")]
73    SchnorrProofFailed,
74    /// No aggregate public key set
75    #[error("No aggregate public key set")]
76    MissingAggregatePublicKey,
77    /// No schnorr proof set
78    #[error("No schnorr proof set")]
79    MissingSchnorrProof,
80    /// No signature set
81    #[error("No signature set")]
82    MissingSignature,
83    /// Missing message response information for a signing round
84    #[error("Missing message nonce information")]
85    MissingMessageNonceInfo,
86    /// Missing public key for signer
87    #[error("Missing public key for signer {0}")]
88    MissingPublicKeyForSigner(u32),
89    /// Missing key IDs for signer
90    #[error("Missing key IDs for signer {0}")]
91    MissingKeyIDsForSigner(u32),
92    /// Bad key IDs for signer
93    #[error("Bad key IDs for signer {0}")]
94    BadKeyIDsForSigner(u32),
95    /// DKG failure from signers, with a map of signer_id to reported errors and new malicious signer_ids
96    #[error("DKG failure from signers")]
97    DkgFailure {
98        /// failures reported by signers during DkgEnd
99        reported_failures: HashMap<u32, DkgFailure>,
100        /// signers who were discovered to be malicious during this DKG round
101        malicious_signers: HashSet<u32>,
102    },
103    /// Aggregate key does not match supplied party polynomial
104    #[error(
105        "Aggregate key and computed key from party polynomials mismatch: got {0}, expected {1}"
106    )]
107    AggregateKeyPolynomialMismatch(Point, Point),
108    /// Supplied party polynomial contained duplicate party IDs
109    #[error("Supplied party polynomials contained a duplicate party ID")]
110    DuplicatePartyId,
111    #[error("Missing coordinator public key")]
112    /// Missing coordinator public key"
113    MissingCoordinatorPublicKey,
114    #[error("A packet had an invalid signature")]
115    /// A packet had an invalid signature
116    InvalidPacketSignature,
117    #[error("No public shares for signer {0}")]
118    /// No public shares for the signer who sent private shares
119    NoPublicSharesForSigner(u32),
120    #[error("A curve point error {0}")]
121    /// A curve point error
122    Point(#[from] PointError),
123    #[error("integer conversion error")]
124    /// An error during integer conversion operations
125    TryFromInt(#[from] TryFromIntError),
126}
127
128impl From<AggregatorError> for Error {
129    fn from(err: AggregatorError) -> Self {
130        Error::Aggregator(err)
131    }
132}
133
134/// Config fields common to all Coordinators
135#[derive(Default, Clone, PartialEq)]
136pub struct Config {
137    /// total number of signers
138    pub num_signers: u32,
139    /// total number of keys
140    pub num_keys: u32,
141    /// threshold of keys needed to form a valid signature
142    pub threshold: u32,
143    /// threshold of keys needed to complete DKG (must be >= threshold)
144    pub dkg_threshold: u32,
145    /// private key used to sign network messages
146    pub message_private_key: Scalar,
147    /// timeout to gather DkgPublicShares messages
148    pub dkg_public_timeout: Option<Duration>,
149    /// timeout to gather DkgPrivateShares messages
150    pub dkg_private_timeout: Option<Duration>,
151    /// timeout to gather DkgEnd messages
152    pub dkg_end_timeout: Option<Duration>,
153    /// timeout to gather nonces
154    pub nonce_timeout: Option<Duration>,
155    /// timeout to gather signature shares
156    pub sign_timeout: Option<Duration>,
157    /// the public keys and key_ids for all signers
158    pub public_keys: PublicKeys,
159    /// whether to verify the signature on Packets
160    pub verify_packet_sigs: bool,
161}
162
163impl fmt::Debug for Config {
164    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165        f.debug_struct("Config")
166            .field("num_signers", &self.num_signers)
167            .field("num_keys", &self.num_keys)
168            .field("dkg_threshold", &self.dkg_threshold)
169            .field("dkg_public_timeout", &self.dkg_public_timeout)
170            .field("dkg_private_timeout", &self.dkg_private_timeout)
171            .field("dkg_end_timeout", &self.dkg_end_timeout)
172            .field("nonce_timeout", &self.nonce_timeout)
173            .field("sign_timeout", &self.sign_timeout)
174            .field("signer_key_ids", &self.public_keys.signer_key_ids)
175            .field("signer_public_keys", &self.public_keys.signers)
176            .field("verify_packet_sigs", &self.verify_packet_sigs)
177            .finish_non_exhaustive()
178    }
179}
180
181impl Config {
182    /// Create a new config object with no timeouts
183    pub fn new(
184        num_signers: u32,
185        num_keys: u32,
186        threshold: u32,
187        message_private_key: Scalar,
188    ) -> Self {
189        Config {
190            num_signers,
191            num_keys,
192            threshold,
193            dkg_threshold: num_keys,
194            message_private_key,
195            dkg_public_timeout: None,
196            dkg_private_timeout: None,
197            dkg_end_timeout: None,
198            nonce_timeout: None,
199            sign_timeout: None,
200            public_keys: Default::default(),
201            verify_packet_sigs: true,
202        }
203    }
204
205    #[allow(clippy::too_many_arguments)]
206    /// Create a new config object with the passed timeouts
207    pub fn with_timeouts(
208        num_signers: u32,
209        num_keys: u32,
210        threshold: u32,
211        dkg_threshold: u32,
212        message_private_key: Scalar,
213        dkg_public_timeout: Option<Duration>,
214        dkg_private_timeout: Option<Duration>,
215        dkg_end_timeout: Option<Duration>,
216        nonce_timeout: Option<Duration>,
217        sign_timeout: Option<Duration>,
218        public_keys: PublicKeys,
219    ) -> Self {
220        Config {
221            num_signers,
222            num_keys,
223            threshold,
224            dkg_threshold,
225            message_private_key,
226            dkg_public_timeout,
227            dkg_private_timeout,
228            dkg_end_timeout,
229            nonce_timeout,
230            sign_timeout,
231            public_keys,
232            verify_packet_sigs: true,
233        }
234    }
235}
236
237#[derive(Clone, Debug, Default, PartialEq)]
238/// The info for a sign round over specific message bytes
239pub struct SignRoundInfo {
240    /// the nonce response of a signer id
241    pub public_nonces: BTreeMap<u32, NonceResponse>,
242    /// which key_ids we've received nonces for this iteration
243    pub nonce_recv_key_ids: HashSet<u32>,
244    /// which key_ids we're received sig shares for this iteration
245    pub sign_recv_key_ids: HashSet<u32>,
246    /// which signer_ids we're expecting sig shares from this iteration
247    pub sign_wait_signer_ids: HashSet<u32>,
248}
249
250/// The saved state required to reconstruct a coordinator
251#[derive(Default, Clone, Debug, PartialEq)]
252pub struct SavedState {
253    /// common config fields
254    pub config: Config,
255    /// current DKG round ID
256    pub current_dkg_id: u64,
257    /// current signing round ID
258    pub current_sign_id: u64,
259    /// current signing iteration ID
260    pub current_sign_iter_id: u64,
261    /// map of DkgPublicShares indexed by signer ID
262    pub dkg_public_shares: BTreeMap<u32, DkgPublicShares>,
263    /// map of DkgPrivateShares indexed by signer ID
264    pub dkg_private_shares: BTreeMap<u32, DkgPrivateShares>,
265    /// map of DkgEnd indexed by signer ID
266    pub dkg_end_messages: BTreeMap<u32, DkgEnd>,
267    /// the current view of a successful DKG's participants' commitments
268    pub party_polynomials: HashMap<u32, PolyCommitment>,
269    /// map of SignatureShare indexed by signer ID
270    pub signature_shares: BTreeMap<u32, Vec<SignatureShare>>,
271    /// map of SignRoundInfo indexed by message bytes
272    pub message_nonces: BTreeMap<Vec<u8>, SignRoundInfo>,
273    /// aggregate public key
274    pub aggregate_public_key: Option<Point>,
275    /// current Signature
276    pub signature: Option<Signature>,
277    /// current SchnorrProof
278    pub schnorr_proof: Option<SchnorrProof>,
279    /// which signers we're currently waiting on for DKG
280    pub dkg_wait_signer_ids: HashSet<u32>,
281    /// the bytes that we're signing
282    pub message: Vec<u8>,
283    /// current state of the state machine
284    pub state: State,
285    /// start time for NonceRequest
286    pub nonce_start: Option<Instant>,
287    /// start time for DkgBegin
288    pub dkg_public_start: Option<Instant>,
289    /// start time for DkgPrivateBegin
290    pub dkg_private_start: Option<Instant>,
291    /// start time for DkgEndBegin
292    pub dkg_end_start: Option<Instant>,
293    /// start time for SignatureShareRequest
294    pub sign_start: Option<Instant>,
295    /// set of malicious signers during signing round
296    pub malicious_signer_ids: HashSet<u32>,
297    /// set of malicious signers during dkg round
298    pub malicious_dkg_signer_ids: HashSet<u32>,
299    /// coordinator public key
300    pub coordinator_public_key: Option<ecdsa::PublicKey>,
301}
302
303/// Coordinator trait for handling the coordination of DKG and sign messages
304pub trait Coordinator: Clone + Debug + PartialEq + StateMachine<State, Error> {
305    /// Create a new Coordinator
306    fn new(config: Config) -> Self;
307
308    /// Load a coordinator from the previously saved `state`
309    fn load(state: &SavedState) -> Self;
310
311    /// Save the state required to reconstruct the coordinator
312    fn save(&self) -> SavedState;
313
314    /// Retrieve the config
315    fn get_config(&self) -> Config;
316
317    /// Retrieve a mutable reference to the config
318    #[cfg(any(test, feature = "testing"))]
319    fn get_config_mut(&mut self) -> &mut Config;
320
321    /// Set the coordinator public key
322    fn set_coordinator_public_key(&mut self, key: Option<ecdsa::PublicKey>);
323
324    /// Initialize Coordinator from partial saved state
325    fn set_key_and_party_polynomials(
326        &mut self,
327        aggregate_key: Point,
328        party_polynomials: Vec<(u32, PolyCommitment)>,
329    ) -> Result<(), Error>;
330
331    /// Process any timeouts, and if none of them fire then process the passed packet
332    /// If a timeout does fire, then the coordinator state has changed; this means the
333    /// packet is now stale and must be dropped
334    fn process(
335        &mut self,
336        packet: &Packet,
337    ) -> Result<(Option<Packet>, Option<OperationResult>), Error>;
338
339    /// Retrieve the aggregate public key
340    fn get_aggregate_public_key(&self) -> Option<Point>;
341
342    /// Set the aggregate public key
343    fn set_aggregate_public_key(&mut self, aggregate_public_key: Option<Point>);
344
345    /// Retrieve the current message bytes being signed
346    fn get_message(&self) -> Vec<u8>;
347
348    /// Retrive the current state
349    fn get_state(&self) -> State;
350
351    /// Trigger a DKG round, with an optional `dkg_id`
352    fn start_dkg_round(&mut self, dkg_id: Option<u64>) -> Result<Packet, Error>;
353
354    /// Trigger a signing round
355    fn start_signing_round(
356        &mut self,
357        message: &[u8],
358        signature_type: SignatureType,
359        sign_id: Option<u64>,
360    ) -> Result<Packet, Error>;
361
362    /// Reset internal state
363    fn reset(&mut self);
364}
365
366/// The coordinator for the FROST algorithm
367pub mod frost;
368
369/// The coordinator for the FIRE algorithm
370pub mod fire;
371
372#[allow(missing_docs)]
373#[cfg(any(test, feature = "testing"))]
374pub mod test {
375    use hashbrown::{HashMap, HashSet};
376    use rand_core::OsRng;
377    use std::{sync::Once, time::Duration};
378    use tracing_subscriber::{fmt, prelude::*, EnvFilter};
379
380    use crate::{
381        common::SignatureShare,
382        compute,
383        curve::{ecdsa, point::Point, point::G, scalar::Scalar},
384        errors::AggregatorError,
385        net::{DkgFailure, Message, Packet, SignatureShareResponse, SignatureType},
386        schnorr,
387        state_machine::{
388            coordinator::{Config, Coordinator as CoordinatorTrait, Error, State},
389            signer::{Error as SignerError, Signer},
390            DkgError, Error as StateMachineError, OperationResult, PublicKeys, SignError,
391            StateMachine,
392        },
393        traits::Signer as SignerTrait,
394        util::create_rng,
395    };
396
397    static INIT: Once = Once::new();
398
399    pub fn new_coordinator<Coordinator: CoordinatorTrait>() {
400        let mut rng = create_rng();
401        let config = Config::new(10, 40, 28, Scalar::random(&mut rng));
402        let coordinator = Coordinator::new(config.clone());
403
404        assert_eq!(coordinator.get_config().num_signers, config.num_signers);
405        assert_eq!(coordinator.get_config().num_keys, config.num_keys);
406        assert_eq!(coordinator.get_config().threshold, config.threshold);
407        assert_eq!(
408            coordinator.get_config().message_private_key,
409            config.message_private_key
410        );
411        assert_eq!(coordinator.get_state(), State::Idle);
412    }
413
414    pub fn coordinator_state_machine<Coordinator: CoordinatorTrait + StateMachine<State, Error>>() {
415        let mut rng = create_rng();
416        let config = Config::new(3, 3, 3, Scalar::random(&mut rng));
417        let mut coordinator = Coordinator::new(config);
418        assert!(coordinator.can_move_to(&State::DkgPublicDistribute).is_ok());
419        assert!(coordinator.can_move_to(&State::DkgPublicGather).is_err());
420        assert!(coordinator
421            .can_move_to(&State::DkgPrivateDistribute)
422            .is_err());
423        assert!(coordinator.can_move_to(&State::DkgPrivateGather).is_err());
424        assert!(coordinator.can_move_to(&State::DkgEndDistribute).is_err());
425        assert!(coordinator.can_move_to(&State::DkgEndGather).is_err());
426        assert!(coordinator.can_move_to(&State::Idle).is_ok());
427
428        coordinator.move_to(State::DkgPublicDistribute).unwrap();
429        assert!(coordinator
430            .can_move_to(&State::DkgPublicDistribute)
431            .is_err());
432        assert!(coordinator.can_move_to(&State::DkgPublicGather).is_ok());
433        assert!(coordinator
434            .can_move_to(&State::DkgPrivateDistribute)
435            .is_err());
436        assert!(coordinator.can_move_to(&State::DkgPrivateGather).is_err());
437        assert!(coordinator.can_move_to(&State::DkgEndDistribute).is_err());
438        assert!(coordinator.can_move_to(&State::DkgEndGather).is_err());
439        assert!(coordinator.can_move_to(&State::Idle).is_ok());
440
441        coordinator.move_to(State::DkgPublicGather).unwrap();
442        assert!(coordinator
443            .can_move_to(&State::DkgPublicDistribute)
444            .is_err());
445        assert!(coordinator.can_move_to(&State::DkgPublicGather).is_ok());
446        assert!(coordinator
447            .can_move_to(&State::DkgPrivateDistribute)
448            .is_ok());
449        assert!(coordinator.can_move_to(&State::DkgPrivateGather).is_err());
450        assert!(coordinator.can_move_to(&State::DkgEndDistribute).is_err());
451        assert!(coordinator.can_move_to(&State::DkgEndGather).is_err());
452        assert!(coordinator.can_move_to(&State::Idle).is_ok());
453
454        coordinator.move_to(State::DkgPrivateDistribute).unwrap();
455        assert!(coordinator
456            .can_move_to(&State::DkgPublicDistribute)
457            .is_err());
458        assert!(coordinator.can_move_to(&State::DkgPublicGather).is_err());
459        assert!(coordinator
460            .can_move_to(&State::DkgPrivateDistribute)
461            .is_err());
462        assert!(coordinator.can_move_to(&State::DkgPrivateGather).is_ok());
463        assert!(coordinator.can_move_to(&State::DkgEndDistribute).is_err());
464        assert!(coordinator.can_move_to(&State::DkgEndGather).is_err());
465        assert!(coordinator.can_move_to(&State::Idle).is_ok());
466
467        coordinator.move_to(State::DkgPrivateGather).unwrap();
468        assert!(coordinator
469            .can_move_to(&State::DkgPublicDistribute)
470            .is_err());
471        assert!(coordinator.can_move_to(&State::DkgPublicGather).is_err());
472        assert!(coordinator
473            .can_move_to(&State::DkgPrivateDistribute)
474            .is_err());
475        assert!(coordinator.can_move_to(&State::DkgPrivateGather).is_ok());
476        assert!(coordinator.can_move_to(&State::DkgEndDistribute).is_ok());
477        assert!(coordinator.can_move_to(&State::DkgEndGather).is_err());
478        assert!(coordinator.can_move_to(&State::Idle).is_ok());
479
480        coordinator.move_to(State::DkgEndDistribute).unwrap();
481        assert!(coordinator.can_move_to(&State::DkgEndGather).is_ok());
482
483        coordinator.move_to(State::DkgEndGather).unwrap();
484        assert!(coordinator.can_move_to(&State::Idle).is_ok());
485    }
486
487    pub fn start_dkg_round<Coordinator: CoordinatorTrait>(dkg_id: Option<u64>) {
488        let mut rng = create_rng();
489        let config = Config::new(10, 40, 28, Scalar::random(&mut rng));
490        let mut coordinator = Coordinator::new(config);
491        let result = coordinator.start_dkg_round(dkg_id);
492
493        assert!(result.is_ok());
494
495        if let Message::DkgBegin(dkg_begin) = result.unwrap().msg {
496            if let Some(id) = dkg_id {
497                assert_eq!(
498                    dkg_begin.dkg_id, id,
499                    "Bad dkg_id {} expected {id}",
500                    dkg_begin.dkg_id
501                );
502            } else {
503                assert_eq!(
504                    dkg_begin.dkg_id, 1,
505                    "Bad dkg_id {} expected 1",
506                    dkg_begin.dkg_id
507                );
508            }
509        } else {
510            panic!("coordinator.start_dkg_round didn't return DkgBegin");
511        };
512
513        assert_eq!(coordinator.get_state(), State::DkgPublicGather);
514    }
515
516    pub fn start_signing_round<Coordinator: CoordinatorTrait>(sign_id: Option<u64>) {
517        let mut rng = create_rng();
518        let config = Config::new(10, 40, 28, Scalar::random(&mut rng));
519        let mut coordinator = Coordinator::new(config);
520
521        coordinator.set_aggregate_public_key(Some(Point::new()));
522
523        let msg = "It was many and many a year ago, in a kingdom by the sea"
524            .as_bytes()
525            .to_vec();
526        let signature_type = SignatureType::Schnorr;
527        let result = coordinator.start_signing_round(&msg, signature_type, sign_id);
528
529        assert!(result.is_ok());
530
531        if let Message::NonceRequest(nonce_request) = result.unwrap().msg {
532            if let Some(id) = sign_id {
533                assert_eq!(
534                    nonce_request.sign_id, id,
535                    "Bad dkg_id {} expected {id}",
536                    nonce_request.sign_id
537                );
538            } else {
539                assert_eq!(
540                    nonce_request.sign_id, 1,
541                    "Bad dkg_id {} expected 1",
542                    nonce_request.sign_id
543                );
544            }
545        } else {
546            panic!("coordinator.start_signing_round didn't return NonceRequest");
547        };
548
549        assert_eq!(coordinator.get_state(), State::NonceGather(signature_type));
550    }
551
552    pub fn setup<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
553        num_signers: u32,
554        keys_per_signer: u32,
555    ) -> (Vec<Coordinator>, Vec<Signer<SignerType>>) {
556        setup_with_timeouts::<Coordinator, SignerType>(
557            num_signers,
558            keys_per_signer,
559            None,
560            None,
561            None,
562            None,
563            None,
564        )
565    }
566
567    pub fn setup_with_timeouts<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
568        num_signers: u32,
569        keys_per_signer: u32,
570        dkg_public_timeout: Option<Duration>,
571        dkg_private_timeout: Option<Duration>,
572        dkg_end_timeout: Option<Duration>,
573        nonce_timeout: Option<Duration>,
574        sign_timeout: Option<Duration>,
575    ) -> (Vec<Coordinator>, Vec<Signer<SignerType>>) {
576        INIT.call_once(|| {
577            tracing_subscriber::registry()
578                .with(fmt::layer())
579                .with(EnvFilter::from_default_env())
580                .init();
581        });
582
583        let mut rng = create_rng();
584        let num_keys = num_signers * keys_per_signer;
585        let threshold = (num_keys * 7) / 10;
586        let dkg_threshold = (num_keys * 9) / 10;
587        let key_pairs = (0..num_signers)
588            .map(|_| {
589                let private_key = Scalar::random(&mut rng);
590                let public_key = ecdsa::PublicKey::new(&private_key).unwrap();
591                (private_key, public_key)
592            })
593            .collect::<Vec<(Scalar, ecdsa::PublicKey)>>();
594        let mut key_id: u32 = 1;
595        let mut signer_ids_map = HashMap::new();
596        let mut signer_key_ids = HashMap::new();
597        let mut signer_key_ids_set = HashMap::new();
598        let mut signer_public_keys = HashMap::new();
599        let mut key_ids_map = HashMap::new();
600        for (i, (private_key, public_key)) in key_pairs.iter().enumerate() {
601            let mut key_ids = Vec::new();
602            let mut key_ids_set = HashSet::new();
603            for _ in 0..keys_per_signer {
604                key_ids_map.insert(key_id, *public_key);
605                key_ids.push(key_id);
606                key_ids_set.insert(key_id);
607                key_id += 1;
608            }
609            signer_ids_map.insert(i as u32, *public_key);
610            signer_key_ids.insert(i as u32, key_ids);
611            signer_key_ids_set.insert(i as u32, key_ids_set);
612            signer_public_keys.insert(i as u32, Point::from(private_key));
613        }
614        let public_keys = PublicKeys {
615            signers: signer_ids_map,
616            key_ids: key_ids_map,
617            signer_key_ids: signer_key_ids_set.clone(),
618        };
619
620        let signers = key_pairs
621            .iter()
622            .enumerate()
623            .map(|(signer_id, (private_key, _public_key))| {
624                let mut signer = Signer::<SignerType>::new(
625                    threshold,
626                    dkg_threshold,
627                    num_signers,
628                    num_keys,
629                    signer_id as u32,
630                    signer_key_ids[&(signer_id as u32)].clone(),
631                    *private_key,
632                    public_keys.clone(),
633                    &mut rng,
634                )
635                .unwrap();
636                signer.verify_packet_sigs = false;
637                signer
638            })
639            .collect::<Vec<Signer<SignerType>>>();
640        let coordinators = key_pairs
641            .into_iter()
642            .map(|(private_key, _public_key)| {
643                let mut config = Config::with_timeouts(
644                    num_signers,
645                    num_keys,
646                    threshold,
647                    dkg_threshold,
648                    private_key,
649                    dkg_public_timeout,
650                    dkg_private_timeout,
651                    dkg_end_timeout,
652                    nonce_timeout,
653                    sign_timeout,
654                    public_keys.clone(),
655                );
656                config.verify_packet_sigs = false;
657                Coordinator::new(config)
658            })
659            .collect::<Vec<Coordinator>>();
660        (coordinators, signers)
661    }
662
663    /// Helper function for feeding messages back from the processor into the signing rounds and coordinators
664    pub fn feedback_messages<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
665        coordinators: &mut [Coordinator],
666        signers: &mut [Signer<SignerType>],
667        messages: &[Packet],
668    ) -> (Vec<Packet>, Vec<OperationResult>) {
669        feedback_mutated_messages(coordinators, signers, messages, |_signer, msgs| msgs)
670    }
671
672    /// Helper function for feeding mutated messages back from the processor into the signing rounds and coordinators
673    pub fn feedback_mutated_messages<
674        Coordinator: CoordinatorTrait,
675        SignerType: SignerTrait,
676        F: Fn(&Signer<SignerType>, Vec<Packet>) -> Vec<Packet>,
677    >(
678        coordinators: &mut [Coordinator],
679        signers: &mut [Signer<SignerType>],
680        messages: &[Packet],
681        signer_mutator: F,
682    ) -> (Vec<Packet>, Vec<OperationResult>) {
683        feedback_mutated_messages_with_errors(coordinators, signers, messages, signer_mutator)
684            .unwrap()
685    }
686
687    /// Helper function for feeding mutated messages back from the processor into the signing rounds and coordinators
688    pub fn feedback_messages_with_errors<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
689        coordinators: &mut [Coordinator],
690        signers: &mut [Signer<SignerType>],
691        messages: &[Packet],
692    ) -> Result<(Vec<Packet>, Vec<OperationResult>), StateMachineError> {
693        feedback_mutated_messages_with_errors(coordinators, signers, messages, |_signer, msgs| msgs)
694    }
695
696    /// Helper function for feeding mutated messages back from the processor into the signing rounds and coordinators
697    pub fn feedback_mutated_messages_with_errors<
698        Coordinator: CoordinatorTrait,
699        SignerType: SignerTrait,
700        F: Fn(&Signer<SignerType>, Vec<Packet>) -> Vec<Packet>,
701    >(
702        coordinators: &mut [Coordinator],
703        signers: &mut [Signer<SignerType>],
704        messages: &[Packet],
705        signer_mutator: F,
706    ) -> Result<(Vec<Packet>, Vec<OperationResult>), StateMachineError> {
707        let mut inbound_messages = vec![];
708        let mut feedback_messages = vec![];
709        let mut rng = create_rng();
710        for signer in signers.iter_mut() {
711            let outbound_messages = signer.process_inbound_messages(messages, &mut rng)?;
712            let outbound_messages = signer_mutator(signer, outbound_messages);
713            feedback_messages.extend_from_slice(outbound_messages.as_slice());
714            inbound_messages.extend(outbound_messages);
715        }
716        for signer in signers.iter_mut() {
717            let outbound_messages =
718                signer.process_inbound_messages(&feedback_messages, &mut rng)?;
719            inbound_messages.extend(outbound_messages);
720        }
721        for coordinator in coordinators.iter_mut() {
722            // Process all coordinator messages, but don't bother with propogating these results
723            for message in messages {
724                let _ = coordinator.process(message)?;
725            }
726        }
727        let mut results = vec![];
728        let mut messages = vec![];
729        for (i, coordinator) in coordinators.iter_mut().enumerate() {
730            for inbound_message in &inbound_messages {
731                let (outbound_message, outbound_result) = coordinator.process(inbound_message)?;
732                // Only propogate a single coordinator's messages and results
733                if i == 0 {
734                    messages.extend(outbound_message);
735                    results.extend(outbound_result);
736                }
737            }
738        }
739        Ok((messages, results))
740    }
741
742    pub fn run_dkg<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
743        num_signers: u32,
744        keys_per_signer: u32,
745    ) -> (Vec<Coordinator>, Vec<Signer<SignerType>>) {
746        let (mut coordinators, mut signers) =
747            setup::<Coordinator, SignerType>(num_signers, keys_per_signer);
748
749        // We have started a dkg round
750        let message = coordinators
751            .first_mut()
752            .unwrap()
753            .start_dkg_round(None)
754            .unwrap();
755        assert!(coordinators
756            .first_mut()
757            .unwrap()
758            .get_aggregate_public_key()
759            .is_none());
760        assert_eq!(
761            coordinators.first_mut().unwrap().get_state(),
762            State::DkgPublicGather
763        );
764
765        // Send the DKG Begin message to all signers and gather responses by sharing with all other signers and coordinator
766        let (outbound_messages, operation_results) =
767            feedback_messages(&mut coordinators, &mut signers, &[message]);
768        assert!(operation_results.is_empty());
769        for coordinator in coordinators.iter() {
770            assert_eq!(coordinator.get_state(), State::DkgPrivateGather);
771        }
772
773        assert_eq!(outbound_messages.len(), 1);
774        assert!(
775            matches!(&outbound_messages[0].msg, Message::DkgPrivateBegin(_)),
776            "Expected DkgPrivateBegin message"
777        );
778
779        // persist the state machines before continuing
780        let new_coordinators = coordinators
781            .iter()
782            .map(|c| Coordinator::load(&c.save()))
783            .collect::<Vec<Coordinator>>();
784
785        assert_eq!(coordinators, new_coordinators);
786
787        coordinators = new_coordinators;
788
789        let new_signers = signers
790            .iter()
791            .map(|s| Signer::<SignerType>::load(&s.save()))
792            .collect::<Vec<Signer<SignerType>>>();
793
794        assert_eq!(signers, new_signers);
795
796        signers = new_signers;
797
798        // Send the DKG Private Begin message to all signers and share their responses with the coordinator and signers
799        let (outbound_messages, operation_results) =
800            feedback_messages(&mut coordinators, &mut signers, &outbound_messages);
801        assert_eq!(operation_results.len(), 0);
802        assert_eq!(outbound_messages.len(), 1);
803        assert!(
804            matches!(outbound_messages[0].msg, Message::DkgEndBegin(_)),
805            "Expected DkgEndBegin message"
806        );
807
808        // persist the state machines before continuing
809        let new_coordinators = coordinators
810            .iter()
811            .map(|c| Coordinator::load(&c.save()))
812            .collect::<Vec<Coordinator>>();
813
814        assert_eq!(coordinators, new_coordinators);
815
816        coordinators = new_coordinators;
817
818        let new_signers = signers
819            .iter()
820            .map(|s| Signer::<SignerType>::load(&s.save()))
821            .collect::<Vec<Signer<SignerType>>>();
822
823        assert_eq!(signers, new_signers);
824
825        signers = new_signers;
826
827        // Send the DkgEndBegin message to all signers and share their responses with the coordinator and signers
828        let (outbound_messages, operation_results) =
829            feedback_messages(&mut coordinators, &mut signers, &outbound_messages);
830        assert_eq!(outbound_messages.len(), 0);
831        assert_eq!(operation_results.len(), 1);
832        let OperationResult::Dkg(point) = operation_results[0] else {
833            panic!("Expected Dkg Operation result");
834        };
835        assert_ne!(point, Point::default());
836        for coordinator in coordinators.iter() {
837            assert_eq!(coordinator.get_aggregate_public_key(), Some(point));
838            assert_eq!(coordinator.get_state(), State::Idle);
839        }
840
841        // clear the polynomials before persisting
842        for signer in &mut signers {
843            signer.signer.clear_polys();
844        }
845
846        // persist the state machines before continuing
847        let new_coordinators = coordinators
848            .iter()
849            .map(|c| Coordinator::load(&c.save()))
850            .collect::<Vec<Coordinator>>();
851
852        assert_eq!(coordinators, new_coordinators);
853
854        coordinators = new_coordinators;
855
856        let new_signers = signers
857            .iter()
858            .map(|s| Signer::<SignerType>::load(&s.save()))
859            .collect::<Vec<Signer<SignerType>>>();
860
861        assert_eq!(signers, new_signers);
862
863        signers = new_signers;
864
865        (coordinators, signers)
866    }
867
868    pub fn run_sign<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
869        coordinators: &mut [Coordinator],
870        signers: &mut Vec<Signer<SignerType>>,
871        msg: &[u8],
872        signature_type: SignatureType,
873    ) -> OperationResult {
874        // Start a signing round
875        let message = coordinators
876            .first_mut()
877            .unwrap()
878            .start_signing_round(msg, signature_type, None)
879            .unwrap();
880        assert_eq!(
881            coordinators.first_mut().unwrap().get_state(),
882            State::NonceGather(signature_type)
883        );
884
885        // Send the message to all signers and gather responses by sharing with all other signers and coordinator
886        let (outbound_messages, operation_results) =
887            feedback_messages(coordinators, signers, &[message]);
888        assert!(operation_results.is_empty());
889        assert_eq!(
890            coordinators.first_mut().unwrap().get_state(),
891            State::SigShareGather(signature_type)
892        );
893
894        assert_eq!(outbound_messages.len(), 1);
895        assert!(
896            matches!(outbound_messages[0].msg, Message::SignatureShareRequest(_)),
897            "Expected SignatureShareRequest message"
898        );
899
900        // persist the coordinators before continuing
901        let _new_coordinators = coordinators
902            .iter()
903            .map(|c| Coordinator::load(&c.save()))
904            .collect::<Vec<Coordinator>>();
905
906        let new_signers = signers
907            .iter()
908            .map(|s| Signer::<SignerType>::load(&s.save()))
909            .collect::<Vec<Signer<SignerType>>>();
910
911        assert_eq!(signers, &new_signers);
912
913        // Send the SignatureShareRequest message to all signers and share their responses with the coordinator and signers
914        let (outbound_messages, operation_results) =
915            feedback_messages(coordinators, signers, &outbound_messages);
916        assert!(outbound_messages.is_empty());
917        assert_eq!(operation_results.len(), 1);
918        match &operation_results[0] {
919            OperationResult::Sign(sig) => {
920                let SignatureType::Frost = signature_type else {
921                    panic!("Expected OperationResult::Sign");
922                };
923                for coordinator in coordinators.iter() {
924                    assert!(sig.verify(
925                        &coordinator
926                            .get_aggregate_public_key()
927                            .expect("No aggregate public key set!"),
928                        msg
929                    ));
930                    assert_eq!(coordinator.get_state(), State::Idle);
931                }
932            }
933            OperationResult::SignSchnorr(sig) => {
934                let SignatureType::Schnorr = signature_type else {
935                    panic!("Expected OperationResult::SignSchnorr");
936                };
937                for coordinator in coordinators.iter() {
938                    assert!(sig.verify(
939                        &coordinator
940                            .get_aggregate_public_key()
941                            .expect("No aggregate public key set!")
942                            .x(),
943                        msg
944                    ));
945                    assert_eq!(coordinator.get_state(), State::Idle);
946                }
947            }
948            OperationResult::SignTaproot(sig) => {
949                let SignatureType::Taproot(merkle_root) = signature_type else {
950                    panic!("Expected OperationResult::SignTaproot");
951                };
952                for coordinator in coordinators.iter() {
953                    let tweaked_public_key = compute::tweaked_public_key(
954                        &coordinator
955                            .get_aggregate_public_key()
956                            .expect("No aggregate public key set!"),
957                        merkle_root,
958                    );
959
960                    assert!(sig.verify(&tweaked_public_key.x(), msg));
961                    assert_eq!(coordinator.get_state(), State::Idle);
962                }
963            }
964            _ => panic!("Expected OperationResult"),
965        }
966
967        operation_results[0].clone()
968    }
969
970    pub fn run_dkg_sign<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
971        num_signers: u32,
972        keys_per_signer: u32,
973    ) {
974        let (mut coordinators, mut signers) =
975            run_dkg::<Coordinator, SignerType>(num_signers, keys_per_signer);
976
977        let msg = "It was many and many a year ago, in a kingdom by the sea"
978            .as_bytes()
979            .to_vec();
980
981        run_sign::<Coordinator, SignerType>(
982            &mut coordinators,
983            &mut signers,
984            &msg,
985            SignatureType::Frost,
986        );
987        run_sign::<Coordinator, SignerType>(
988            &mut coordinators,
989            &mut signers,
990            &msg,
991            SignatureType::Schnorr,
992        );
993        run_sign::<Coordinator, SignerType>(
994            &mut coordinators,
995            &mut signers,
996            &msg,
997            SignatureType::Taproot(None),
998        );
999        run_sign::<Coordinator, SignerType>(
1000            &mut coordinators,
1001            &mut signers,
1002            &msg,
1003            SignatureType::Taproot(Some([128u8; 32])),
1004        );
1005    }
1006
1007    pub fn verify_packet_sigs<Coordinator: CoordinatorTrait, SignerType: SignerTrait>() {
1008        verify_removed_coordinator_key_on_signers::<Coordinator, SignerType>();
1009        verify_removed_coordinator_key_on_coordinator::<Coordinator, SignerType>();
1010        verify_changed_coordinator_key_on_signers::<Coordinator, SignerType>();
1011        verify_changed_coordinator_key_on_coordinator::<Coordinator, SignerType>();
1012    }
1013
1014    pub fn verify_removed_coordinator_key_on_signers<
1015        Coordinator: CoordinatorTrait,
1016        SignerType: SignerTrait,
1017    >() {
1018        let (coordinators, mut signers) = setup::<Coordinator, SignerType>(5, 1);
1019        let mut coordinators = vec![coordinators[0].clone()];
1020
1021        for coordinator in coordinators.iter_mut() {
1022            let config = coordinator.get_config_mut();
1023            config.verify_packet_sigs = true;
1024
1025            let coordinator_public_key = config.public_keys.signers[&0];
1026            coordinator.set_coordinator_public_key(Some(coordinator_public_key));
1027        }
1028
1029        for signer in signers.iter_mut() {
1030            signer.verify_packet_sigs = true;
1031
1032            let coordinator_public_key = signer.public_keys.signers[&0];
1033            signer.coordinator_public_key = Some(coordinator_public_key);
1034        }
1035
1036        // We have started a dkg round
1037        let message = coordinators
1038            .first_mut()
1039            .unwrap()
1040            .start_dkg_round(None)
1041            .unwrap();
1042        assert!(coordinators
1043            .first_mut()
1044            .unwrap()
1045            .get_aggregate_public_key()
1046            .is_none());
1047        assert_eq!(
1048            coordinators.first_mut().unwrap().get_state(),
1049            State::DkgPublicGather
1050        );
1051
1052        // Send the DKG Begin message to all signers and gather responses by sharing with all other signers and coordinator
1053        let (outbound_messages, operation_results) =
1054            feedback_messages(&mut coordinators, &mut signers, &[message]);
1055        assert!(operation_results.is_empty());
1056        for coordinator in coordinators.iter() {
1057            assert_eq!(coordinator.get_state(), State::DkgPrivateGather);
1058        }
1059
1060        assert_eq!(outbound_messages.len(), 1);
1061        match &outbound_messages[0].msg {
1062            Message::DkgPrivateBegin(_) => {}
1063            _ => {
1064                panic!("Expected DkgPrivateBegin message");
1065            }
1066        }
1067
1068        // Send the DKG Private Begin message to all signers and share their responses with the coordinator and signers
1069        let (outbound_messages, operation_results) =
1070            feedback_messages(&mut coordinators, &mut signers, &outbound_messages);
1071        assert_eq!(operation_results.len(), 0);
1072        assert_eq!(outbound_messages.len(), 1);
1073        match &outbound_messages[0].msg {
1074            Message::DkgEndBegin(_) => {}
1075            _ => {
1076                panic!("Expected DkgEndBegin message");
1077            }
1078        }
1079
1080        // Send the DkgEndBegin message to all signers and share their responses with the coordinator and signers
1081        let (outbound_messages, operation_results) =
1082            feedback_messages(&mut coordinators, &mut signers, &outbound_messages);
1083        assert_eq!(outbound_messages.len(), 0);
1084        assert_eq!(operation_results.len(), 1);
1085        match operation_results[0] {
1086            OperationResult::Dkg(point) => {
1087                assert_ne!(point, Point::default());
1088                for coordinator in coordinators.iter() {
1089                    assert_eq!(coordinator.get_aggregate_public_key(), Some(point));
1090                    assert_eq!(coordinator.get_state(), State::Idle);
1091                }
1092            }
1093            _ => panic!("Expected Dkg Operation result"),
1094        }
1095
1096        // clear the polynomials before persisting
1097        for signer in &mut signers {
1098            signer.signer.clear_polys();
1099        }
1100
1101        let msg = "It was many and many a year ago, in a kingdom by the sea"
1102            .as_bytes()
1103            .to_vec();
1104
1105        run_sign::<Coordinator, SignerType>(
1106            &mut coordinators,
1107            &mut signers,
1108            &msg,
1109            SignatureType::Frost,
1110        );
1111
1112        // Remove the coordinator public key on the signers and show that signers fail to verify
1113        for signer in signers.iter_mut() {
1114            signer.coordinator_public_key = None;
1115        }
1116
1117        let message = coordinators
1118            .first_mut()
1119            .unwrap()
1120            .start_dkg_round(None)
1121            .unwrap();
1122        assert_eq!(
1123            coordinators.first_mut().unwrap().get_state(),
1124            State::DkgPublicGather
1125        );
1126
1127        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &[message]);
1128        assert!(matches!(
1129            result,
1130            Err(StateMachineError::Signer(
1131                SignerError::MissingCoordinatorPublicKey
1132            ))
1133        ));
1134    }
1135
1136    // Remove the coordinator public key on the coordinator and show that signatures fail to verify
1137    pub fn verify_removed_coordinator_key_on_coordinator<
1138        Coordinator: CoordinatorTrait,
1139        SignerType: SignerTrait,
1140    >() {
1141        let (coordinators, mut signers) = setup::<Coordinator, SignerType>(5, 1);
1142        let mut coordinators = vec![coordinators[0].clone()];
1143
1144        for coordinator in coordinators.iter_mut() {
1145            let config = coordinator.get_config_mut();
1146            config.verify_packet_sigs = true;
1147
1148            coordinator.set_coordinator_public_key(None);
1149        }
1150
1151        for signer in signers.iter_mut() {
1152            signer.verify_packet_sigs = true;
1153
1154            let coordinator_public_key = signer.public_keys.signers[&0];
1155            signer.coordinator_public_key = Some(coordinator_public_key);
1156        }
1157
1158        let message = coordinators
1159            .first_mut()
1160            .unwrap()
1161            .start_dkg_round(None)
1162            .unwrap();
1163        assert_eq!(
1164            coordinators.first_mut().unwrap().get_state(),
1165            State::DkgPublicGather
1166        );
1167
1168        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &[message]);
1169        assert!(matches!(
1170            result,
1171            Err(StateMachineError::Coordinator(
1172                Error::MissingCoordinatorPublicKey
1173            ))
1174        ));
1175    }
1176
1177    // Change the coordinator public key on the signers and show that signatures fail to verify
1178    pub fn verify_changed_coordinator_key_on_signers<
1179        Coordinator: CoordinatorTrait,
1180        SignerType: SignerTrait,
1181    >() {
1182        let (coordinators, mut signers) = setup::<Coordinator, SignerType>(5, 1);
1183        let mut coordinators = vec![coordinators[0].clone()];
1184
1185        for coordinator in coordinators.iter_mut() {
1186            let config = coordinator.get_config_mut();
1187            config.verify_packet_sigs = true;
1188
1189            let coordinator_public_key = config.public_keys.signers[&0];
1190            coordinator.set_coordinator_public_key(Some(coordinator_public_key));
1191        }
1192
1193        for signer in signers.iter_mut() {
1194            signer.verify_packet_sigs = true;
1195
1196            let coordinator_public_key = signer.public_keys.signers[&1];
1197            signer.coordinator_public_key = Some(coordinator_public_key);
1198        }
1199
1200        let message = coordinators
1201            .first_mut()
1202            .unwrap()
1203            .start_dkg_round(None)
1204            .unwrap();
1205        assert_eq!(
1206            coordinators.first_mut().unwrap().get_state(),
1207            State::DkgPublicGather
1208        );
1209
1210        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &[message]);
1211        assert!(matches!(
1212            result,
1213            Err(StateMachineError::Signer(
1214                SignerError::InvalidPacketSignature
1215            ))
1216        ));
1217    }
1218
1219    // Change the coordinator public key on the coordinator and show that signatures fail to verify
1220    pub fn verify_changed_coordinator_key_on_coordinator<
1221        Coordinator: CoordinatorTrait,
1222        SignerType: SignerTrait,
1223    >() {
1224        let (coordinators, mut signers) = setup::<Coordinator, SignerType>(5, 1);
1225        let mut coordinators = vec![coordinators[0].clone()];
1226
1227        for coordinator in coordinators.iter_mut() {
1228            let config = coordinator.get_config_mut();
1229            config.verify_packet_sigs = true;
1230
1231            let coordinator_public_key = config.public_keys.signers[&1];
1232            coordinator.set_coordinator_public_key(Some(coordinator_public_key));
1233        }
1234
1235        for signer in signers.iter_mut() {
1236            signer.verify_packet_sigs = true;
1237
1238            let coordinator_public_key = signer.public_keys.signers[&0];
1239            signer.coordinator_public_key = Some(coordinator_public_key);
1240        }
1241
1242        let message = coordinators
1243            .first_mut()
1244            .unwrap()
1245            .start_dkg_round(None)
1246            .unwrap();
1247        assert_eq!(
1248            coordinators.first_mut().unwrap().get_state(),
1249            State::DkgPublicGather
1250        );
1251
1252        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &[message]);
1253        assert!(matches!(
1254            result,
1255            Err(StateMachineError::Coordinator(
1256                Error::InvalidPacketSignature
1257            ))
1258        ));
1259    }
1260
1261    /// Run DKG then sign a message, but alter the signature shares for signer 0.  This should trigger the aggregator internal check_signature_shares function to run and determine which parties signatures were bad.
1262    /// Because of the differences between how parties are represented in v1 and v2, we need to pass in a vector of the expected bad parties.
1263    pub fn check_signature_shares<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
1264        num_signers: u32,
1265        keys_per_signer: u32,
1266        signature_type: SignatureType,
1267        bad_parties: Vec<u32>,
1268    ) {
1269        let (mut coordinators, mut signers) =
1270            run_dkg::<Coordinator, SignerType>(num_signers, keys_per_signer);
1271
1272        let msg = "It was many and many a year ago, in a kingdom by the sea"
1273            .as_bytes()
1274            .to_vec();
1275        // Start a signing round
1276        let message = coordinators
1277            .first_mut()
1278            .unwrap()
1279            .start_signing_round(&msg, signature_type, None)
1280            .unwrap();
1281        assert_eq!(
1282            coordinators.first_mut().unwrap().get_state(),
1283            State::NonceGather(signature_type)
1284        );
1285
1286        // Send the message to all signers and gather responses by sharing with all other signers and coordinator
1287        let (outbound_messages, operation_results) =
1288            feedback_messages(&mut coordinators, &mut signers, &[message]);
1289        assert!(operation_results.is_empty());
1290        assert_eq!(
1291            coordinators.first_mut().unwrap().get_state(),
1292            State::SigShareGather(signature_type)
1293        );
1294
1295        assert_eq!(outbound_messages.len(), 1);
1296        assert!(
1297            matches!(outbound_messages[0].msg, Message::SignatureShareRequest(_)),
1298            "Expected SignatureShareRequest message"
1299        );
1300
1301        // Send the SignatureShareRequest message to all signers and share their responses with the coordinator and signers
1302        let (outbound_messages, operation_results) = feedback_mutated_messages(
1303            &mut coordinators,
1304            &mut signers,
1305            &outbound_messages,
1306            |signer, packets| {
1307                if signer.signer_id != 0 {
1308                    return packets.clone();
1309                }
1310                packets
1311                    .iter()
1312                    .map(|packet| {
1313                        let Message::SignatureShareResponse(response) = &packet.msg else {
1314                            return packet.clone();
1315                        };
1316                        // mutate one of the shares
1317                        let sshares: Vec<SignatureShare> = response
1318                            .signature_shares
1319                            .iter()
1320                            .map(|share| SignatureShare {
1321                                id: share.id,
1322                                key_ids: share.key_ids.clone(),
1323                                z_i: share.z_i + Scalar::from(1),
1324                            })
1325                            .collect();
1326                        Packet {
1327                            msg: Message::SignatureShareResponse(SignatureShareResponse {
1328                                dkg_id: response.dkg_id,
1329                                sign_id: response.sign_id,
1330                                sign_iter_id: response.sign_iter_id,
1331                                signer_id: response.signer_id,
1332                                signature_shares: sshares,
1333                            }),
1334                            sig: vec![],
1335                        }
1336                    })
1337                    .collect()
1338            },
1339        );
1340        assert!(outbound_messages.is_empty());
1341        assert_eq!(operation_results.len(), 1);
1342        let OperationResult::SignError(SignError::Coordinator(Error::Aggregator(
1343            AggregatorError::BadPartySigs(parties),
1344        ))) = &operation_results[0]
1345        else {
1346            panic!("Expected OperationResult::SignError(SignError::Coordinator(Error::Aggregator(AggregatorError::BadPartySigs(parties))))");
1347        };
1348        assert_eq!(
1349            parties, &bad_parties,
1350            "Expected BadPartySigs from {bad_parties:?}, got {:?}",
1351            &operation_results[0]
1352        );
1353    }
1354
1355    pub fn equal_after_save_load<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
1356        num_signers: u32,
1357        keys_per_signer: u32,
1358    ) {
1359        let (coordinators, signers) =
1360            setup::<Coordinator, SignerType>(num_signers, keys_per_signer);
1361
1362        let loaded_coordinators = coordinators
1363            .iter()
1364            .map(|c| Coordinator::load(&c.save()))
1365            .collect::<Vec<Coordinator>>();
1366
1367        assert_eq!(coordinators, loaded_coordinators);
1368
1369        let loaded_signers = signers
1370            .iter()
1371            .map(|s| Signer::<SignerType>::load(&s.save()))
1372            .collect::<Vec<Signer<SignerType>>>();
1373
1374        assert_eq!(signers, loaded_signers);
1375    }
1376
1377    /// Test if a signer will generate a new nonce after a signing round as a defense
1378    /// against a malicious coordinator who requests multiple signing rounds
1379    /// with no nonce round in between to generate a new nonce
1380    pub fn gen_nonces<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
1381        num_signers: u32,
1382        keys_per_signer: u32,
1383    ) {
1384        let mut rng = OsRng;
1385
1386        let (mut coordinators, mut signers) =
1387            run_dkg::<Coordinator, SignerType>(num_signers, keys_per_signer);
1388
1389        let msg = "It was many and many a year ago, in a kingdom by the sea"
1390            .as_bytes()
1391            .to_vec();
1392
1393        let signature_type = SignatureType::Frost;
1394
1395        // Start a signing round
1396        let message = coordinators
1397            .first_mut()
1398            .unwrap()
1399            .start_signing_round(&msg, signature_type, None)
1400            .unwrap();
1401        assert_eq!(
1402            coordinators.first_mut().unwrap().get_state(),
1403            State::NonceGather(signature_type)
1404        );
1405
1406        // Send the NonceRequest to all signers and gather NonceResponses
1407        // by sharing with all other signers and coordinator
1408        let (outbound_messages, operation_results) =
1409            feedback_messages(&mut coordinators, &mut signers, &[message]);
1410        assert!(operation_results.is_empty());
1411        assert_eq!(
1412            coordinators.first_mut().unwrap().get_state(),
1413            State::SigShareGather(signature_type)
1414        );
1415
1416        // Once the coordinator has received sufficient NonceResponses,
1417        // it should send out a SignatureShareRequest
1418        assert_eq!(outbound_messages.len(), 1);
1419        assert!(
1420            matches!(outbound_messages[0].msg, Message::SignatureShareRequest(_)),
1421            "Expected SignatureShareRequest message"
1422        );
1423
1424        // Pass the SignatureShareRequest to the first signer and get his SignatureShares
1425        // which should use the nonce generated before sending out NonceResponse above
1426        let messages1 = signers[0].process(&outbound_messages[0], &mut rng).unwrap();
1427
1428        // Pass the SignatureShareRequest to the second signer and get his SignatureShares
1429        // which should use the nonce generated just before sending out the previous SignatureShare
1430        let messages2 = signers[0].process(&outbound_messages[0], &mut rng).unwrap();
1431
1432        // iterate through the responses and collect the embedded shares
1433        // if the signer didn't generate a nonce after sending the first signature shares
1434        // then the shares should be the same, since the message and everything else is
1435        for (message1, message2) in messages1.into_iter().zip(messages2) {
1436            let share1 = if let Message::SignatureShareResponse(response) = message1 {
1437                response.signature_shares[0].clone()
1438            } else {
1439                panic!("Message should have been SignatureShareResponse");
1440            };
1441            let share2 = if let Message::SignatureShareResponse(response) = message2 {
1442                response.signature_shares[0].clone()
1443            } else {
1444                panic!("Message should have been SignatureShareResponse");
1445            };
1446
1447            assert_ne!(share1.z_i, share2.z_i);
1448        }
1449    }
1450
1451    pub fn bad_signature_share_request<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
1452        num_signers: u32,
1453        keys_per_signer: u32,
1454    ) {
1455        let (mut coordinators, mut signers) =
1456            run_dkg::<Coordinator, SignerType>(num_signers, keys_per_signer);
1457
1458        let msg = "It was many and many a year ago, in a kingdom by the sea"
1459            .as_bytes()
1460            .to_vec();
1461
1462        // Start a signing round
1463        let signature_type = SignatureType::Frost;
1464        let message = coordinators
1465            .first_mut()
1466            .unwrap()
1467            .start_signing_round(&msg, signature_type, None)
1468            .unwrap();
1469        assert_eq!(
1470            coordinators.first_mut().unwrap().get_state(),
1471            State::NonceGather(signature_type)
1472        );
1473
1474        // Send the message to all signers and gather responses by sharing with all other signers and coordinator
1475        let (outbound_messages, operation_results) =
1476            feedback_messages(&mut coordinators, &mut signers, &[message]);
1477        assert!(operation_results.is_empty());
1478        assert_eq!(
1479            coordinators.first_mut().unwrap().get_state(),
1480            State::SigShareGather(signature_type)
1481        );
1482
1483        assert_eq!(outbound_messages.len(), 1);
1484        assert!(
1485            matches!(outbound_messages[0].msg, Message::SignatureShareRequest(_)),
1486            "Expected SignatureShareRequest message"
1487        );
1488
1489        let messages = outbound_messages.clone();
1490        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &messages);
1491        assert!(result.is_ok());
1492
1493        // test request with no NonceResponses
1494        let mut packet = outbound_messages[0].clone();
1495        let Message::SignatureShareRequest(ref mut request) = packet.msg else {
1496            panic!("failed to match message");
1497        };
1498        request.nonce_responses.clear();
1499
1500        // Send the SignatureShareRequest message to all signers and share
1501        // their responses with the coordinator and signers
1502        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &[packet]);
1503        assert!(
1504            matches!(
1505                result,
1506                Err(StateMachineError::Signer(SignerError::InvalidNonceResponse))
1507            ),
1508            "Should have received signer invalid nonce response error, got {result:?}"
1509        );
1510
1511        // test request with a duplicate NonceResponse
1512        let mut packet = outbound_messages[0].clone();
1513        let Message::SignatureShareRequest(ref mut request) = packet.msg else {
1514            panic!("failed to match message");
1515        };
1516        request
1517            .nonce_responses
1518            .push(request.nonce_responses[0].clone());
1519
1520        // Send the SignatureShareRequest message to all signers and share
1521        // their responses with the coordinator and signers
1522        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &[packet]);
1523        assert!(
1524            matches!(
1525                result,
1526                Err(StateMachineError::Signer(SignerError::InvalidNonceResponse))
1527            ),
1528            "Should have received signer invalid nonce response error, got {result:?}"
1529        );
1530
1531        // test request with an out of range signer_id
1532        let mut packet = outbound_messages[0].clone();
1533        let Message::SignatureShareRequest(ref mut request) = packet.msg else {
1534            panic!("failed to match message");
1535        };
1536        request.nonce_responses[0].signer_id = num_signers;
1537
1538        // Send the SignatureShareRequest message to all signers and share
1539        // their responses with the coordinator and signers
1540        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &[packet]);
1541        assert!(
1542            matches!(
1543                result,
1544                Err(StateMachineError::Signer(SignerError::InvalidNonceResponse))
1545            ),
1546            "Should have received signer invalid nonce response error, got {result:?}"
1547        );
1548    }
1549
1550    pub fn invalid_nonce<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
1551        num_signers: u32,
1552        keys_per_signer: u32,
1553    ) {
1554        let (mut coordinators, mut signers) =
1555            run_dkg::<Coordinator, SignerType>(num_signers, keys_per_signer);
1556
1557        let msg = "It was many and many a year ago, in a kingdom by the sea"
1558            .as_bytes()
1559            .to_vec();
1560
1561        // Start a signing round
1562        let signature_type = SignatureType::Frost;
1563        let message = coordinators
1564            .first_mut()
1565            .unwrap()
1566            .start_signing_round(&msg, signature_type, None)
1567            .unwrap();
1568        assert_eq!(
1569            coordinators.first_mut().unwrap().get_state(),
1570            State::NonceGather(signature_type)
1571        );
1572
1573        // Send the message to all signers and gather responses by sharing with all other signers and coordinator
1574        let (outbound_messages, operation_results) =
1575            feedback_messages(&mut coordinators, &mut signers, &[message]);
1576        assert!(operation_results.is_empty());
1577        assert_eq!(
1578            coordinators.first_mut().unwrap().get_state(),
1579            State::SigShareGather(signature_type)
1580        );
1581
1582        assert_eq!(outbound_messages.len(), 1);
1583        assert!(
1584            matches!(outbound_messages[0].msg, Message::SignatureShareRequest(_)),
1585            "Expected SignatureShareRequest message"
1586        );
1587
1588        let messages = outbound_messages.clone();
1589        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &messages);
1590        assert!(result.is_ok());
1591
1592        // test request with NonceResponse having zero nonce
1593        let mut packet = outbound_messages[0].clone();
1594        let Message::SignatureShareRequest(ref mut request) = packet.msg else {
1595            panic!("failed to match message");
1596        };
1597        for nonce_response in &mut request.nonce_responses {
1598            for nonce in &mut nonce_response.nonces {
1599                nonce.D = Point::new();
1600                nonce.E = Point::new();
1601            }
1602        }
1603
1604        // Send the SignatureShareRequest message to all signers and share
1605        // their responses with the coordinator and signers
1606        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &[packet]);
1607        assert!(
1608            matches!(
1609                result,
1610                Err(StateMachineError::Signer(SignerError::InvalidNonceResponse))
1611            ),
1612            "Should have received signer invalid nonce response error, got {result:?}"
1613        );
1614
1615        // test request with NonceResponse having generator nonce
1616        let mut packet = outbound_messages[0].clone();
1617        let Message::SignatureShareRequest(ref mut request) = packet.msg else {
1618            panic!("failed to match message");
1619        };
1620        for nonce_response in &mut request.nonce_responses {
1621            for nonce in &mut nonce_response.nonces {
1622                nonce.D = G;
1623                nonce.E = G;
1624            }
1625        }
1626
1627        // Send the SignatureShareRequest message to all signers and share
1628        // their responses with the coordinator and signers
1629        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &[packet]);
1630        assert!(
1631            matches!(
1632                result,
1633                Err(StateMachineError::Signer(SignerError::InvalidNonceResponse))
1634            ),
1635            "Should have received signer invalid nonce response error, got {result:?}"
1636        );
1637
1638        // test request with a duplicate NonceResponse
1639        let mut packet = outbound_messages[0].clone();
1640        let Message::SignatureShareRequest(ref mut request) = packet.msg else {
1641            panic!("failed to match message");
1642        };
1643        request
1644            .nonce_responses
1645            .push(request.nonce_responses[0].clone());
1646
1647        // Send the SignatureShareRequest message to all signers and share
1648        // their responses with the coordinator and signers
1649        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &[packet]);
1650        assert!(
1651            matches!(
1652                result,
1653                Err(StateMachineError::Signer(SignerError::InvalidNonceResponse))
1654            ),
1655            "Should have received signer invalid nonce response error, got {result:?}"
1656        );
1657
1658        // test request with an out of range signer_id
1659        let mut packet = outbound_messages[0].clone();
1660        let Message::SignatureShareRequest(ref mut request) = packet.msg else {
1661            panic!("failed to match message");
1662        };
1663        request.nonce_responses[0].signer_id = num_signers;
1664
1665        // Send the SignatureShareRequest message to all signers and share
1666        // their responses with the coordinator and signers
1667        let result = feedback_messages_with_errors(&mut coordinators, &mut signers, &[packet]);
1668        assert!(
1669            matches!(
1670                result,
1671                Err(StateMachineError::Signer(SignerError::InvalidNonceResponse))
1672            ),
1673            "Should have received signer invalid nonce response error, got {result:?}"
1674        );
1675    }
1676
1677    pub fn empty_public_shares<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
1678        num_signers: u32,
1679        keys_per_signer: u32,
1680    ) {
1681        let (mut coordinators, mut signers) =
1682            setup::<Coordinator, SignerType>(num_signers, keys_per_signer);
1683
1684        // We have started a dkg round
1685        let message = coordinators
1686            .first_mut()
1687            .unwrap()
1688            .start_dkg_round(None)
1689            .unwrap();
1690        assert!(coordinators
1691            .first_mut()
1692            .unwrap()
1693            .get_aggregate_public_key()
1694            .is_none());
1695        assert_eq!(
1696            coordinators.first_mut().unwrap().get_state(),
1697            State::DkgPublicGather
1698        );
1699
1700        // Send the DKG Begin message to all signers and gather responses by sharing with all other signers and coordinator
1701        let (outbound_messages, operation_results) = feedback_mutated_messages(
1702            &mut coordinators,
1703            &mut signers,
1704            &[message],
1705            |signer, packets| {
1706                if signer.signer_id != 0 {
1707                    return packets.clone();
1708                }
1709                packets
1710                    .iter()
1711                    .map(|packet| {
1712                        let Message::DkgPublicShares(shares) = &packet.msg else {
1713                            return packet.clone();
1714                        };
1715                        let public_shares = crate::net::DkgPublicShares {
1716                            dkg_id: shares.dkg_id,
1717                            signer_id: shares.signer_id,
1718                            comms: vec![],
1719                            kex_public_key: Point::new(),
1720                            kex_proof: schnorr::Proof {
1721                                R: Point::new(),
1722                                s: Scalar::new(),
1723                            },
1724                        };
1725                        Packet {
1726                            msg: Message::DkgPublicShares(public_shares),
1727                            sig: vec![],
1728                        }
1729                    })
1730                    .collect()
1731            },
1732        );
1733        assert!(operation_results.is_empty());
1734        for coordinator in coordinators.iter() {
1735            assert_eq!(coordinator.get_state(), State::DkgPrivateGather);
1736        }
1737
1738        assert_eq!(outbound_messages.len(), 1);
1739        assert!(
1740            matches!(outbound_messages[0].msg, Message::DkgPrivateBegin(_)),
1741            "Expected DkgPrivateBegin message"
1742        );
1743        // Send the DKG Private Begin message to all signers and share their responses with the coordinator and signers
1744        let (outbound_messages, operation_results) =
1745            feedback_messages(&mut coordinators, &mut signers, &outbound_messages);
1746        assert_eq!(operation_results.len(), 0);
1747        assert_eq!(outbound_messages.len(), 1);
1748        assert!(
1749            matches!(outbound_messages[0].msg, Message::DkgEndBegin(_)),
1750            "Expected DkgEndBegin message"
1751        );
1752
1753        // Send the DkgEndBegin message to all signers and share their responses with the coordinator and signers
1754        let (outbound_messages, operation_results) =
1755            feedback_messages(&mut coordinators, &mut signers, &outbound_messages);
1756        assert_eq!(outbound_messages.len(), 0);
1757        assert_eq!(operation_results.len(), 1);
1758        let OperationResult::DkgError(DkgError::DkgEndFailure {
1759            reported_failures, ..
1760        }) = &operation_results[0]
1761        else {
1762            panic!(
1763                "Expected OperationResult::DkgError got {:?}",
1764                &operation_results[0]
1765            );
1766        };
1767        assert_eq!(
1768            reported_failures.len(),
1769            num_signers as usize,
1770            "Expected {num_signers} DkgFailures got {}",
1771            reported_failures.len()
1772        );
1773        let expected_signer_ids = (0..1).collect::<HashSet<u32>>();
1774        for dkg_failure in reported_failures {
1775            let (_, DkgFailure::MissingPublicShares(signer_ids)) = dkg_failure else {
1776                panic!("Expected DkgFailure::MissingPublicShares got {dkg_failure:?}");
1777            };
1778            assert_eq!(
1779                expected_signer_ids, *signer_ids,
1780                "Expected signer_ids {expected_signer_ids:?} got {signer_ids:?}"
1781            );
1782        }
1783    }
1784
1785    pub fn empty_private_shares<Coordinator: CoordinatorTrait, SignerType: SignerTrait>(
1786        num_signers: u32,
1787        keys_per_signer: u32,
1788    ) {
1789        let (mut coordinators, mut signers) =
1790            setup::<Coordinator, SignerType>(num_signers, keys_per_signer);
1791
1792        // We have started a dkg round
1793        let message = coordinators
1794            .first_mut()
1795            .unwrap()
1796            .start_dkg_round(None)
1797            .unwrap();
1798        assert!(coordinators
1799            .first_mut()
1800            .unwrap()
1801            .get_aggregate_public_key()
1802            .is_none());
1803        assert_eq!(
1804            coordinators.first_mut().unwrap().get_state(),
1805            State::DkgPublicGather
1806        );
1807
1808        // Send the DKG Begin message to all signers and gather responses by sharing with all other signers and coordinator
1809        let (outbound_messages, operation_results) =
1810            feedback_messages(&mut coordinators, &mut signers, &[message]);
1811        assert!(operation_results.is_empty());
1812        for coordinator in coordinators.iter() {
1813            assert_eq!(coordinator.get_state(), State::DkgPrivateGather);
1814        }
1815
1816        assert_eq!(outbound_messages.len(), 1);
1817        assert!(
1818            matches!(outbound_messages[0].msg, Message::DkgPrivateBegin(_)),
1819            "Expected DkgPrivateBegin message"
1820        );
1821
1822        // Send the DKG Begin message to all signers and gather responses by sharing with all other signers and coordinator
1823        let (outbound_messages, operation_results) = feedback_mutated_messages(
1824            &mut coordinators,
1825            &mut signers,
1826            &[outbound_messages[0].clone()],
1827            |signer, packets| {
1828                if signer.signer_id != 0 {
1829                    return packets.clone();
1830                }
1831                packets
1832                    .iter()
1833                    .map(|packet| {
1834                        let Message::DkgPrivateShares(shares) = &packet.msg else {
1835                            return packet.clone();
1836                        };
1837                        let private_shares = crate::net::DkgPrivateShares {
1838                            dkg_id: shares.dkg_id,
1839                            signer_id: shares.signer_id,
1840                            shares: vec![],
1841                        };
1842                        Packet {
1843                            msg: Message::DkgPrivateShares(private_shares),
1844                            sig: vec![],
1845                        }
1846                    })
1847                    .collect()
1848            },
1849        );
1850        assert_eq!(operation_results.len(), 0);
1851        assert_eq!(outbound_messages.len(), 1);
1852        assert!(
1853            matches!(&outbound_messages[0].msg, Message::DkgEndBegin(_)),
1854            "Expected DkgEndBegin message"
1855        );
1856
1857        // Send the DkgEndBegin message to all signers and share their responses with the coordinator and signers
1858        let (outbound_messages, operation_results) =
1859            feedback_messages(&mut coordinators, &mut signers, &outbound_messages);
1860        assert_eq!(outbound_messages.len(), 0);
1861        assert_eq!(operation_results.len(), 1);
1862        let OperationResult::DkgError(DkgError::DkgEndFailure {
1863            reported_failures, ..
1864        }) = &operation_results[0]
1865        else {
1866            panic!(
1867                "Expected OperationResult::DkgError(DkgError::DkgEndFailure) got {:?}",
1868                operation_results[0]
1869            );
1870        };
1871        assert_eq!(
1872            reported_failures.len(),
1873            num_signers as usize,
1874            "Expected {num_signers} DkgFailures got {}",
1875            reported_failures.len()
1876        );
1877        let expected_signer_ids = (0..1).collect::<HashSet<u32>>();
1878        for dkg_failure in reported_failures {
1879            let (_, DkgFailure::MissingPrivateShares(signer_ids)) = dkg_failure else {
1880                panic!("Expected DkgFailure::MissingPublicShares got {dkg_failure:?}");
1881            };
1882            assert_eq!(
1883                expected_signer_ids, *signer_ids,
1884                "Expected signer_ids {expected_signer_ids:?} got {signer_ids:?}"
1885            );
1886        }
1887    }
1888}