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