1use hashbrown::{HashMap, HashSet};
2use std::collections::BTreeMap;
3use tracing::{debug, info, warn};
4
5use crate::{
6 common::{PolyCommitment, PublicNonce, Signature, SignatureShare},
7 compute,
8 curve::{ecdsa, point::Point},
9 net::{
10 DkgBegin, DkgEnd, DkgEndBegin, DkgPrivateBegin, DkgPrivateShares, DkgPublicShares,
11 DkgStatus, Message, NonceRequest, NonceResponse, Packet, Signable, SignatureShareRequest,
12 SignatureType,
13 },
14 state_machine::{
15 coordinator::{
16 Config, Coordinator as CoordinatorTrait, Error, SavedState, SignRoundInfo, State,
17 },
18 DkgError, OperationResult, SignError, StateMachine,
19 },
20 taproot::SchnorrProof,
21 traits::Aggregator as AggregatorTrait,
22};
23
24#[derive(Clone, Debug, PartialEq)]
26pub struct Coordinator<Aggregator: AggregatorTrait> {
27 config: Config,
29 pub current_dkg_id: u64,
31 current_sign_id: u64,
33 current_sign_iter_id: u64,
35 dkg_public_shares: BTreeMap<u32, DkgPublicShares>,
36 dkg_private_shares: BTreeMap<u32, DkgPrivateShares>,
37 dkg_end_messages: BTreeMap<u32, DkgEnd>,
38 party_polynomials: HashMap<u32, PolyCommitment>,
39 public_nonces: BTreeMap<u32, NonceResponse>,
40 signature_shares: BTreeMap<u32, Vec<SignatureShare>>,
41 pub aggregate_public_key: Option<Point>,
43 signature: Option<Signature>,
44 schnorr_proof: Option<SchnorrProof>,
45 pub ids_to_await: HashSet<u32>,
47 pub message: Vec<u8>,
49 pub state: State,
51 aggregator: Aggregator,
53 pub coordinator_public_key: Option<ecdsa::PublicKey>,
55}
56
57impl<Aggregator: AggregatorTrait> Coordinator<Aggregator> {
58 pub fn process_message(
60 &mut self,
61 packet: &Packet,
62 ) -> Result<(Option<Packet>, Option<OperationResult>), Error> {
63 if self.config.verify_packet_sigs {
64 let Some(coordinator_public_key) = self.coordinator_public_key else {
65 return Err(Error::MissingCoordinatorPublicKey);
66 };
67 if !packet.verify(&self.config.public_keys, &coordinator_public_key) {
68 return Err(Error::InvalidPacketSignature);
69 }
70 }
71 loop {
72 match self.state.clone() {
73 State::Idle => {
74 if let Message::DkgBegin(dkg_begin) = &packet.msg {
76 if self.current_dkg_id == dkg_begin.dkg_id {
77 return Ok((None, None));
79 }
80 let packet = self.start_dkg_round(Some(dkg_begin.dkg_id))?;
82 return Ok((Some(packet), None));
83 } else if let Message::NonceRequest(nonce_request) = &packet.msg {
84 if self.current_sign_id == nonce_request.sign_id {
85 return Ok((None, None));
87 }
88 self.current_sign_iter_id = nonce_request.sign_iter_id;
89 let packet = self.start_signing_round(
91 nonce_request.message.as_slice(),
92 nonce_request.signature_type,
93 Some(nonce_request.sign_id),
94 )?;
95 return Ok((Some(packet), None));
96 }
97 return Ok((None, None));
98 }
99 State::DkgPublicDistribute => {
100 let packet = self.start_public_shares()?;
101 return Ok((Some(packet), None));
102 }
103 State::DkgPublicGather => {
104 self.gather_public_shares(packet)?;
105 if self.state == State::DkgPublicGather {
106 return Ok((None, None));
108 }
109 }
110 State::DkgPrivateDistribute => {
111 let packet = self.start_private_shares()?;
112 return Ok((Some(packet), None));
113 }
114 State::DkgPrivateGather => {
115 self.gather_private_shares(packet)?;
116 if self.state == State::DkgPrivateGather {
117 return Ok((None, None));
119 }
120 }
121 State::DkgEndDistribute => {
122 let packet = self.start_dkg_end()?;
123 return Ok((Some(packet), None));
124 }
125 State::DkgEndGather => {
126 if let Err(error) = self.gather_dkg_end(packet) {
127 if let Error::DkgFailure {
128 reported_failures,
129 malicious_signers,
130 } = error
131 {
132 return Ok((
133 None,
134 Some(OperationResult::DkgError(DkgError::DkgEndFailure {
135 reported_failures,
136 malicious_signers,
137 })),
138 ));
139 } else {
140 return Err(error);
141 }
142 }
143 if self.state == State::DkgEndGather {
144 return Ok((None, None));
146 } else if self.state == State::Idle {
147 return Ok((
149 None,
150 Some(OperationResult::Dkg(
151 self.aggregate_public_key
152 .ok_or(Error::MissingAggregatePublicKey)?,
153 )),
154 ));
155 }
156 }
157 State::NonceRequest(signature_type) => {
158 let packet = self.request_nonces(signature_type)?;
159 return Ok((Some(packet), None));
160 }
161 State::NonceGather(signature_type) => {
162 self.gather_nonces(packet, signature_type)?;
163 if self.state == State::NonceGather(signature_type) {
164 return Ok((None, None));
166 }
167 }
168 State::SigShareRequest(signature_type) => {
169 let packet = self.request_sig_shares(signature_type)?;
170 return Ok((Some(packet), None));
171 }
172 State::SigShareGather(signature_type) => {
173 if let Err(e) = self.gather_sig_shares(packet, signature_type) {
174 return Ok((
175 None,
176 Some(OperationResult::SignError(SignError::Coordinator(e))),
177 ));
178 }
179 if self.state == State::SigShareGather(signature_type) {
180 return Ok((None, None));
182 } else if self.state == State::Idle {
183 if let SignatureType::Taproot(_) = signature_type {
185 let schnorr_proof = self
186 .schnorr_proof
187 .as_ref()
188 .ok_or(Error::MissingSchnorrProof)?;
189 return Ok((
190 None,
191 Some(OperationResult::SignTaproot(SchnorrProof {
192 r: schnorr_proof.r,
193 s: schnorr_proof.s,
194 })),
195 ));
196 } else if let SignatureType::Schnorr = signature_type {
197 let schnorr_proof = self
198 .schnorr_proof
199 .as_ref()
200 .ok_or(Error::MissingSchnorrProof)?;
201 return Ok((
202 None,
203 Some(OperationResult::SignSchnorr(SchnorrProof {
204 r: schnorr_proof.r,
205 s: schnorr_proof.s,
206 })),
207 ));
208 } else {
209 let signature =
210 self.signature.as_ref().ok_or(Error::MissingSignature)?;
211 return Ok((
212 None,
213 Some(OperationResult::Sign(Signature {
214 R: signature.R,
215 z: signature.z,
216 })),
217 ));
218 }
219 }
220 }
221 }
222 }
223 }
224
225 pub fn start_public_shares(&mut self) -> Result<Packet, Error> {
227 self.dkg_public_shares.clear();
228 self.party_polynomials.clear();
229 self.ids_to_await = (0..self.config.num_signers).collect();
230 info!(
231 dkg_id = %self.current_dkg_id,
232 "Starting Public Share Distribution"
233 );
234 let dkg_begin = DkgBegin {
235 dkg_id: self.current_dkg_id,
236 };
237
238 let dkg_begin_packet = Packet {
239 sig: dkg_begin
240 .sign(&self.config.message_private_key)
241 .expect("Failed to sign DkgBegin"),
242 msg: Message::DkgBegin(dkg_begin),
243 };
244 self.move_to(State::DkgPublicGather)?;
245 Ok(dkg_begin_packet)
246 }
247
248 pub fn start_private_shares(&mut self) -> Result<Packet, Error> {
250 self.ids_to_await = (0..self.config.num_signers).collect();
251 info!(
252 dkg_id = %self.current_dkg_id,
253 "Starting Private Share Distribution"
254 );
255 let dkg_begin = DkgPrivateBegin {
256 dkg_id: self.current_dkg_id,
257 key_ids: (1..self.config.num_keys + 1).collect(),
258 signer_ids: (0..self.config.num_signers).collect(),
259 };
260 let dkg_private_begin_msg = Packet {
261 sig: dkg_begin
262 .sign(&self.config.message_private_key)
263 .expect("Failed to sign DkgPrivateBegin"),
264 msg: Message::DkgPrivateBegin(dkg_begin),
265 };
266 self.move_to(State::DkgPrivateGather)?;
267 Ok(dkg_private_begin_msg)
268 }
269
270 pub fn start_dkg_end(&mut self) -> Result<Packet, Error> {
272 self.ids_to_await = (0..self.config.num_signers).collect();
273 info!(
274 dkg_id = %self.current_dkg_id,
275 "Starting DKG End Distribution"
276 );
277 let dkg_begin = DkgEndBegin {
278 dkg_id: self.current_dkg_id,
279 key_ids: (0..self.config.num_keys).collect(),
280 signer_ids: (0..self.config.num_signers).collect(),
281 };
282 let dkg_end_begin_msg = Packet {
283 sig: dkg_begin.sign(&self.config.message_private_key).expect(""),
284 msg: Message::DkgEndBegin(dkg_begin),
285 };
286 self.move_to(State::DkgEndGather)?;
287 Ok(dkg_end_begin_msg)
288 }
289
290 fn gather_public_shares(&mut self, packet: &Packet) -> Result<(), Error> {
291 if let Message::DkgPublicShares(dkg_public_shares) = &packet.msg {
292 if dkg_public_shares.dkg_id != self.current_dkg_id {
293 return Err(Error::BadDkgId(
294 dkg_public_shares.dkg_id,
295 self.current_dkg_id,
296 ));
297 }
298
299 let signer_public_keys = &self.config.public_keys.signers;
301 if !signer_public_keys.contains_key(&dkg_public_shares.signer_id) {
302 warn!(signer_id = %dkg_public_shares.signer_id, "No public key in config");
303 return Ok(());
304 };
305
306 let have_shares = self
307 .dkg_public_shares
308 .contains_key(&dkg_public_shares.signer_id);
309
310 if have_shares {
311 info!(signer_id = %dkg_public_shares.signer_id, "received duplicate DkgPublicShares");
312 return Ok(());
313 }
314
315 self.ids_to_await.remove(&dkg_public_shares.signer_id);
316
317 self.dkg_public_shares
318 .insert(dkg_public_shares.signer_id, dkg_public_shares.clone());
319 for (party_id, comm) in &dkg_public_shares.comms {
320 self.party_polynomials.insert(*party_id, comm.clone());
321 }
322
323 debug!(
324 dkg_id = %dkg_public_shares.dkg_id,
325 signer_id = %dkg_public_shares.signer_id,
326 "DkgPublicShares received"
327 );
328 }
329
330 if self.ids_to_await.is_empty() {
331 self.move_to(State::DkgPrivateDistribute)?;
332 }
333 Ok(())
334 }
335
336 fn gather_private_shares(&mut self, packet: &Packet) -> Result<(), Error> {
337 if let Message::DkgPrivateShares(dkg_private_shares) = &packet.msg {
338 if dkg_private_shares.dkg_id != self.current_dkg_id {
339 return Err(Error::BadDkgId(
340 dkg_private_shares.dkg_id,
341 self.current_dkg_id,
342 ));
343 }
344
345 let signer_public_keys = &self.config.public_keys.signers;
347 if !signer_public_keys.contains_key(&dkg_private_shares.signer_id) {
348 warn!(signer_id = %dkg_private_shares.signer_id, "No public key in config");
349 return Ok(());
350 };
351
352 let has_received_shares = self
353 .dkg_private_shares
354 .contains_key(&dkg_private_shares.signer_id);
355 if has_received_shares {
356 info!(signer_id = %dkg_private_shares.signer_id, "received duplicate DkgPrivateShares");
357 return Ok(());
358 }
359
360 self.ids_to_await.remove(&dkg_private_shares.signer_id);
361
362 self.dkg_private_shares
363 .insert(dkg_private_shares.signer_id, dkg_private_shares.clone());
364 info!(
365 dkg_id = %dkg_private_shares.dkg_id,
366 signer_id = %dkg_private_shares.signer_id,
367 "DkgPrivateShares received"
368 );
369 }
370
371 if self.ids_to_await.is_empty() {
372 self.move_to(State::DkgEndDistribute)?;
373 }
374 Ok(())
375 }
376
377 fn gather_dkg_end(&mut self, packet: &Packet) -> Result<(), Error> {
378 debug!(
379 dkg_id = %self.current_dkg_id,
380 waiting = ?self.ids_to_await,
381 "Waiting for Dkg End from signers"
382 );
383 if let Message::DkgEnd(dkg_end) = &packet.msg {
384 if dkg_end.dkg_id != self.current_dkg_id {
385 return Err(Error::BadDkgId(dkg_end.dkg_id, self.current_dkg_id));
386 }
387 if self.ids_to_await.contains(&dkg_end.signer_id) {
388 self.ids_to_await.remove(&dkg_end.signer_id);
389 self.dkg_end_messages
390 .insert(dkg_end.signer_id, dkg_end.clone());
391 debug!(
392 dkg_id = %dkg_end.dkg_id,
393 signer_id = %dkg_end.signer_id,
394 waiting = ?self.ids_to_await,
395 "DkgEnd received"
396 );
397 }
398 }
399
400 if self.ids_to_await.is_empty() {
401 let mut reported_failures = HashMap::new();
402
403 for (signer_id, dkg_end) in &self.dkg_end_messages {
404 if let DkgStatus::Failure(dkg_failure) = &dkg_end.status {
405 warn!(%signer_id, ?dkg_failure, "DkgEnd failure");
406 reported_failures.insert(*signer_id, dkg_failure.clone());
407 }
408 }
409
410 if reported_failures.is_empty() {
411 self.dkg_end_gathered()?;
412 } else {
413 return Err(Error::DkgFailure {
414 reported_failures,
415 malicious_signers: Default::default(),
416 });
417 }
418 }
419 Ok(())
420 }
421
422 fn dkg_end_gathered(&mut self) -> Result<(), Error> {
423 for signer_id in self.dkg_private_shares.keys() {
425 let Some(dkg_public_shares) = self.dkg_public_shares.get(signer_id) else {
426 warn!(%signer_id, "no DkgPublicShares");
427 return Err(Error::BadStateChange(format!("Should not have transitioned to DkgEndGather since we were missing DkgPublicShares from signer {signer_id}")));
428 };
429 for (party_id, comm) in &dkg_public_shares.comms {
430 self.party_polynomials.insert(*party_id, comm.clone());
431 }
432 }
433
434 let key = self
436 .party_polynomials
437 .iter()
438 .fold(Point::default(), |s, (_, comm)| s + comm.poly[0]);
439
440 info!(
441 %key,
442 "Aggregate public key"
443 );
444 self.aggregate_public_key = Some(key);
445 self.move_to(State::Idle)
446 }
447
448 fn request_nonces(&mut self, signature_type: SignatureType) -> Result<Packet, Error> {
449 self.public_nonces.clear();
450 info!(
451 sign_id = %self.current_sign_id,
452 sign_iter_id = %self.current_sign_iter_id,
453 "Requesting Nonces"
454 );
455 let nonce_request = NonceRequest {
456 dkg_id: self.current_dkg_id,
457 sign_id: self.current_sign_id,
458 sign_iter_id: self.current_sign_iter_id,
459 message: self.message.clone(),
460 signature_type,
461 };
462 let nonce_request_msg = Packet {
463 sig: nonce_request
464 .sign(&self.config.message_private_key)
465 .expect(""),
466 msg: Message::NonceRequest(nonce_request),
467 };
468 self.ids_to_await = (0..self.config.num_signers).collect();
469 self.move_to(State::NonceGather(signature_type))?;
470 Ok(nonce_request_msg)
471 }
472
473 fn gather_nonces(
474 &mut self,
475 packet: &Packet,
476 signature_type: SignatureType,
477 ) -> Result<(), Error> {
478 if let Message::NonceResponse(nonce_response) = &packet.msg {
479 if nonce_response.dkg_id != self.current_dkg_id {
480 return Err(Error::BadDkgId(nonce_response.dkg_id, self.current_dkg_id));
481 }
482 if nonce_response.sign_id != self.current_sign_id {
483 return Err(Error::BadSignId(
484 nonce_response.sign_id,
485 self.current_sign_id,
486 ));
487 }
488 if nonce_response.sign_iter_id != self.current_sign_iter_id {
489 return Err(Error::BadSignIterId(
490 nonce_response.sign_iter_id,
491 self.current_sign_iter_id,
492 ));
493 }
494
495 let signer_public_keys = &self.config.public_keys.signers;
497 if !signer_public_keys.contains_key(&nonce_response.signer_id) {
498 warn!(signer_id = %nonce_response.signer_id, "No public key in config");
499 return Ok(());
500 };
501
502 let Some(signer_key_ids) = self
504 .config
505 .public_keys
506 .signer_key_ids
507 .get(&nonce_response.signer_id)
508 else {
509 warn!(signer_id = %nonce_response.signer_id, "No keys IDs configured");
510 return Ok(());
511 };
512
513 let nonce_response_key_ids = nonce_response
514 .key_ids
515 .iter()
516 .cloned()
517 .collect::<HashSet<u32>>();
518 if *signer_key_ids != nonce_response_key_ids {
519 warn!(signer_id = %nonce_response.signer_id, "Nonce response key_ids didn't match config");
520 return Ok(());
521 }
522
523 for nonce in &nonce_response.nonces {
524 if !nonce.is_valid() {
525 warn!(
526 sign_id = %nonce_response.sign_id,
527 sign_iter_id = %nonce_response.sign_iter_id,
528 signer_id = %nonce_response.signer_id,
529 "Received invalid nonce in NonceResponse"
530 );
531 return Ok(());
532 }
533 }
534
535 let have_nonces = self.public_nonces.contains_key(&nonce_response.signer_id);
536
537 if have_nonces {
538 info!(signer_id = %nonce_response.signer_id, "Received duplicate NonceResponse");
539 return Ok(());
540 }
541
542 self.public_nonces
543 .insert(nonce_response.signer_id, nonce_response.clone());
544 self.ids_to_await.remove(&nonce_response.signer_id);
545 debug!(
546 sign_id = %nonce_response.sign_id,
547 sign_iter_id = %nonce_response.sign_iter_id,
548 signer_id = %nonce_response.signer_id,
549 waiting = ?self.ids_to_await,
550 "NonceResponse received"
551 );
552 }
553 if self.ids_to_await.is_empty() {
554 let aggregate_nonce = self.compute_aggregate_nonce();
555 info!(
556 %aggregate_nonce,
557 "Aggregate nonce"
558 );
559
560 self.move_to(State::SigShareRequest(signature_type))?;
561 }
562 Ok(())
563 }
564
565 fn request_sig_shares(&mut self, signature_type: SignatureType) -> Result<Packet, Error> {
566 self.signature_shares.clear();
567 info!(
568 sign_id = %self.current_sign_id,
569 "Requesting Signature Shares"
570 );
571 let nonce_responses = (0..self.config.num_signers)
572 .map(|i| self.public_nonces[&i].clone())
573 .collect::<Vec<NonceResponse>>();
574 let sig_share_request = SignatureShareRequest {
575 dkg_id: self.current_dkg_id,
576 sign_id: self.current_sign_id,
577 sign_iter_id: self.current_sign_iter_id,
578 nonce_responses,
579 message: self.message.clone(),
580 signature_type,
581 };
582 let sig_share_request_msg = Packet {
583 sig: sig_share_request
584 .sign(&self.config.message_private_key)
585 .expect(""),
586 msg: Message::SignatureShareRequest(sig_share_request),
587 };
588 self.ids_to_await = (0..self.config.num_signers).collect();
589 self.move_to(State::SigShareGather(signature_type))?;
590
591 Ok(sig_share_request_msg)
592 }
593
594 fn gather_sig_shares(
595 &mut self,
596 packet: &Packet,
597 signature_type: SignatureType,
598 ) -> Result<(), Error> {
599 if let Message::SignatureShareResponse(sig_share_response) = &packet.msg {
600 if sig_share_response.dkg_id != self.current_dkg_id {
601 return Err(Error::BadDkgId(
602 sig_share_response.dkg_id,
603 self.current_dkg_id,
604 ));
605 }
606 if sig_share_response.sign_id != self.current_sign_id {
607 return Err(Error::BadSignId(
608 sig_share_response.sign_id,
609 self.current_sign_id,
610 ));
611 }
612
613 let signer_public_keys = &self.config.public_keys.signers;
615 if !signer_public_keys.contains_key(&sig_share_response.signer_id) {
616 warn!(signer_id = %sig_share_response.signer_id, "No public key in config");
617 return Ok(());
618 };
619
620 let Some(signer_key_ids) = self
622 .config
623 .public_keys
624 .signer_key_ids
625 .get(&sig_share_response.signer_id)
626 else {
627 warn!(signer_id = %sig_share_response.signer_id, "No keys IDs configured");
628 return Ok(());
629 };
630
631 let mut sig_share_response_key_ids = HashSet::new();
632 for sig_share in &sig_share_response.signature_shares {
633 for key_id in &sig_share.key_ids {
634 sig_share_response_key_ids.insert(*key_id);
635 }
636 }
637
638 if *signer_key_ids != sig_share_response_key_ids {
639 warn!(signer_id = %sig_share_response.signer_id, "SignatureShareResponse key_ids didn't match config");
640 return Ok(());
641 }
642
643 let have_shares = self
644 .signature_shares
645 .contains_key(&sig_share_response.signer_id);
646
647 if have_shares {
648 info!(signer_id = %sig_share_response.signer_id, "received duplicate SignatureShareResponse");
649 return Ok(());
650 }
651
652 self.signature_shares.insert(
653 sig_share_response.signer_id,
654 sig_share_response.signature_shares.clone(),
655 );
656 self.ids_to_await.remove(&sig_share_response.signer_id);
657 debug!(
658 sign_id = %sig_share_response.sign_id,
659 signer_id = %sig_share_response.signer_id,
660 waiting = ?self.ids_to_await,
661 "SignatureShareResponse received"
662 );
663 }
664 if self.ids_to_await.is_empty() {
665 let nonce_responses = (0..self.config.num_signers)
667 .map(|i| self.public_nonces[&i].clone())
668 .collect::<Vec<NonceResponse>>();
669
670 let nonces = nonce_responses
671 .iter()
672 .flat_map(|nr| nr.nonces.clone())
673 .collect::<Vec<PublicNonce>>();
674
675 let key_ids = nonce_responses
676 .iter()
677 .flat_map(|nr| nr.key_ids.clone())
678 .collect::<Vec<u32>>();
679
680 let shares = &self
681 .public_nonces
682 .iter()
683 .flat_map(|(i, _)| self.signature_shares[i].clone())
684 .collect::<Vec<SignatureShare>>();
685
686 debug!(
687 nonces_len = %nonces.len(),
688 shares_len = %shares.len(),
689 "aggregator.sign"
690 );
691
692 self.aggregator.init(&self.party_polynomials)?;
693
694 if let SignatureType::Taproot(merkle_root) = signature_type {
695 let schnorr_proof = self.aggregator.sign_taproot(
696 &self.message,
697 &nonces,
698 shares,
699 &key_ids,
700 merkle_root,
701 )?;
702 debug!(
703 r = %schnorr_proof.r,
704 s = %schnorr_proof.s,
705 "SchnorrProof"
706 );
707 self.schnorr_proof = Some(schnorr_proof);
708 } else if let SignatureType::Schnorr = signature_type {
709 let schnorr_proof =
710 self.aggregator
711 .sign_schnorr(&self.message, &nonces, shares, &key_ids)?;
712 debug!(
713 r = %schnorr_proof.r,
714 s = %schnorr_proof.s,
715 "SchnorrProof"
716 );
717 self.schnorr_proof = Some(schnorr_proof);
718 } else {
719 let signature = self
720 .aggregator
721 .sign(&self.message, &nonces, shares, &key_ids)?;
722 debug!(
723 R = %signature.R,
724 z = %signature.z,
725 "Signature"
726 );
727 self.signature = Some(signature);
728 }
729
730 self.move_to(State::Idle)?;
731 }
732 Ok(())
733 }
734
735 #[allow(non_snake_case)]
736 fn compute_aggregate_nonce(&self) -> Point {
737 let party_ids = self
739 .public_nonces
740 .values()
741 .flat_map(|pn| pn.key_ids.clone())
742 .collect::<Vec<u32>>();
743 let nonces = self
744 .public_nonces
745 .values()
746 .flat_map(|pn| pn.nonces.clone())
747 .collect::<Vec<PublicNonce>>();
748 let (_, R) = compute::intermediate(&self.message, &party_ids, &nonces);
749
750 R
751 }
752}
753
754impl<Aggregator: AggregatorTrait> StateMachine<State, Error> for Coordinator<Aggregator> {
755 fn move_to(&mut self, state: State) -> Result<(), Error> {
756 self.can_move_to(&state)?;
757 self.state = state;
758 Ok(())
759 }
760
761 fn can_move_to(&self, state: &State) -> Result<(), Error> {
762 let prev_state = &self.state;
763 let accepted = match state {
764 State::Idle => true,
765 State::DkgPublicDistribute => prev_state == &State::Idle,
766 State::DkgPublicGather => {
767 prev_state == &State::DkgPublicDistribute || prev_state == &State::DkgPublicGather
768 }
769 State::DkgPrivateDistribute => prev_state == &State::DkgPublicGather,
770 State::DkgPrivateGather => {
771 prev_state == &State::DkgPrivateDistribute || prev_state == &State::DkgPrivateGather
772 }
773 State::DkgEndDistribute => prev_state == &State::DkgPrivateGather,
774 State::DkgEndGather => prev_state == &State::DkgEndDistribute,
775 State::NonceRequest(_) => {
776 prev_state == &State::Idle || prev_state == &State::DkgEndGather
777 }
778 State::NonceGather(signature_type) => {
779 prev_state == &State::NonceRequest(*signature_type)
780 || prev_state == &State::NonceGather(*signature_type)
781 }
782 State::SigShareRequest(signature_type) => {
783 prev_state == &State::NonceGather(*signature_type)
784 }
785 State::SigShareGather(signature_type) => {
786 prev_state == &State::SigShareRequest(*signature_type)
787 || prev_state == &State::SigShareGather(*signature_type)
788 }
789 };
790 if accepted {
791 debug!("state change from {prev_state:?} to {state:?}");
792 Ok(())
793 } else {
794 Err(Error::BadStateChange(format!(
795 "{prev_state:?} to {state:?}"
796 )))
797 }
798 }
799}
800
801impl<Aggregator: AggregatorTrait> CoordinatorTrait for Coordinator<Aggregator> {
802 fn new(config: Config) -> Self {
804 Self {
805 aggregator: Aggregator::new(config.num_keys, config.threshold),
806 config,
807 current_dkg_id: 0,
808 current_sign_id: 0,
809 current_sign_iter_id: 0,
810 dkg_public_shares: Default::default(),
811 dkg_private_shares: Default::default(),
812 dkg_end_messages: Default::default(),
813 party_polynomials: Default::default(),
814 public_nonces: Default::default(),
815 signature_shares: Default::default(),
816 aggregate_public_key: None,
817 signature: None,
818 schnorr_proof: None,
819 message: Default::default(),
820 ids_to_await: Default::default(),
821 state: State::Idle,
822 coordinator_public_key: None,
823 }
824 }
825
826 fn load(state: &SavedState) -> Self {
827 Self {
828 aggregator: Aggregator::new(state.config.num_keys, state.config.threshold),
829 config: state.config.clone(),
830 current_dkg_id: state.current_dkg_id,
831 current_sign_id: state.current_sign_id,
832 current_sign_iter_id: state.current_sign_iter_id,
833 dkg_public_shares: state.dkg_public_shares.clone(),
834 dkg_private_shares: state.dkg_private_shares.clone(),
835 dkg_end_messages: state.dkg_end_messages.clone(),
836 party_polynomials: state.party_polynomials.clone(),
837 public_nonces: state.message_nonces[&Vec::new()].public_nonces.clone(),
838 signature_shares: state.signature_shares.clone(),
839 aggregate_public_key: state.aggregate_public_key,
840 signature: state.signature.clone(),
841 schnorr_proof: state.schnorr_proof.clone(),
842 message: state.message.clone(),
843 ids_to_await: state.dkg_wait_signer_ids.clone(),
844 state: state.state.clone(),
845 coordinator_public_key: state.coordinator_public_key,
846 }
847 }
848
849 fn save(&self) -> SavedState {
850 let round_info = SignRoundInfo {
851 public_nonces: self.public_nonces.clone(),
852 nonce_recv_key_ids: Default::default(),
853 sign_recv_key_ids: Default::default(),
854 sign_wait_signer_ids: Default::default(),
855 };
856 let mut message_nonces = BTreeMap::new();
857
858 message_nonces.insert(Vec::new(), round_info);
859
860 SavedState {
861 config: self.config.clone(),
862 current_dkg_id: self.current_dkg_id,
863 current_sign_id: self.current_sign_id,
864 current_sign_iter_id: self.current_sign_iter_id,
865 dkg_public_shares: self.dkg_public_shares.clone(),
866 dkg_private_shares: self.dkg_private_shares.clone(),
867 dkg_end_messages: self.dkg_end_messages.clone(),
868 party_polynomials: self.party_polynomials.clone(),
869 message_nonces,
870 signature_shares: self.signature_shares.clone(),
871 aggregate_public_key: self.aggregate_public_key,
872 signature: self.signature.clone(),
873 schnorr_proof: self.schnorr_proof.clone(),
874 message: self.message.clone(),
875 dkg_wait_signer_ids: self.ids_to_await.clone(),
876 state: self.state.clone(),
877 dkg_public_start: Default::default(),
878 dkg_private_start: Default::default(),
879 dkg_end_start: Default::default(),
880 nonce_start: Default::default(),
881 sign_start: Default::default(),
882 malicious_signer_ids: Default::default(),
883 malicious_dkg_signer_ids: Default::default(),
884 coordinator_public_key: self.coordinator_public_key,
885 }
886 }
887
888 fn get_config(&self) -> Config {
890 self.config.clone()
891 }
892
893 #[cfg(any(test, feature = "testing"))]
894 fn get_config_mut(&mut self) -> &mut Config {
895 &mut self.config
896 }
897
898 fn set_coordinator_public_key(&mut self, key: Option<ecdsa::PublicKey>) {
899 self.coordinator_public_key = key;
900 }
901
902 fn set_key_and_party_polynomials(
905 &mut self,
906 aggregate_key: Point,
907 party_polynomials: Vec<(u32, PolyCommitment)>,
908 ) -> Result<(), Error> {
909 let computed_key = party_polynomials
910 .iter()
911 .fold(Point::default(), |s, (_, comm)| s + comm.poly[0]);
912 if computed_key != aggregate_key {
913 return Err(Error::AggregateKeyPolynomialMismatch(
914 computed_key,
915 aggregate_key,
916 ));
917 }
918 let party_polynomials_len = party_polynomials.len();
919 let party_polynomials = HashMap::from_iter(party_polynomials);
920 if party_polynomials.len() != party_polynomials_len {
921 return Err(Error::DuplicatePartyId);
922 }
923 self.aggregate_public_key = Some(aggregate_key);
924 self.party_polynomials = party_polynomials;
925 Ok(())
926 }
927
928 fn process(
930 &mut self,
931 packet: &Packet,
932 ) -> Result<(Option<Packet>, Option<OperationResult>), Error> {
933 self.process_message(packet)
934 }
935
936 fn get_aggregate_public_key(&self) -> Option<Point> {
938 self.aggregate_public_key
939 }
940
941 fn set_aggregate_public_key(&mut self, aggregate_public_key: Option<Point>) {
943 self.aggregate_public_key = aggregate_public_key;
944 }
945
946 fn get_message(&self) -> Vec<u8> {
948 self.message.clone()
949 }
950
951 fn get_state(&self) -> State {
953 self.state.clone()
954 }
955
956 fn start_dkg_round(&mut self, dkg_id: Option<u64>) -> Result<Packet, Error> {
958 if let Some(id) = dkg_id {
959 self.current_dkg_id = id;
960 } else {
961 self.current_dkg_id = self.current_dkg_id.wrapping_add(1);
962 }
963 info!("Starting DKG round {}", self.current_dkg_id);
964 self.move_to(State::DkgPublicDistribute)?;
965 self.start_public_shares()
966 }
967
968 fn start_signing_round(
970 &mut self,
971 message: &[u8],
972 signature_type: SignatureType,
973 sign_id: Option<u64>,
974 ) -> Result<Packet, Error> {
975 if self.aggregate_public_key.is_none() {
977 return Err(Error::MissingAggregatePublicKey);
978 }
979 self.message = message.to_vec();
980 if let Some(id) = sign_id {
981 self.current_sign_id = id;
982 } else {
983 self.current_sign_id = self.current_sign_id.wrapping_add(1);
984 }
985 info!("Starting signing round {}", self.current_sign_id);
986 self.move_to(State::NonceRequest(signature_type))?;
987 self.request_nonces(signature_type)
988 }
989
990 fn reset(&mut self) {
992 self.state = State::Idle;
993 self.dkg_public_shares.clear();
994 self.party_polynomials.clear();
995 self.public_nonces.clear();
996 self.signature_shares.clear();
997 self.ids_to_await = (0..self.config.num_signers).collect();
998 }
999}
1000
1001#[cfg(test)]
1002pub mod test {
1004 use super::*;
1005 #[cfg(feature = "with_v1")]
1006 use crate::v1;
1007 use crate::{
1008 curve::scalar::Scalar,
1009 net::{DkgBegin, Message, NonceRequest, Packet, SignatureShareResponse, SignatureType},
1010 schnorr::{self, ID},
1011 state_machine::coordinator::{
1012 frost::Coordinator as FrostCoordinator,
1013 test::{
1014 bad_signature_share_request, check_signature_shares, coordinator_state_machine,
1015 empty_private_shares, empty_public_shares, equal_after_save_load, invalid_nonce,
1016 new_coordinator, run_dkg_sign, setup, start_dkg_round, start_signing_round,
1017 verify_packet_sigs,
1018 },
1019 Config, Coordinator as CoordinatorTrait, State,
1020 },
1021 traits::{Aggregator as AggregatorTrait, Signer as SignerTrait},
1022 util::create_rng,
1023 v2,
1024 };
1025
1026 #[test]
1027 #[cfg(feature = "with_v1")]
1028 fn new_coordinator_v1() {
1029 new_coordinator::<FrostCoordinator<v1::Aggregator>>();
1030 }
1031
1032 #[test]
1033 fn new_coordinator_v2() {
1034 new_coordinator::<FrostCoordinator<v2::Aggregator>>();
1035 }
1036
1037 #[test]
1038 #[cfg(feature = "with_v1")]
1039 fn equal_after_save_load_v1() {
1040 equal_after_save_load::<FrostCoordinator<v1::Aggregator>, v1::Signer>(2, 2);
1041 }
1042
1043 #[test]
1044 fn equal_after_save_load_v2() {
1045 equal_after_save_load::<FrostCoordinator<v2::Aggregator>, v2::Signer>(2, 2);
1046 }
1047
1048 #[test]
1049 #[cfg(feature = "with_v1")]
1050 fn coordinator_state_machine_v1() {
1051 coordinator_state_machine::<FrostCoordinator<v1::Aggregator>>();
1052 }
1053
1054 #[test]
1055 fn coordinator_state_machine_v2() {
1056 coordinator_state_machine::<FrostCoordinator<v2::Aggregator>>();
1057 }
1058
1059 #[test]
1060 #[cfg(feature = "with_v1")]
1061 fn start_dkg_round_v1() {
1062 start_dkg_round::<FrostCoordinator<v1::Aggregator>>(None);
1063 start_dkg_round::<FrostCoordinator<v1::Aggregator>>(Some(12345u64));
1064 }
1065
1066 #[test]
1067 fn start_dkg_round_v2() {
1068 start_dkg_round::<FrostCoordinator<v2::Aggregator>>(None);
1069 start_dkg_round::<FrostCoordinator<v2::Aggregator>>(Some(12345u64));
1070 }
1071
1072 #[test]
1073 #[cfg(feature = "with_v1")]
1074 fn start_signing_round_v1() {
1075 start_signing_round::<FrostCoordinator<v1::Aggregator>>(None);
1076 start_signing_round::<FrostCoordinator<v1::Aggregator>>(Some(12345u64));
1077 }
1078
1079 #[test]
1080 fn start_signing_round_v2() {
1081 start_signing_round::<FrostCoordinator<v2::Aggregator>>(None);
1082 start_signing_round::<FrostCoordinator<v2::Aggregator>>(Some(12345u64));
1083 }
1084
1085 #[test]
1086 #[cfg(feature = "with_v1")]
1087 fn start_public_shares_v1() {
1088 start_public_shares::<v1::Aggregator>();
1089 }
1090
1091 #[test]
1092 fn start_public_shares_v2() {
1093 start_public_shares::<v2::Aggregator>();
1094 }
1095
1096 fn start_public_shares<Aggregator: AggregatorTrait>() {
1097 let mut rng = create_rng();
1098 let config = Config::new(10, 40, 28, Scalar::random(&mut rng));
1099 let mut coordinator = FrostCoordinator::<Aggregator>::new(config);
1100
1101 coordinator.state = State::DkgPublicDistribute; let result = coordinator.start_public_shares().unwrap();
1104
1105 assert!(matches!(result.msg, Message::DkgBegin(_)));
1106 assert_eq!(coordinator.get_state(), State::DkgPublicGather);
1107 assert_eq!(coordinator.current_dkg_id, 0);
1108 }
1109
1110 #[test]
1111 #[cfg(feature = "with_v1")]
1112 fn start_private_shares_v1() {
1113 start_private_shares::<v1::Aggregator>();
1114 }
1115
1116 #[test]
1117 fn start_private_shares_v2() {
1118 start_private_shares::<v2::Aggregator>();
1119 }
1120
1121 fn start_private_shares<Aggregator: AggregatorTrait>() {
1122 let mut rng = create_rng();
1123 let config = Config::new(10, 40, 28, Scalar::random(&mut rng));
1124 let mut coordinator = FrostCoordinator::<Aggregator>::new(config);
1125
1126 coordinator.state = State::DkgPrivateDistribute; let message = coordinator.start_private_shares().unwrap();
1129 assert!(matches!(message.msg, Message::DkgPrivateBegin(_)));
1130 assert_eq!(coordinator.get_state(), State::DkgPrivateGather);
1131 assert_eq!(coordinator.current_dkg_id, 0);
1132 }
1133
1134 #[test]
1135 #[cfg(feature = "with_v1")]
1136 fn dkg_public_share_v1() {
1137 dkg_public_share::<v1::Aggregator, v1::Signer>();
1138 }
1139
1140 #[test]
1141 #[cfg(feature = "with_v1")]
1142 fn dkg_public_share_v2() {
1143 dkg_public_share::<v1::Aggregator, v2::Signer>();
1144 }
1145
1146 #[allow(dead_code)]
1148 fn dkg_public_share<Aggregator: AggregatorTrait, Signer: SignerTrait>() {
1149 let ctx = 0u64.to_be_bytes();
1150 let mut rng = create_rng();
1151 let (coordinators, _) = setup::<FrostCoordinator<Aggregator>, Signer>(2, 1);
1152 let mut coordinator: FrostCoordinator<Aggregator> = coordinators[0].clone();
1153
1154 coordinator.start_dkg_round(None).unwrap(); let public_shares = DkgPublicShares {
1156 dkg_id: 1,
1157 signer_id: 0,
1158 comms: vec![(
1159 0,
1160 PolyCommitment {
1161 id: ID::new(&Scalar::new(), &Scalar::new(), &ctx, &mut rng),
1162 poly: vec![],
1163 },
1164 )],
1165 kex_public_key: Point::from(Scalar::random(&mut rng)),
1166 kex_proof: schnorr::Proof {
1167 R: Point::new(),
1168 s: Scalar::new(),
1169 },
1170 };
1171 let packet = Packet {
1172 msg: Message::DkgPublicShares(public_shares.clone()),
1173 sig: Default::default(),
1174 };
1175 coordinator.gather_public_shares(&packet).unwrap();
1176 assert_eq!(1, coordinator.dkg_public_shares.len());
1177
1178 let dup_public_shares = DkgPublicShares {
1180 dkg_id: 1,
1181 signer_id: 0,
1182 comms: vec![(
1183 0,
1184 PolyCommitment {
1185 id: ID::new(&Scalar::new(), &Scalar::new(), &ctx, &mut rng),
1186 poly: vec![],
1187 },
1188 )],
1189 kex_public_key: Point::from(Scalar::random(&mut rng)),
1190 kex_proof: schnorr::Proof {
1191 R: Point::new(),
1192 s: Scalar::new(),
1193 },
1194 };
1195 let dup_packet = Packet {
1196 msg: Message::DkgPublicShares(dup_public_shares.clone()),
1197 sig: Default::default(),
1198 };
1199
1200 coordinator.gather_public_shares(&dup_packet).unwrap();
1201 assert_eq!(1, coordinator.dkg_public_shares.len());
1202 assert_eq!(
1203 public_shares,
1204 coordinator
1205 .dkg_public_shares
1206 .iter()
1207 .next()
1208 .unwrap()
1209 .1
1210 .clone()
1211 );
1212 }
1213
1214 #[test]
1215 #[cfg(feature = "with_v1")]
1216 fn dkg_private_share_v1() {
1217 dkg_private_share::<v1::Aggregator, v1::Signer>();
1218 }
1219
1220 #[test]
1221 fn dkg_private_share_v2() {
1222 dkg_private_share::<v2::Aggregator, v2::Signer>();
1223 }
1224
1225 fn dkg_private_share<Aggregator: AggregatorTrait, Signer: SignerTrait>() {
1227 let (coordinators, _) = setup::<FrostCoordinator<Aggregator>, Signer>(2, 1);
1228 let mut coordinator: FrostCoordinator<Aggregator> = coordinators[0].clone();
1229
1230 coordinator.state = State::DkgPrivateGather;
1231
1232 let private_share = DkgPrivateShares {
1233 dkg_id: 0,
1234 signer_id: 0,
1235 shares: vec![(1, HashMap::new())],
1236 };
1237 let packet = Packet {
1238 msg: Message::DkgPrivateShares(private_share.clone()),
1239 sig: Default::default(),
1240 };
1241 coordinator.gather_private_shares(&packet).unwrap();
1242 assert_eq!(1, coordinator.dkg_private_shares.len());
1243
1244 let dup_private_share = DkgPrivateShares {
1246 dkg_id: 0,
1247 signer_id: 0,
1248 shares: vec![(1, HashMap::new())],
1249 };
1250 let packet = Packet {
1251 msg: Message::DkgPrivateShares(dup_private_share.clone()),
1252 sig: Default::default(),
1253 };
1254 coordinator.gather_private_shares(&packet).unwrap();
1255 assert_eq!(1, coordinator.dkg_private_shares.len());
1256 assert_eq!(
1257 private_share,
1258 coordinator
1259 .dkg_private_shares
1260 .iter()
1261 .next()
1262 .unwrap()
1263 .1
1264 .clone()
1265 );
1266 }
1267
1268 #[test]
1269 #[cfg(feature = "with_v1")]
1270 fn nonce_response_v1() {
1271 nonce_response::<v1::Aggregator, v1::Signer>();
1272 }
1273
1274 #[test]
1275 fn nonce_response_v2() {
1276 nonce_response::<v2::Aggregator, v2::Signer>();
1277 }
1278
1279 fn nonce_response<Aggregator: AggregatorTrait, Signer: SignerTrait>() {
1281 let mut rng = create_rng();
1282 let (coordinators, _) = setup::<FrostCoordinator<Aggregator>, Signer>(2, 1);
1283 let mut coordinator: FrostCoordinator<Aggregator> = coordinators[0].clone();
1284 let signature_type = SignatureType::Frost;
1285 let message = vec![0u8];
1286 coordinator.state = State::NonceGather(signature_type);
1287
1288 let nonce_response = NonceResponse {
1289 dkg_id: 0,
1290 sign_id: 0,
1291 sign_iter_id: 0,
1292 signer_id: 0,
1293 key_ids: vec![1u32],
1294 nonces: vec![PublicNonce {
1295 D: Point::from(Scalar::random(&mut rng)),
1296 E: Point::from(Scalar::random(&mut rng)),
1297 }],
1298 message: message.clone(),
1299 };
1300 let packet = Packet {
1301 msg: Message::NonceResponse(nonce_response.clone()),
1302 sig: Default::default(),
1303 };
1304 coordinator.gather_nonces(&packet, signature_type).unwrap();
1305 assert_eq!(1, coordinator.public_nonces.len());
1306
1307 let dup_nonce_response = NonceResponse {
1309 dkg_id: 0,
1310 sign_id: 0,
1311 sign_iter_id: 0,
1312 signer_id: 0,
1313 key_ids: vec![1u32],
1314 nonces: vec![PublicNonce {
1315 D: Point::from(Scalar::random(&mut rng)),
1316 E: Point::from(Scalar::random(&mut rng)),
1317 }],
1318 message: message.clone(),
1319 };
1320 let packet = Packet {
1321 msg: Message::NonceResponse(dup_nonce_response.clone()),
1322 sig: Default::default(),
1323 };
1324 coordinator.gather_nonces(&packet, signature_type).unwrap();
1325 assert_eq!(1, coordinator.public_nonces.len());
1326 assert_eq!(
1327 nonce_response,
1328 coordinator.public_nonces.iter().next().unwrap().1.clone()
1329 );
1330 }
1331
1332 #[test]
1333 #[cfg(feature = "with_v1")]
1334 fn sig_share_v1() {
1335 sig_share::<v1::Aggregator, v1::Signer>();
1336 }
1337
1338 #[test]
1339 #[cfg(feature = "with_v1")]
1340 fn sig_share_v2() {
1341 sig_share::<v2::Aggregator, v1::Signer>();
1342 }
1343
1344 #[allow(dead_code)]
1346 fn sig_share<Aggregator: AggregatorTrait, Signer: SignerTrait>() {
1347 let mut rng = create_rng();
1348 let (coordinators, _) = setup::<FrostCoordinator<Aggregator>, Signer>(2, 1);
1349 let mut coordinator = coordinators[0].clone();
1350 let signature_type = SignatureType::Frost;
1351
1352 coordinator.ids_to_await = (0..coordinator.config.num_signers).collect();
1353 coordinator.state = State::SigShareGather(signature_type);
1354
1355 let signature_share = SignatureShare {
1356 id: 1,
1357 z_i: Scalar::random(&mut rng),
1358 key_ids: vec![1],
1359 };
1360 let sig_share_response = SignatureShareResponse {
1361 dkg_id: 0,
1362 sign_id: 0,
1363 sign_iter_id: 0,
1364 signer_id: 0,
1365 signature_shares: vec![signature_share.clone()],
1366 };
1367 let packet = Packet {
1368 msg: Message::SignatureShareResponse(sig_share_response.clone()),
1369 sig: Default::default(),
1370 };
1371 coordinator
1372 .gather_sig_shares(&packet, signature_type)
1373 .unwrap();
1374 assert_eq!(1, coordinator.signature_shares.len());
1375
1376 let dup_signature_share = SignatureShare {
1378 id: 1,
1379 z_i: Scalar::random(&mut rng),
1380 key_ids: vec![1],
1381 };
1382 let dup_sig_share_response = SignatureShareResponse {
1383 dkg_id: 0,
1384 sign_id: 0,
1385 sign_iter_id: 0,
1386 signer_id: 0,
1387 signature_shares: vec![dup_signature_share.clone()],
1388 };
1389 let packet = Packet {
1390 msg: Message::SignatureShareResponse(dup_sig_share_response.clone()),
1391 sig: Default::default(),
1392 };
1393 coordinator
1394 .gather_sig_shares(&packet, signature_type)
1395 .unwrap();
1396 assert_eq!(1, coordinator.signature_shares.len());
1397 assert_eq!(
1398 vec![signature_share],
1399 coordinator
1400 .signature_shares
1401 .iter()
1402 .next()
1403 .unwrap()
1404 .1
1405 .clone()
1406 );
1407 }
1408
1409 #[test]
1410 #[cfg(feature = "with_v1")]
1411 fn run_dkg_sign_v1() {
1412 run_dkg_sign::<FrostCoordinator<v1::Aggregator>, v1::Signer>(5, 2);
1413 }
1414
1415 #[test]
1416 fn run_dkg_sign_v2() {
1417 run_dkg_sign::<FrostCoordinator<v2::Aggregator>, v2::Signer>(5, 2);
1418 }
1419
1420 #[test]
1421 #[cfg(feature = "with_v1")]
1422 fn check_signature_shares_v1() {
1423 check_signature_shares::<FrostCoordinator<v1::Aggregator>, v1::Signer>(
1424 5,
1425 1,
1426 SignatureType::Frost,
1427 vec![1],
1428 );
1429 check_signature_shares::<FrostCoordinator<v1::Aggregator>, v1::Signer>(
1430 5,
1431 1,
1432 SignatureType::Schnorr,
1433 vec![1],
1434 );
1435 check_signature_shares::<FrostCoordinator<v1::Aggregator>, v1::Signer>(
1436 5,
1437 1,
1438 SignatureType::Taproot(None),
1439 vec![1],
1440 );
1441 check_signature_shares::<FrostCoordinator<v1::Aggregator>, v1::Signer>(
1442 5,
1443 1,
1444 SignatureType::Taproot(Some([23u8; 32])),
1445 vec![1],
1446 );
1447 }
1448
1449 #[test]
1450 fn check_signature_shares_v2() {
1451 check_signature_shares::<FrostCoordinator<v2::Aggregator>, v2::Signer>(
1452 5,
1453 2,
1454 SignatureType::Frost,
1455 vec![0],
1456 );
1457 check_signature_shares::<FrostCoordinator<v2::Aggregator>, v2::Signer>(
1458 5,
1459 2,
1460 SignatureType::Schnorr,
1461 vec![0],
1462 );
1463 check_signature_shares::<FrostCoordinator<v2::Aggregator>, v2::Signer>(
1464 5,
1465 2,
1466 SignatureType::Taproot(None),
1467 vec![0],
1468 );
1469 check_signature_shares::<FrostCoordinator<v2::Aggregator>, v2::Signer>(
1470 5,
1471 2,
1472 SignatureType::Taproot(Some([23u8; 32])),
1473 vec![0],
1474 );
1475 }
1476
1477 #[test]
1478 #[cfg(feature = "with_v1")]
1479 fn bad_signature_share_request_v1() {
1480 bad_signature_share_request::<FrostCoordinator<v1::Aggregator>, v1::Signer>(5, 2);
1481 }
1482
1483 #[test]
1484 fn bad_signature_share_request_v2() {
1485 bad_signature_share_request::<FrostCoordinator<v2::Aggregator>, v2::Signer>(5, 2);
1486 }
1487
1488 #[test]
1489 #[cfg(feature = "with_v1")]
1490 fn invalid_nonce_v1() {
1491 invalid_nonce::<FrostCoordinator<v1::Aggregator>, v1::Signer>(5, 2);
1492 }
1493
1494 #[test]
1495 fn invalid_nonce_v2() {
1496 invalid_nonce::<FrostCoordinator<v2::Aggregator>, v2::Signer>(5, 2);
1497 }
1498
1499 #[test]
1500 fn process_inbound_messages_v2() {
1501 run_dkg_sign::<FrostCoordinator<v2::Aggregator>, v2::Signer>(5, 2);
1502 }
1503
1504 #[test]
1505 #[cfg(feature = "with_v1")]
1506 fn old_round_ids_are_ignored_v1() {
1507 old_round_ids_are_ignored::<v1::Aggregator>();
1508 }
1509
1510 #[test]
1511 fn old_round_ids_are_ignored_v2() {
1512 old_round_ids_are_ignored::<v2::Aggregator>();
1513 }
1514
1515 fn old_round_ids_are_ignored<Aggregator: AggregatorTrait>() {
1516 let mut rng = create_rng();
1517 let mut config = Config::new(10, 40, 28, Scalar::random(&mut rng));
1518 config.verify_packet_sigs = false;
1519 let mut coordinator = FrostCoordinator::<Aggregator>::new(config);
1520 let id: u64 = 10;
1521 let old_id = id;
1522 coordinator.current_dkg_id = id;
1523 coordinator.current_sign_id = id;
1524 let (packet, result) = coordinator
1526 .process(&Packet {
1527 sig: vec![],
1528 msg: Message::DkgBegin(DkgBegin { dkg_id: old_id }),
1529 })
1530 .unwrap();
1531 assert!(packet.is_none());
1532 assert!(result.is_none());
1533 assert_eq!(coordinator.state, State::Idle);
1534 assert_eq!(coordinator.current_dkg_id, id);
1535
1536 let (packet, result) = coordinator
1538 .process(&Packet {
1539 sig: vec![],
1540 msg: Message::DkgBegin(DkgBegin { dkg_id: id }),
1541 })
1542 .unwrap();
1543 assert!(packet.is_none());
1544 assert!(result.is_none());
1545 assert_eq!(coordinator.state, State::Idle);
1546 assert_eq!(coordinator.current_dkg_id, id);
1547
1548 let (packet, result) = coordinator
1550 .process(&Packet {
1551 sig: vec![],
1552 msg: Message::NonceRequest(NonceRequest {
1553 dkg_id: id,
1554 sign_id: old_id,
1555 message: vec![],
1556 sign_iter_id: id,
1557 signature_type: SignatureType::Frost,
1558 }),
1559 })
1560 .unwrap();
1561 assert!(packet.is_none());
1562 assert!(result.is_none());
1563 assert_eq!(coordinator.state, State::Idle);
1564 assert_eq!(coordinator.current_sign_id, id);
1565
1566 let (packet, result) = coordinator
1568 .process(&Packet {
1569 sig: vec![],
1570 msg: Message::NonceRequest(NonceRequest {
1571 dkg_id: id,
1572 sign_id: id,
1573 message: vec![],
1574 sign_iter_id: id,
1575 signature_type: SignatureType::Frost,
1576 }),
1577 })
1578 .unwrap();
1579 assert!(packet.is_none());
1580 assert!(result.is_none());
1581 assert_eq!(coordinator.state, State::Idle);
1582 assert_eq!(coordinator.current_sign_id, id);
1583 }
1584
1585 #[test]
1586 #[cfg(feature = "with_v1")]
1587 fn empty_public_shares_v1() {
1588 empty_public_shares::<FrostCoordinator<v1::Aggregator>, v1::Signer>(5, 2);
1589 }
1590
1591 #[test]
1592 fn empty_public_shares_v2() {
1593 empty_public_shares::<FrostCoordinator<v2::Aggregator>, v2::Signer>(5, 2);
1594 }
1595
1596 #[test]
1597 #[cfg(feature = "with_v1")]
1598 fn empty_private_shares_v1() {
1599 empty_private_shares::<FrostCoordinator<v1::Aggregator>, v1::Signer>(5, 2);
1600 }
1601
1602 #[test]
1603 fn empty_private_shares_v2() {
1604 empty_private_shares::<FrostCoordinator<v2::Aggregator>, v2::Signer>(5, 2);
1605 }
1606
1607 #[test]
1608 #[cfg(feature = "with_v1")]
1609 fn verify_packet_sigs_v1() {
1610 verify_packet_sigs::<FrostCoordinator<v1::Aggregator>, v1::Signer>();
1611 }
1612
1613 #[test]
1614 fn verify_packet_sigs_v2() {
1615 verify_packet_sigs::<FrostCoordinator<v2::Aggregator>, v2::Signer>();
1616 }
1617}