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