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)]
22pub enum State {
24 #[default]
26 Idle,
27 DkgPublicDistribute,
29 DkgPublicGather,
31 DkgPublicSharesDoneDistribute,
33 DkgPublicSharesDoneGather,
35 DkgPrivateDistribute,
37 DkgPrivateGather,
39 DkgPrivateSharesDoneDistribute,
41 DkgPrivateSharesDoneGather,
43 DkgEndDistribute,
45 DkgEndGather,
47 NonceRequest(SignatureType),
49 NonceGather(SignatureType),
51 SigShareRequest(SignatureType),
53 SigShareGather(SignatureType),
55}
56
57#[derive(thiserror::Error, Clone, Debug)]
58#[allow(clippy::large_enum_variant)]
59pub enum Error {
61 #[error("Bad State Change: {0}")]
63 BadStateChange(String),
64 #[error("Bad dkg_id: got {0} expected {1}")]
66 BadDkgId(u64, u64),
67 #[error("Bad sign_id: got {0} expected {1}")]
69 BadSignId(u64, u64),
70 #[error("Bad sign_iter_id: got {0} expected {1}")]
72 BadSignIterId(u64, u64),
73 #[error("Malicious signer {0}")]
75 MaliciousSigner(u32),
76 #[error("Aggregator: {0}")]
78 Aggregator(AggregatorError),
79 #[error("Schnorr Proof failed to verify")]
81 SchnorrProofFailed,
82 #[error("No aggregate public key set")]
84 MissingAggregatePublicKey,
85 #[error("No schnorr proof set")]
87 MissingSchnorrProof,
88 #[error("No signature set")]
90 MissingSignature,
91 #[error("Missing message nonce information")]
93 MissingMessageNonceInfo,
94 #[error("Missing public key for signer {0}")]
96 MissingPublicKeyForSigner(u32),
97 #[error("Missing key IDs for signer {0}")]
99 MissingKeyIDsForSigner(u32),
100 #[error("Bad key IDs for signer {0}")]
102 BadKeyIDsForSigner(u32),
103 #[error("DKG failure from signers")]
105 DkgFailure {
106 reported_failures: HashMap<u32, DkgFailure>,
108 malicious_signers: HashSet<u32>,
110 },
111 #[error(
113 "Aggregate key and computed key from party polynomials mismatch: got {0}, expected {1}"
114 )]
115 AggregateKeyPolynomialMismatch(Point, Point),
116 #[error("Supplied party polynomials contained a duplicate party ID")]
118 DuplicatePartyId,
119 #[error("Missing coordinator public key")]
120 MissingCoordinatorPublicKey,
122 #[error("A packet had an invalid signature")]
123 InvalidPacketSignature,
125 #[error("No public shares for signer {0}")]
126 NoPublicSharesForSigner(u32),
128 #[error("A curve point error {0}")]
129 Point(#[from] PointError),
131 #[error("integer conversion error")]
132 TryFromInt(#[from] TryFromIntError),
134}
135
136impl From<AggregatorError> for Error {
137 fn from(err: AggregatorError) -> Self {
138 Error::Aggregator(err)
139 }
140}
141
142#[derive(Default, Clone, PartialEq)]
144pub struct Config {
145 pub num_signers: u32,
147 pub num_keys: u32,
149 pub threshold: u32,
151 pub dkg_threshold: u32,
153 pub sign_threshold: u32,
155 pub message_private_key: Scalar,
157 pub dkg_public_timeout: Option<Duration>,
159 pub dkg_private_timeout: Option<Duration>,
161 pub dkg_end_timeout: Option<Duration>,
163 pub nonce_timeout: Option<Duration>,
165 pub sign_timeout: Option<Duration>,
167 pub public_keys: PublicKeys,
169 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 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 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)]
253pub struct SignRoundInfo {
255 pub public_nonces: BTreeMap<u32, NonceResponse>,
257 pub nonce_recv_key_ids: HashSet<u32>,
259 pub sign_recv_key_ids: HashSet<u32>,
261 pub sign_wait_signer_ids: HashSet<u32>,
263}
264
265#[derive(Default, Clone, Debug, PartialEq)]
267pub struct SavedState {
268 pub config: Config,
270 pub current_dkg_id: u64,
272 pub current_sign_id: u64,
274 pub current_sign_iter_id: u64,
276 pub dkg_public_shares: BTreeMap<u32, DkgPublicShares>,
278 pub dkg_private_shares: BTreeMap<u32, DkgPrivateShares>,
280 pub dkg_end_messages: BTreeMap<u32, DkgEnd>,
282 pub party_polynomials: HashMap<u32, PolyCommitment>,
284 pub signature_shares: BTreeMap<u32, Vec<SignatureShare>>,
286 pub message_nonces: BTreeMap<Vec<u8>, SignRoundInfo>,
288 pub aggregate_public_key: Option<Point>,
290 pub signature: Option<Signature>,
292 pub schnorr_proof: Option<SchnorrProof>,
294 pub dkg_wait_signer_ids: HashSet<u32>,
296 pub message: Vec<u8>,
298 pub state: State,
300 pub nonce_start: Option<Instant>,
302 pub dkg_public_start: Option<Instant>,
304 pub dkg_private_start: Option<Instant>,
306 pub dkg_end_start: Option<Instant>,
308 pub sign_start: Option<Instant>,
310 pub malicious_signer_ids: HashSet<u32>,
312 pub malicious_dkg_signer_ids: HashSet<u32>,
314 pub coordinator_public_key: Option<ecdsa::PublicKey>,
316}
317
318pub trait Coordinator: Clone + Debug + PartialEq + StateMachine<State, Error> {
320 fn new(config: Config) -> Self;
322
323 fn load(state: &SavedState) -> Self;
325
326 fn save(&self) -> SavedState;
328
329 fn get_config(&self) -> Config;
331
332 #[cfg(any(test, feature = "testing"))]
334 fn get_config_mut(&mut self) -> &mut Config;
335
336 fn set_coordinator_public_key(&mut self, key: Option<ecdsa::PublicKey>);
338
339 fn set_key_and_party_polynomials(
341 &mut self,
342 aggregate_key: Point,
343 party_polynomials: Vec<(u32, PolyCommitment)>,
344 ) -> Result<(), Error>;
345
346 fn process(
350 &mut self,
351 packet: &Packet,
352 ) -> Result<(Option<Packet>, Option<OperationResult>), Error>;
353
354 fn get_aggregate_public_key(&self) -> Option<Point>;
356
357 fn set_aggregate_public_key(&mut self, aggregate_public_key: Option<Point>);
359
360 fn get_message(&self) -> Vec<u8>;
362
363 fn get_state(&self) -> State;
365
366 fn start_dkg_round(&mut self, dkg_id: Option<u64>) -> Result<Packet, Error>;
368
369 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 fn reset(&mut self);
379}
380
381pub mod frost;
383
384pub 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 for signer in &mut signers {
924 signer.signer.clear_polys();
925 }
926
927 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 assert_eq!(outbound_messages.len(), 1);
1526 assert!(
1527 matches!(outbound_messages[0].msg, Message::SignatureShareRequest(_)),
1528 "Expected SignatureShareRequest message"
1529 );
1530
1531 let messages1 = signers[0].process(&outbound_messages[0], &mut rng).unwrap();
1534
1535 let messages2 = signers[0].process(&outbound_messages[0], &mut rng).unwrap();
1538
1539 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}