1use core::num::TryFromIntError;
2use hashbrown::{HashMap, HashSet};
3use rand_core::{CryptoRng, RngCore};
4use std::{
5 collections::{BTreeMap, BTreeSet},
6 fmt,
7};
8use tracing::{debug, error, info, trace, warn};
9
10use crate::{
11 common::{
12 check_public_shares, validate_key_id, validate_signer_id, PolyCommitment, PublicNonce,
13 TupleProof,
14 },
15 curve::{
16 ecdsa,
17 point::{Error as PointError, Point, G},
18 scalar::Scalar,
19 },
20 errors::{DkgError, EncryptionError},
21 net::{
22 BadPrivateShare, DkgBegin, DkgEnd, DkgEndBegin, DkgFailure, DkgPrivateBegin,
23 DkgPrivateShares, DkgPublicShares, DkgStatus, Message, NonceRequest, NonceResponse, Packet,
24 SignatureShareRequest, SignatureShareResponse, SignatureType,
25 },
26 state_machine::{PublicKeys, StateMachine},
27 traits::{Signer as SignerTrait, SignerState as SignerSavedState},
28 util::{decrypt, encrypt, make_shared_secret},
29};
30
31#[cfg(any(test, feature = "testing"))]
32use crate::net::Signable;
33
34#[derive(Debug, Clone, PartialEq)]
35pub enum State {
37 Idle,
39 DkgPublicDistribute,
41 DkgPublicGather,
43 DkgPrivateDistribute,
45 DkgPrivateGather,
47 SignGather,
49}
50
51#[derive(thiserror::Error, Clone, Debug)]
52pub enum ConfigError {
54 #[error("Insufficient keys for the number of signers")]
56 InsufficientKeys,
57 #[error("InvalidThreshold")]
59 InvalidThreshold,
60 #[error("Invalid signer ID {0}")]
62 InvalidSignerId(u32),
63 #[error("Invalid key ID {0}")]
65 InvalidKeyId(u32),
66}
67
68#[derive(thiserror::Error, Clone, Debug)]
69pub enum Error {
71 #[error("Config error {0}")]
73 Config(#[from] ConfigError),
74 #[error("InvalidPartyID")]
76 InvalidPartyID,
77 #[error("InvalidDkgPublicShares")]
79 InvalidDkgPublicShares,
80 #[error("InvalidDkgPrivateShares")]
82 InvalidDkgPrivateShares(Vec<u32>),
83 #[error("InvalidNonceResponse")]
85 InvalidNonceResponse,
86 #[error("InvalidSignatureShare")]
88 InvalidSignatureShare,
89 #[error("Bad State Change: {0}")]
91 BadStateChange(String),
92 #[error("Encryption error: {0}")]
94 Encryption(#[from] EncryptionError),
95 #[error("integer conversion error")]
96 TryFromInt(#[from] TryFromIntError),
98 #[error("Missing coordinator public key")]
99 MissingCoordinatorPublicKey,
101 #[error("A packet had an invalid signature")]
102 InvalidPacketSignature,
104 #[error("A curve point error {0}")]
105 Point(#[from] PointError),
107 #[error("missing kex public key for key_id {0}")]
108 MissingKexPublicKey(u32),
110}
111
112#[derive(Clone)]
114pub struct SavedState {
115 pub dkg_id: u64,
117 pub sign_id: u64,
119 pub sign_iter_id: u64,
121 pub threshold: u32,
123 pub dkg_threshold: u32,
125 pub total_signers: u32,
127 pub total_keys: u32,
129 pub signer: SignerSavedState,
131 pub signer_id: u32,
133 pub state: State,
135 pub commitments: HashMap<u32, PolyCommitment>,
138 decrypted_shares: HashMap<u32, HashMap<u32, Scalar>>,
141 decryption_keys: HashMap<u32, (u32, Point)>,
144 pub invalid_private_shares: HashMap<u32, BadPrivateShare>,
147 pub public_nonces: Vec<PublicNonce>,
149 network_private_key: Scalar,
151 pub public_keys: PublicKeys,
153 pub dkg_public_shares: BTreeMap<u32, DkgPublicShares>,
155 pub dkg_private_shares: BTreeMap<u32, DkgPrivateShares>,
157 pub dkg_private_begin_msg: Option<DkgPrivateBegin>,
159 pub dkg_end_begin_msg: Option<DkgEndBegin>,
161 pub verify_packet_sigs: bool,
163 pub coordinator_public_key: Option<ecdsa::PublicKey>,
165 kex_private_key: Scalar,
167 kex_public_keys: HashMap<u32, Point>,
169}
170
171impl fmt::Debug for SavedState {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 f.debug_struct("SavedState")
174 .field("dkg_id", &self.dkg_id)
175 .field("sign_id", &self.sign_id)
176 .field("sign_iter_id", &self.sign_iter_id)
177 .field("threshold", &self.threshold)
178 .field("dkg_threshold", &self.dkg_threshold)
179 .field("total_signers", &self.total_signers)
180 .field("total_keys", &self.total_keys)
181 .field("signer", &self.signer)
182 .field("signer_id", &self.signer_id)
183 .field("state", &self.state)
184 .field("commitments", &self.commitments)
185 .field("invalid_private_shares", &self.invalid_private_shares)
186 .field("public_nonces", &self.public_nonces)
187 .field("public_keys", &self.public_keys)
188 .field("dkg_public_shares", &self.dkg_public_shares)
189 .field("dkg_private_begin_msg", &self.dkg_private_begin_msg)
190 .field("dkg_end_begin_msg", &self.dkg_end_begin_msg)
191 .finish_non_exhaustive()
192 }
193}
194
195#[derive(Clone, PartialEq)]
197pub struct Signer<SignerType: SignerTrait> {
198 pub dkg_id: u64,
200 pub sign_id: u64,
202 pub sign_iter_id: u64,
204 pub threshold: u32,
206 pub dkg_threshold: u32,
208 pub total_signers: u32,
210 pub total_keys: u32,
212 pub signer: SignerType,
214 pub signer_id: u32,
216 pub state: State,
218 pub commitments: HashMap<u32, PolyCommitment>,
221 pub decrypted_shares: HashMap<u32, HashMap<u32, Scalar>>,
224 pub decryption_keys: HashMap<u32, (u32, Point)>,
227 pub invalid_private_shares: HashMap<u32, BadPrivateShare>,
230 pub public_nonces: Vec<PublicNonce>,
232 pub network_private_key: Scalar,
234 pub public_keys: PublicKeys,
236 pub dkg_public_shares: BTreeMap<u32, DkgPublicShares>,
238 pub dkg_private_shares: BTreeMap<u32, DkgPrivateShares>,
240 pub dkg_private_begin_msg: Option<DkgPrivateBegin>,
242 pub dkg_end_begin_msg: Option<DkgEndBegin>,
244 pub verify_packet_sigs: bool,
246 pub coordinator_public_key: Option<ecdsa::PublicKey>,
248 kex_private_key: Scalar,
250 kex_public_keys: HashMap<u32, Point>,
252}
253
254impl<SignerType: SignerTrait> fmt::Debug for Signer<SignerType> {
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 f.debug_struct("Signer")
257 .field("dkg_id", &self.dkg_id)
258 .field("sign_id", &self.sign_id)
259 .field("sign_iter_id", &self.sign_iter_id)
260 .field("threshold", &self.threshold)
261 .field("dkg_threshold", &self.dkg_threshold)
262 .field("total_signers", &self.total_signers)
263 .field("total_keys", &self.total_keys)
264 .field("signer", &self.signer)
265 .field("signer_id", &self.signer_id)
266 .field("state", &self.state)
267 .field("commitments", &self.commitments)
268 .field("invalid_private_shares", &self.invalid_private_shares)
269 .field("public_nonces", &self.public_nonces)
270 .field("public_keys", &self.public_keys)
271 .field("dkg_public_shares", &self.dkg_public_shares)
272 .field("dkg_private_begin_msg", &self.dkg_private_begin_msg)
273 .field("dkg_end_begin_msg", &self.dkg_end_begin_msg)
274 .finish_non_exhaustive()
275 }
276}
277
278impl<SignerType: SignerTrait> Signer<SignerType> {
279 #[allow(clippy::too_many_arguments)]
281 pub fn new<R: RngCore + CryptoRng>(
282 threshold: u32,
283 dkg_threshold: u32,
284 total_signers: u32,
285 total_keys: u32,
286 signer_id: u32,
287 key_ids: Vec<u32>,
288 network_private_key: Scalar,
289 public_keys: PublicKeys,
290 rng: &mut R,
291 ) -> Result<Self, Error> {
292 if total_signers > total_keys {
293 return Err(Error::Config(ConfigError::InsufficientKeys));
294 }
295
296 if threshold == 0 || threshold > total_keys {
297 return Err(Error::Config(ConfigError::InvalidThreshold));
298 }
299
300 if dkg_threshold == 0 || dkg_threshold < threshold {
301 return Err(Error::Config(ConfigError::InvalidThreshold));
302 }
303
304 if !validate_signer_id(signer_id, total_signers) {
305 return Err(Error::Config(ConfigError::InvalidSignerId(signer_id)));
306 }
307
308 for key_id in &key_ids {
309 if !validate_key_id(*key_id, total_keys) {
310 return Err(Error::Config(ConfigError::InvalidKeyId(*key_id)));
311 }
312 }
313
314 public_keys.validate(total_signers, total_keys)?;
315
316 let mut signer = SignerType::new(
317 signer_id,
318 &key_ids,
319 total_signers,
320 total_keys,
321 threshold,
322 rng,
323 );
324
325 signer.gen_nonces(&network_private_key, rng);
327
328 debug!("new Signer for signer_id {signer_id} with key_ids {key_ids:?}");
329 Ok(Self {
330 dkg_id: 0,
331 sign_id: 1,
332 sign_iter_id: 1,
333 threshold,
334 dkg_threshold,
335 total_signers,
336 total_keys,
337 signer,
338 signer_id,
339 state: State::Idle,
340 commitments: Default::default(),
341 decrypted_shares: Default::default(),
342 decryption_keys: Default::default(),
343 invalid_private_shares: Default::default(),
344 public_nonces: vec![],
345 network_private_key,
346 public_keys,
347 dkg_public_shares: Default::default(),
348 dkg_private_shares: Default::default(),
349 dkg_private_begin_msg: Default::default(),
350 dkg_end_begin_msg: Default::default(),
351 verify_packet_sigs: true,
352 coordinator_public_key: None,
353 kex_private_key: Scalar::random(rng),
354 kex_public_keys: Default::default(),
355 })
356 }
357
358 pub fn load(state: &SavedState) -> Self {
360 Self {
361 dkg_id: state.dkg_id,
362 sign_id: state.sign_id,
363 sign_iter_id: state.sign_iter_id,
364 threshold: state.threshold,
365 dkg_threshold: state.dkg_threshold,
366 total_signers: state.total_signers,
367 total_keys: state.total_keys,
368 signer: SignerType::load(&state.signer),
369 signer_id: state.signer_id,
370 state: state.state.clone(),
371 commitments: state.commitments.clone(),
372 decrypted_shares: state.decrypted_shares.clone(),
373 decryption_keys: state.decryption_keys.clone(),
374 invalid_private_shares: state.invalid_private_shares.clone(),
375 public_nonces: state.public_nonces.clone(),
376 network_private_key: state.network_private_key,
377 public_keys: state.public_keys.clone(),
378 dkg_public_shares: state.dkg_public_shares.clone(),
379 dkg_private_shares: state.dkg_private_shares.clone(),
380 dkg_private_begin_msg: state.dkg_private_begin_msg.clone(),
381 dkg_end_begin_msg: state.dkg_end_begin_msg.clone(),
382 verify_packet_sigs: state.verify_packet_sigs,
383 coordinator_public_key: state.coordinator_public_key,
384 kex_private_key: state.kex_private_key,
385 kex_public_keys: state.kex_public_keys.clone(),
386 }
387 }
388
389 pub fn save(&self) -> SavedState {
391 SavedState {
392 dkg_id: self.dkg_id,
393 sign_id: self.sign_id,
394 sign_iter_id: self.sign_iter_id,
395 threshold: self.threshold,
396 dkg_threshold: self.dkg_threshold,
397 total_signers: self.total_signers,
398 total_keys: self.total_keys,
399 signer: self.signer.save(),
400 signer_id: self.signer_id,
401 state: self.state.clone(),
402 commitments: self.commitments.clone(),
403 decrypted_shares: self.decrypted_shares.clone(),
404 decryption_keys: self.decryption_keys.clone(),
405 invalid_private_shares: self.invalid_private_shares.clone(),
406 public_nonces: self.public_nonces.clone(),
407 network_private_key: self.network_private_key,
408 public_keys: self.public_keys.clone(),
409 dkg_public_shares: self.dkg_public_shares.clone(),
410 dkg_private_shares: self.dkg_private_shares.clone(),
411 dkg_private_begin_msg: self.dkg_private_begin_msg.clone(),
412 dkg_end_begin_msg: self.dkg_end_begin_msg.clone(),
413 verify_packet_sigs: self.verify_packet_sigs,
414 coordinator_public_key: self.coordinator_public_key,
415 kex_private_key: self.kex_private_key,
416 kex_public_keys: self.kex_public_keys.clone(),
417 }
418 }
419
420 pub fn reset<T: RngCore + CryptoRng>(&mut self, dkg_id: u64, rng: &mut T) {
422 self.dkg_id = dkg_id;
423 self.commitments.clear();
424 self.decrypted_shares.clear();
425 self.decryption_keys.clear();
426 self.invalid_private_shares.clear();
427 self.public_nonces.clear();
428 self.signer.reset_polys(rng);
429 self.dkg_public_shares.clear();
430 self.dkg_private_shares.clear();
431 self.dkg_private_begin_msg = None;
432 self.dkg_end_begin_msg = None;
433 self.kex_private_key = Scalar::random(rng);
434 self.kex_public_keys.clear();
435 self.state = State::Idle;
436 }
437
438 #[cfg(any(test, feature = "testing"))]
440 pub fn process_inbound_messages<R: RngCore + CryptoRng>(
441 &mut self,
442 packets: &[Packet],
443 rng: &mut R,
444 ) -> Result<Vec<Packet>, Error> {
445 let mut responses = vec![];
446 for packet in packets {
447 let outbounds = self.process(packet, rng)?;
448 for out in outbounds {
449 let msg = Packet {
450 sig: out
451 .sign(&self.network_private_key)
452 .expect("Failed to sign message"),
453 msg: out,
454 };
455 responses.push(msg);
456 }
457 }
458 Ok(responses)
459 }
460
461 pub fn process<R: RngCore + CryptoRng>(
463 &mut self,
464 packet: &Packet,
465 rng: &mut R,
466 ) -> Result<Vec<Message>, Error> {
467 if self.verify_packet_sigs {
468 let Some(coordinator_public_key) = self.coordinator_public_key else {
469 return Err(Error::MissingCoordinatorPublicKey);
470 };
471 if !packet.verify(&self.public_keys, &coordinator_public_key) {
472 return Err(Error::InvalidPacketSignature);
473 }
474 }
475 let out_msgs = match &packet.msg {
476 Message::DkgBegin(dkg_begin) => self.dkg_begin(dkg_begin, rng),
477 Message::DkgPrivateBegin(dkg_private_begin) => {
478 self.dkg_private_begin(dkg_private_begin, rng)
479 }
480 Message::DkgEndBegin(dkg_end_begin) => self.dkg_end_begin(dkg_end_begin),
481 Message::DkgPublicShares(dkg_public_shares) => self.dkg_public_share(dkg_public_shares),
482 Message::DkgPrivateShares(dkg_private_shares) => {
483 self.dkg_private_shares(dkg_private_shares, rng)
484 }
485 Message::SignatureShareRequest(sign_share_request) => {
486 self.sign_share_request(sign_share_request, rng)
487 }
488 Message::NonceRequest(nonce_request) => self.nonce_request(nonce_request, rng),
489 Message::DkgEnd(_) | Message::NonceResponse(_) | Message::SignatureShareResponse(_) => {
490 Ok(vec![])
491 } };
493
494 match out_msgs {
495 Ok(mut out) => {
496 if self.can_dkg_end() {
497 let dkg_end_msgs = self.dkg_ended(rng)?;
498 out.push(dkg_end_msgs);
499 self.move_to(State::Idle)?;
500 }
501 Ok(out)
502 }
503 Err(e) => Err(e),
504 }
505 }
506
507 pub fn dkg_ended<R: RngCore + CryptoRng>(&mut self, rng: &mut R) -> Result<Message, Error> {
509 if !self.can_dkg_end() {
510 return Ok(Message::DkgEnd(DkgEnd {
511 dkg_id: self.dkg_id,
512 signer_id: self.signer_id,
513 status: DkgStatus::Failure(DkgFailure::BadState),
514 }));
515 }
516
517 let mut missing_public_shares = HashSet::new();
519 let mut missing_private_shares = HashSet::new();
520 let mut bad_public_shares = HashSet::new();
521 let threshold: usize = self.threshold.try_into().unwrap();
522
523 let Some(dkg_end_begin) = &self.dkg_end_begin_msg else {
524 return Ok(Message::DkgEnd(DkgEnd {
526 dkg_id: self.dkg_id,
527 signer_id: self.signer_id,
528 status: DkgStatus::Failure(DkgFailure::BadState),
529 }));
530 };
531
532 let signer_ids_set: HashSet<u32> = dkg_end_begin
534 .signer_ids
535 .iter()
536 .filter(|&&id| id < self.total_signers)
537 .copied()
538 .collect::<HashSet<u32>>();
539 let mut num_dkg_keys = 0u32;
540 for id in &signer_ids_set {
541 if let Some(key_ids) = self.public_keys.signer_key_ids.get(id) {
542 let len: u32 = key_ids.len().try_into()?;
543 num_dkg_keys = num_dkg_keys.saturating_add(len);
544 }
545 }
546
547 if num_dkg_keys < self.dkg_threshold {
548 return Ok(Message::DkgEnd(DkgEnd {
549 dkg_id: self.dkg_id,
550 signer_id: self.signer_id,
551 status: DkgStatus::Failure(DkgFailure::Threshold),
552 }));
553 }
554
555 for signer_id in &signer_ids_set {
556 if let Some(shares) = self.dkg_public_shares.get(signer_id) {
557 if shares.comms.is_empty() {
558 missing_public_shares.insert(*signer_id);
559 } else {
560 for (party_id, comm) in shares.comms.iter() {
561 if !check_public_shares(comm, threshold, &self.dkg_id.to_be_bytes()) {
562 bad_public_shares.insert(*signer_id);
563 } else {
564 self.commitments.insert(*party_id, comm.clone());
565 }
566 }
567 }
568 } else {
569 missing_public_shares.insert(*signer_id);
570 }
571 if let Some(shares) = self.dkg_private_shares.get(signer_id) {
572 if shares.shares.is_empty() {
574 missing_private_shares.insert(*signer_id);
575 } else {
576 for dst_key_id in self.signer.get_key_ids() {
577 for (_src_key_id, shares) in &shares.shares {
578 if shares.get(&dst_key_id).is_none() {
579 missing_private_shares.insert(*signer_id);
580 }
581 }
582 }
583 }
584 } else {
585 missing_private_shares.insert(*signer_id);
586 }
587 }
588
589 if !missing_public_shares.is_empty() {
590 return Ok(Message::DkgEnd(DkgEnd {
591 dkg_id: self.dkg_id,
592 signer_id: self.signer_id,
593 status: DkgStatus::Failure(DkgFailure::MissingPublicShares(missing_public_shares)),
594 }));
595 }
596
597 if !bad_public_shares.is_empty() {
598 return Ok(Message::DkgEnd(DkgEnd {
599 dkg_id: self.dkg_id,
600 signer_id: self.signer_id,
601 status: DkgStatus::Failure(DkgFailure::BadPublicShares(bad_public_shares)),
602 }));
603 }
604
605 if !missing_private_shares.is_empty() {
606 return Ok(Message::DkgEnd(DkgEnd {
607 dkg_id: self.dkg_id,
608 signer_id: self.signer_id,
609 status: DkgStatus::Failure(DkgFailure::MissingPrivateShares(
610 missing_private_shares,
611 )),
612 }));
613 }
614
615 let dkg_end = if self.invalid_private_shares.is_empty() {
616 match self.signer.compute_secrets(
617 &self.decrypted_shares,
618 &self.commitments,
619 &self.dkg_id.to_be_bytes(),
620 ) {
621 Ok(()) => DkgEnd {
622 dkg_id: self.dkg_id,
623 signer_id: self.signer_id,
624 status: DkgStatus::Success,
625 },
626 Err(dkg_error_map) => {
627 let mut bad_private_shares = HashMap::new();
629 for (_my_party_id, dkg_error) in dkg_error_map {
630 if let DkgError::BadPrivateShares(party_ids) = dkg_error {
631 for party_id in party_ids {
632 if let Some((party_signer_id, _shared_key)) =
633 &self.decryption_keys.get(&party_id)
634 {
635 bad_private_shares.insert(
636 *party_signer_id,
637 self.make_bad_private_share(*party_signer_id, rng)?,
638 );
639 } else {
640 warn!("DkgError::BadPrivateShares from party_id {party_id} but no (signer_id, shared_secret) cached");
641 }
642 }
643 } else {
644 warn!("Got unexpected dkg_error {dkg_error:?}");
645 }
646 }
647 DkgEnd {
648 dkg_id: self.dkg_id,
649 signer_id: self.signer_id,
650 status: DkgStatus::Failure(DkgFailure::BadPrivateShares(
651 bad_private_shares,
652 )),
653 }
654 }
655 }
656 } else {
657 DkgEnd {
658 dkg_id: self.dkg_id,
659 signer_id: self.signer_id,
660 status: DkgStatus::Failure(DkgFailure::BadPrivateShares(
661 self.invalid_private_shares.clone(),
662 )),
663 }
664 };
665
666 info!(
667 signer_id = %self.signer_id,
668 dkg_id = %self.dkg_id,
669 status = ?dkg_end.status,
670 "sending DkgEnd"
671 );
672
673 let dkg_end = Message::DkgEnd(dkg_end);
674 Ok(dkg_end)
675 }
676
677 pub fn public_shares_done(&self) -> bool {
679 debug!(
680 "public_shares_done state {:?} commitments {}",
681 self.state,
682 self.commitments.len(),
683 );
684 self.state == State::DkgPublicGather
685 && self.commitments.len() == usize::try_from(self.signer.get_num_parties()).unwrap()
686 }
687
688 pub fn can_dkg_end(&self) -> bool {
690 debug!(
691 "can_dkg_end: state {:?} DkgPrivateBegin {} DkgEndBegin {}",
692 self.state,
693 self.dkg_private_begin_msg.is_some(),
694 self.dkg_end_begin_msg.is_some(),
695 );
696
697 if self.state == State::DkgPrivateGather {
698 if let Some(dkg_private_begin) = &self.dkg_private_begin_msg {
699 for signer_id in &dkg_private_begin.signer_ids {
701 if !self.dkg_public_shares.contains_key(signer_id) {
702 debug!("can_dkg_end: false, missing public shares from signer {signer_id}");
703 return false;
704 }
705 }
706
707 if let Some(dkg_end_begin) = &self.dkg_end_begin_msg {
708 for signer_id in &dkg_end_begin.signer_ids {
710 if !self.dkg_private_shares.contains_key(signer_id) {
711 debug!("can_dkg_end: false, missing private shares from signer {signer_id}");
712 return false;
713 }
714 }
715 debug!("can_dkg_end: true");
716
717 return true;
718 }
719 }
720 } else {
721 debug!("can_dkg_end: false, bad state {:?}", self.state);
722 return false;
723 }
724 false
725 }
726
727 fn nonce_request<R: RngCore + CryptoRng>(
728 &mut self,
729 nonce_request: &NonceRequest,
730 rng: &mut R,
731 ) -> Result<Vec<Message>, Error> {
732 let mut msgs = vec![];
733 let signer_id = self.signer_id;
734 let key_ids = self.signer.get_key_ids();
735 let nonces = self.signer.gen_nonces(&self.network_private_key, rng);
736
737 let response = NonceResponse {
738 dkg_id: nonce_request.dkg_id,
739 sign_id: nonce_request.sign_id,
740 sign_iter_id: nonce_request.sign_iter_id,
741 signer_id,
742 key_ids,
743 nonces,
744 message: nonce_request.message.clone(),
745 };
746
747 let response = Message::NonceResponse(response);
748
749 info!(
750 %signer_id,
751 dkg_id = %nonce_request.dkg_id,
752 sign_id = %nonce_request.sign_id,
753 sign_iter_id = %nonce_request.sign_iter_id,
754 "sending NonceResponse"
755 );
756 msgs.push(response);
757
758 Ok(msgs)
759 }
760
761 fn sign_share_request<R: RngCore + CryptoRng>(
762 &mut self,
763 sign_request: &SignatureShareRequest,
764 rng: &mut R,
765 ) -> Result<Vec<Message>, Error> {
766 let signer_id_set = sign_request
767 .nonce_responses
768 .iter()
769 .map(|nr| nr.signer_id)
770 .collect::<BTreeSet<u32>>();
771
772 let is_invalid_request = sign_request.nonce_responses.len() != signer_id_set.len()
777 || signer_id_set.is_empty()
778 || signer_id_set.last() >= Some(&self.total_signers);
779
780 if is_invalid_request {
781 warn!("received an invalid SignatureShareRequest");
782 return Err(Error::InvalidNonceResponse);
783 }
784
785 let nonces = sign_request
786 .nonce_responses
787 .iter()
788 .flat_map(|nr| nr.nonces.clone())
789 .collect::<Vec<PublicNonce>>();
790
791 for nonce in &nonces {
792 if !nonce.is_valid() {
793 warn!(
794 signer_id = %self.signer_id,
795 "received an SignatureShareRequest with invalid nonce"
796 );
797 return Err(Error::InvalidNonceResponse);
798 }
799 }
800
801 debug!(signer_id = %self.signer_id, "received a valid SignatureShareRequest");
802
803 if signer_id_set.contains(&self.signer_id) {
804 let key_ids: Vec<u32> = sign_request
805 .nonce_responses
806 .iter()
807 .flat_map(|nr| nr.key_ids.iter().copied())
808 .collect::<Vec<u32>>();
809
810 let signer_ids = signer_id_set.into_iter().collect::<Vec<_>>();
811 let msg = &sign_request.message;
812 let signature_shares = match sign_request.signature_type {
813 SignatureType::Taproot(merkle_root) => {
814 self.signer
815 .sign_taproot(msg, &signer_ids, &key_ids, &nonces, merkle_root)
816 }
817 SignatureType::Schnorr => {
818 self.signer
819 .sign_schnorr(msg, &signer_ids, &key_ids, &nonces)
820 }
821 SignatureType::Frost => self.signer.sign(msg, &signer_ids, &key_ids, &nonces),
822 };
823
824 self.signer.gen_nonces(&self.network_private_key, rng);
825
826 let response = SignatureShareResponse {
827 dkg_id: sign_request.dkg_id,
828 sign_id: sign_request.sign_id,
829 sign_iter_id: sign_request.sign_iter_id,
830 signer_id: self.signer_id,
831 signature_shares,
832 };
833 info!(
834 signer_id = %self.signer_id,
835 dkg_id = %sign_request.dkg_id,
836 sign_id = %sign_request.sign_id,
837 sign_iter_id = %sign_request.sign_iter_id,
838 "sending SignatureShareResponse"
839 );
840
841 Ok(vec![Message::SignatureShareResponse(response)])
842 } else {
843 debug!(signer_id = %self.signer_id, "signer not included in SignatureShareRequest");
844 Ok(Vec::new())
845 }
846 }
847
848 fn dkg_begin<R: RngCore + CryptoRng>(
849 &mut self,
850 dkg_begin: &DkgBegin,
851 rng: &mut R,
852 ) -> Result<Vec<Message>, Error> {
853 self.reset(dkg_begin.dkg_id, rng);
854 self.move_to(State::DkgPublicDistribute)?;
855
856 self.dkg_public_begin(rng)
859 }
860
861 fn dkg_public_begin<R: RngCore + CryptoRng>(
862 &mut self,
863 rng: &mut R,
864 ) -> Result<Vec<Message>, Error> {
865 let mut msgs = vec![];
866 let comms = self
867 .signer
868 .get_poly_commitments(&self.dkg_id.to_be_bytes(), rng);
869 let comms = comms
870 .iter()
871 .map(|poly| (poly.id.id.get_u32(), poly.clone()))
872 .collect();
873
874 info!(
875 signer_id = %self.signer_id,
876 dkg_id = %self.dkg_id,
877 "sending DkgPublicShares"
878 );
879
880 let kex_proof = DkgPublicShares::kex_prove(
881 self.dkg_id,
882 self.signer_id,
883 &comms,
884 &self.kex_private_key,
885 rng,
886 );
887 let public_share = DkgPublicShares {
888 dkg_id: self.dkg_id,
889 signer_id: self.signer_id,
890 comms,
891 kex_public_key: self.kex_private_key * G,
892 kex_proof,
893 };
894
895 let public_share = Message::DkgPublicShares(public_share);
896 msgs.push(public_share);
897
898 self.move_to(State::DkgPublicGather)?;
899 Ok(msgs)
900 }
901
902 fn dkg_private_begin<R: RngCore + CryptoRng>(
903 &mut self,
904 dkg_private_begin: &DkgPrivateBegin,
905 rng: &mut R,
906 ) -> Result<Vec<Message>, Error> {
907 let mut msgs = vec![];
908 let mut private_shares = DkgPrivateShares {
909 dkg_id: self.dkg_id,
910 signer_id: self.signer_id,
911 shares: Vec::new(),
912 };
913 let mut active_key_ids = HashSet::new();
914 for signer_id in &dkg_private_begin.signer_ids {
915 if let Some(key_ids) = self.public_keys.signer_key_ids.get(signer_id) {
916 for key_id in key_ids {
917 active_key_ids.insert(*key_id);
918 }
919 }
920 }
921
922 self.dkg_private_begin_msg = Some(dkg_private_begin.clone());
923 self.move_to(State::DkgPrivateDistribute)?;
924
925 info!(
926 signer_id = %self.signer_id,
927 dkg_id = %self.dkg_id,
928 "sending DkgPrivateShares"
929 );
930
931 trace!(
932 "Signer {} shares {:?}",
933 self.signer_id,
934 &self.signer.get_shares()
935 );
936 for (party_id, shares) in &self.signer.get_shares() {
937 debug!(
938 "Signer {} addding dkg private share for party_id {party_id}",
939 self.signer_id
940 );
941 let mut encrypted_shares = HashMap::new();
943
944 for (dst_key_id, private_share) in shares {
945 if active_key_ids.contains(dst_key_id) {
946 debug!("encrypting dkg private share for key_id {dst_key_id}");
947 let Some(kex_public_key) = self.kex_public_keys.get(dst_key_id) else {
948 error!("No KEX public key for key_id {dst_key_id}");
949 return Err(Error::MissingKexPublicKey(*dst_key_id));
950 };
951 let shared_secret = make_shared_secret(&self.kex_private_key, kex_public_key);
952 let encrypted_share = encrypt(&shared_secret, &private_share.to_bytes(), rng)?;
953
954 encrypted_shares.insert(*dst_key_id, encrypted_share);
955 }
956 }
957
958 private_shares.shares.push((*party_id, encrypted_shares));
959 }
960
961 let private_shares = Message::DkgPrivateShares(private_shares);
962 msgs.push(private_shares);
963
964 self.move_to(State::DkgPrivateGather)?;
965 Ok(msgs)
966 }
967
968 pub fn dkg_end_begin(&mut self, dkg_end_begin: &DkgEndBegin) -> Result<Vec<Message>, Error> {
970 let msgs = vec![];
971
972 self.dkg_end_begin_msg = Some(dkg_end_begin.clone());
973
974 info!(
975 signer_id = %self.signer_id,
976 dkg_id = %self.dkg_id,
977 "received DkgEndBegin"
978 );
979
980 Ok(msgs)
981 }
982
983 pub fn dkg_public_share(
985 &mut self,
986 dkg_public_shares: &DkgPublicShares,
987 ) -> Result<Vec<Message>, Error> {
988 debug!(
989 "received DkgPublicShares from signer {} {}/{}",
990 dkg_public_shares.signer_id,
991 self.commitments.len(),
992 self.signer.get_num_parties(),
993 );
994
995 let signer_id = dkg_public_shares.signer_id;
996
997 let Some(_signer_public_key) = self.public_keys.signers.get(&signer_id) else {
999 warn!(%signer_id, "No public key configured");
1000 return Ok(vec![]);
1001 };
1002
1003 for (party_id, _) in &dkg_public_shares.comms {
1004 if !SignerType::validate_party_id(
1005 signer_id,
1006 *party_id,
1007 &self.public_keys.signer_key_ids,
1008 ) {
1009 warn!(%signer_id, %party_id, "signer sent polynomial commitment for wrong party");
1010 return Ok(vec![]);
1011 }
1012 }
1013
1014 let have_shares = self
1015 .dkg_public_shares
1016 .contains_key(&dkg_public_shares.signer_id);
1017
1018 if have_shares {
1019 info!(signer_id = %dkg_public_shares.signer_id, "received duplicate DkgPublicShares");
1020 return Ok(vec![]);
1021 }
1022
1023 let Some(signer_key_ids) = self.public_keys.signer_key_ids.get(&signer_id) else {
1024 warn!(%signer_id, "No key_ids configured");
1025 return Ok(vec![]);
1026 };
1027
1028 if !dkg_public_shares.kex_verify() {
1029 warn!(signer_id = %dkg_public_shares.signer_id, "received DkgPublicShares with invalid kex_proof");
1030 return Ok(vec![]);
1031 }
1032
1033 for key_id in signer_key_ids {
1034 self.kex_public_keys
1035 .insert(*key_id, dkg_public_shares.kex_public_key);
1036 }
1037
1038 self.dkg_public_shares
1039 .insert(dkg_public_shares.signer_id, dkg_public_shares.clone());
1040 Ok(vec![])
1041 }
1042
1043 pub fn dkg_private_shares<R: RngCore + CryptoRng>(
1045 &mut self,
1046 dkg_private_shares: &DkgPrivateShares,
1047 rng: &mut R,
1048 ) -> Result<Vec<Message>, Error> {
1049 let src_signer_id = dkg_private_shares.signer_id;
1051
1052 let Some(_signer_public_key) = self.public_keys.signers.get(&src_signer_id) else {
1054 warn!(%src_signer_id, "No public key configured");
1055 return Ok(vec![]);
1056 };
1057
1058 let Ok(kex_public_key) = self.get_kex_public_key(src_signer_id) else {
1059 return Ok(vec![]);
1060 };
1061
1062 for (party_id, _shares) in &dkg_private_shares.shares {
1063 if !SignerType::validate_party_id(
1064 src_signer_id,
1065 *party_id,
1066 &self.public_keys.signer_key_ids,
1067 ) {
1068 warn!("Signer {src_signer_id} sent a polynomial commitment for party {party_id}");
1069 return Ok(vec![]);
1070 }
1071 }
1072
1073 if self.dkg_private_shares.contains_key(&src_signer_id) {
1074 info!(signer_id = %dkg_private_shares.signer_id, "received duplicate DkgPrivateShares");
1075 return Ok(vec![]);
1076 }
1077
1078 self.dkg_private_shares
1079 .insert(src_signer_id, dkg_private_shares.clone());
1080
1081 let key_ids: HashSet<u32> = self.signer.get_key_ids().into_iter().collect();
1083
1084 let shared_key = self.kex_private_key * kex_public_key;
1085 let shared_secret = make_shared_secret(&self.kex_private_key, &kex_public_key);
1086
1087 for (src_id, shares) in &dkg_private_shares.shares {
1088 let mut decrypted_shares = HashMap::new();
1089 for (dst_key_id, bytes) in shares {
1090 if key_ids.contains(dst_key_id) {
1091 match decrypt(&shared_secret, bytes) {
1092 Ok(plain) => match Scalar::try_from(&plain[..]) {
1093 Ok(s) => {
1094 decrypted_shares.insert(*dst_key_id, s);
1095 }
1096 Err(e) => {
1097 warn!("Failed to parse Scalar for dkg private share from src_id {src_id} to dst_id {dst_key_id}: {e:?}");
1098 self.invalid_private_shares.insert(
1099 src_signer_id,
1100 self.make_bad_private_share(src_signer_id, rng)?,
1101 );
1102 }
1103 },
1104 Err(e) => {
1105 warn!("Failed to decrypt dkg private share from src_id {src_id} to dst_id {dst_key_id}: {e:?}");
1106 self.invalid_private_shares.insert(
1107 src_signer_id,
1108 self.make_bad_private_share(src_signer_id, rng)?,
1109 );
1110 }
1111 }
1112 }
1113 }
1114 self.decrypted_shares.insert(*src_id, decrypted_shares);
1115 self.decryption_keys
1116 .insert(*src_id, (dkg_private_shares.signer_id, shared_key));
1117 }
1118 debug!(
1119 "received DkgPrivateShares from signer {} {}/{}",
1120 dkg_private_shares.signer_id,
1121 self.decrypted_shares.len(),
1122 self.signer.get_num_parties(),
1123 );
1124 Ok(vec![])
1125 }
1126
1127 fn get_kex_public_key(&self, signer_id: u32) -> Result<Point, Error> {
1128 let Some(signer_key_ids) = self.public_keys.signer_key_ids.get(&signer_id) else {
1129 warn!(%signer_id, "No key_ids configured");
1130 return Err(Error::Config(ConfigError::InvalidSignerId(signer_id)));
1131 };
1132
1133 let Some(signer_key_id) = signer_key_ids.iter().next() else {
1134 warn!(%signer_id, "No key_ids configured");
1135 return Err(Error::Config(ConfigError::InvalidSignerId(signer_id)));
1136 };
1137
1138 let Some(kex_public_key) = self.kex_public_keys.get(signer_key_id) else {
1139 warn!(%signer_id, %signer_key_id, "No KEX public key configured");
1140 return Err(Error::MissingKexPublicKey(*signer_key_id));
1141 };
1142
1143 Ok(*kex_public_key)
1144 }
1145
1146 #[allow(non_snake_case)]
1147 fn make_bad_private_share<R: RngCore + CryptoRng>(
1148 &self,
1149 signer_id: u32,
1150 rng: &mut R,
1151 ) -> Result<BadPrivateShare, Error> {
1152 let a = self.kex_private_key;
1153 let A = a * G;
1154 let B = self.get_kex_public_key(signer_id)?;
1155 let K = a * B;
1156 let tuple_proof = TupleProof::new(&a, &A, &B, &K, rng);
1157
1158 Ok(BadPrivateShare {
1159 shared_key: K,
1160 tuple_proof,
1161 })
1162 }
1163}
1164
1165impl<SignerType: SignerTrait> StateMachine<State, Error> for Signer<SignerType> {
1166 fn move_to(&mut self, state: State) -> Result<(), Error> {
1167 self.can_move_to(&state)?;
1168 self.state = state;
1169 Ok(())
1170 }
1171
1172 fn can_move_to(&self, state: &State) -> Result<(), Error> {
1173 let prev_state = &self.state;
1174 let accepted = match state {
1175 State::Idle => true,
1176 State::DkgPublicDistribute => {
1177 prev_state == &State::Idle
1178 || prev_state == &State::DkgPublicGather
1179 || prev_state == &State::DkgPrivateDistribute
1180 }
1181 State::DkgPublicGather => prev_state == &State::DkgPublicDistribute,
1182 State::DkgPrivateDistribute => prev_state == &State::DkgPublicGather,
1183 State::DkgPrivateGather => prev_state == &State::DkgPrivateDistribute,
1184 State::SignGather => prev_state == &State::Idle,
1185 };
1186 if accepted {
1187 debug!("state change from {prev_state:?} to {state:?}");
1188 Ok(())
1189 } else {
1190 Err(Error::BadStateChange(format!(
1191 "{prev_state:?} to {state:?}"
1192 )))
1193 }
1194 }
1195}
1196#[cfg(test)]
1197pub mod test {
1199 use super::*;
1200 #[cfg(feature = "with_v1")]
1201 use crate::v1;
1202 use crate::{
1203 common::PolyCommitment,
1204 curve::{ecdsa, scalar::Scalar},
1205 net::{DkgBegin, DkgEndBegin, DkgPrivateBegin, DkgPublicShares, DkgStatus, Message},
1206 schnorr::ID,
1207 state_machine::{
1208 signer::{ConfigError, Error, Signer, State as SignerState},
1209 PublicKeys,
1210 },
1211 traits::Signer as SignerTrait,
1212 util::create_rng,
1213 v2,
1214 };
1215
1216 use hashbrown::HashSet;
1217
1218 #[test]
1219 #[cfg(feature = "with_v1")]
1220 fn bad_config_v1() {
1221 bad_config::<v1::Signer>();
1222 }
1223
1224 #[test]
1225 #[cfg(feature = "with_v1")]
1226 fn bad_config_v2() {
1227 bad_config::<v1::Signer>();
1228 }
1229
1230 #[allow(dead_code)]
1231 fn bad_config<SignerType: SignerTrait>() {
1232 let mut rng = create_rng();
1233
1234 assert!(matches!(
1236 Signer::<SignerType>::new(
1237 1,
1238 1,
1239 2,
1240 1,
1241 0,
1242 vec![1],
1243 Default::default(),
1244 Default::default(),
1245 &mut rng,
1246 ),
1247 Err(Error::Config(ConfigError::InsufficientKeys))
1248 ));
1249
1250 assert!(matches!(
1252 Signer::<SignerType>::new(
1253 0,
1254 1,
1255 4,
1256 4,
1257 0,
1258 vec![1],
1259 Default::default(),
1260 Default::default(),
1261 &mut rng,
1262 ),
1263 Err(Error::Config(ConfigError::InvalidThreshold))
1264 ));
1265
1266 assert!(matches!(
1268 Signer::<SignerType>::new(
1269 1,
1270 0,
1271 4,
1272 4,
1273 0,
1274 vec![1],
1275 Default::default(),
1276 Default::default(),
1277 &mut rng,
1278 ),
1279 Err(Error::Config(ConfigError::InvalidThreshold))
1280 ));
1281
1282 assert!(matches!(
1284 Signer::<SignerType>::new(
1285 5,
1286 5,
1287 4,
1288 4,
1289 0,
1290 vec![1],
1291 Default::default(),
1292 Default::default(),
1293 &mut rng,
1294 ),
1295 Err(Error::Config(ConfigError::InvalidThreshold))
1296 ));
1297
1298 assert!(matches!(
1300 Signer::<SignerType>::new(
1301 2,
1302 1,
1303 4,
1304 4,
1305 0,
1306 vec![1],
1307 Default::default(),
1308 Default::default(),
1309 &mut rng,
1310 ),
1311 Err(Error::Config(ConfigError::InvalidThreshold))
1312 ));
1313
1314 assert!(matches!(
1316 Signer::<SignerType>::new(
1317 2,
1318 2,
1319 4,
1320 4,
1321 4,
1322 vec![1],
1323 Default::default(),
1324 Default::default(),
1325 &mut rng,
1326 ),
1327 Err(Error::Config(ConfigError::InvalidSignerId(4)))
1328 ));
1329
1330 assert!(matches!(
1332 Signer::<SignerType>::new(
1333 2,
1334 2,
1335 4,
1336 4,
1337 0,
1338 vec![0],
1339 Default::default(),
1340 Default::default(),
1341 &mut rng,
1342 ),
1343 Err(Error::Config(ConfigError::InvalidKeyId(0)))
1344 ));
1345
1346 assert!(matches!(
1348 Signer::<SignerType>::new(
1349 2,
1350 2,
1351 4,
1352 4,
1353 0,
1354 vec![5],
1355 Default::default(),
1356 Default::default(),
1357 &mut rng,
1358 ),
1359 Err(Error::Config(ConfigError::InvalidKeyId(5)))
1360 ));
1361
1362 }
1364
1365 #[test]
1366 #[cfg(feature = "with_v1")]
1367 fn dkg_public_share_v1() {
1368 dkg_public_share::<v1::Signer>();
1369 }
1370
1371 #[test]
1372 fn dkg_public_share_v2() {
1373 dkg_public_share::<v2::Signer>();
1374 }
1375
1376 fn dkg_public_share<SignerType: SignerTrait>() {
1377 let ctx = 0u64.to_be_bytes();
1378 let mut rng = create_rng();
1379 let private_key = Scalar::random(&mut rng);
1380 let public_key = ecdsa::PublicKey::new(&private_key).unwrap();
1381 let mut public_keys: PublicKeys = Default::default();
1382 let mut key_ids = HashSet::new();
1383
1384 public_keys.signers.insert(0, public_key);
1385 public_keys.key_ids.insert(1, public_key);
1386
1387 key_ids.insert(1);
1388 public_keys.signer_key_ids.insert(0, key_ids);
1389
1390 let mut signer =
1391 Signer::<SignerType>::new(1, 1, 1, 1, 0, vec![1], private_key, public_keys, &mut rng)
1392 .unwrap();
1393 let comms: Vec<(u32, PolyCommitment)> = signer
1394 .signer
1395 .get_poly_commitments(&ctx, &mut rng)
1396 .iter()
1397 .map(|comm| (comm.id.id.get_u32(), comm.clone()))
1398 .collect();
1399 let kex_private_key = Scalar::random(&mut rng);
1400 let kex_proof = DkgPublicShares::kex_prove(0, 0, &comms, &kex_private_key, &mut rng);
1401 let public_share = DkgPublicShares {
1402 dkg_id: 0,
1403 signer_id: 0,
1404 comms: comms.clone(),
1405 kex_public_key: Point::from(kex_private_key),
1406 kex_proof: kex_proof.clone(),
1407 };
1408 signer.dkg_public_share(&public_share).unwrap();
1409 assert_eq!(1, signer.dkg_public_shares.len());
1410
1411 let dup_public_share = DkgPublicShares {
1413 dkg_id: 0,
1414 signer_id: 0,
1415 comms: comms.clone(),
1416 kex_public_key: Point::from(kex_private_key),
1417 kex_proof: kex_proof.clone(),
1418 };
1419 signer.dkg_public_share(&dup_public_share).unwrap();
1420 assert_eq!(1, signer.dkg_public_shares.len());
1421 assert_eq!(
1422 public_share,
1423 signer.dkg_public_shares.iter().next().unwrap().1.clone()
1424 );
1425 }
1426
1427 #[test]
1428 #[cfg(feature = "with_v1")]
1429 fn public_shares_done_v1() {
1430 public_shares_done::<v1::Signer>();
1431 }
1432
1433 #[test]
1434 fn public_shares_done_v2() {
1435 public_shares_done::<v2::Signer>();
1436 }
1437
1438 fn public_shares_done<SignerType: SignerTrait>() {
1439 let ctx = 0u64.to_be_bytes();
1440 let mut rng = create_rng();
1441 let mut signer = Signer::<SignerType>::new(
1442 1,
1443 1,
1444 1,
1445 1,
1446 0,
1447 vec![1],
1448 Default::default(),
1449 Default::default(),
1450 &mut rng,
1451 )
1452 .unwrap();
1453 assert!(!signer.public_shares_done());
1455
1456 signer.state = SignerState::DkgPublicGather;
1458 signer.commitments.insert(
1459 1,
1460 PolyCommitment {
1461 id: ID::new(&Scalar::new(), &Scalar::new(), &ctx, &mut rng),
1462 poly: vec![],
1463 },
1464 );
1465
1466 assert!(signer.public_shares_done());
1468 }
1469
1470 #[test]
1471 #[cfg(feature = "with_v1")]
1472 fn dkg_private_share_v1() {
1474 let mut rng = create_rng();
1475
1476 let private_key = Scalar::random(&mut rng);
1477 let public_key = ecdsa::PublicKey::new(&private_key).unwrap();
1478 let private_key2 = Scalar::random(&mut rng);
1479 let public_key2 = ecdsa::PublicKey::new(&private_key2).unwrap();
1480 let mut public_keys: PublicKeys = Default::default();
1481 let kex_private_key = Scalar::random(&mut rng);
1482 let kex_public_key = Point::from(&kex_private_key);
1483
1484 public_keys.signers.insert(0, public_key);
1485 public_keys.signers.insert(1, public_key2);
1486 public_keys.key_ids.insert(1, public_key);
1487 public_keys.key_ids.insert(2, public_key2);
1488
1489 let mut key_ids = HashSet::new();
1490 key_ids.insert(1);
1491 public_keys.signer_key_ids.insert(0, key_ids);
1492
1493 let mut key_ids2 = HashSet::new();
1494 key_ids2.insert(2);
1495 public_keys.signer_key_ids.insert(1, key_ids2);
1496
1497 let mut signer =
1498 Signer::<v1::Signer>::new(1, 1, 2, 2, 0, vec![1], private_key, public_keys, &mut rng)
1499 .unwrap();
1500
1501 let kex_proof = DkgPublicShares::kex_prove(0, 1, &vec![], &kex_private_key, &mut rng);
1502 let public_share = DkgPublicShares {
1503 dkg_id: 0,
1504 signer_id: 1,
1505 comms: vec![],
1506 kex_public_key,
1507 kex_proof: kex_proof.clone(),
1508 };
1509 signer.dkg_public_share(&public_share).unwrap();
1510 assert_eq!(1, signer.dkg_public_shares.len());
1511
1512 let private_share = DkgPrivateShares {
1513 dkg_id: 0,
1514 signer_id: 1,
1515 shares: vec![(2, HashMap::new())],
1516 };
1517 signer.dkg_private_shares(&private_share, &mut rng).unwrap();
1518 assert_eq!(1, signer.dkg_private_shares.len());
1519
1520 let dup_private_share = DkgPrivateShares {
1522 dkg_id: 0,
1523 signer_id: 1,
1524 shares: vec![(2, HashMap::new())],
1525 };
1526 signer
1527 .dkg_private_shares(&dup_private_share, &mut rng)
1528 .unwrap();
1529 assert_eq!(1, signer.dkg_private_shares.len());
1530 assert_eq!(
1531 private_share,
1532 signer.dkg_private_shares.iter().next().unwrap().1.clone()
1533 );
1534 }
1535
1536 #[test]
1537 fn dkg_private_share_v2() {
1539 let mut rng = create_rng();
1540
1541 let private_key = Scalar::random(&mut rng);
1542 let public_key = ecdsa::PublicKey::new(&private_key).unwrap();
1543 let private_key2 = Scalar::random(&mut rng);
1544 let public_key2 = ecdsa::PublicKey::new(&private_key2).unwrap();
1545 let mut public_keys: PublicKeys = Default::default();
1546 let kex_private_key = Scalar::random(&mut rng);
1547 let kex_public_key = Point::from(&kex_private_key);
1548
1549 public_keys.signers.insert(0, public_key);
1550 public_keys.signers.insert(1, public_key2);
1551 public_keys.key_ids.insert(1, public_key);
1552 public_keys.key_ids.insert(2, public_key2);
1553
1554 let mut key_ids = HashSet::new();
1555 key_ids.insert(1);
1556 public_keys.signer_key_ids.insert(0, key_ids);
1557
1558 let mut key_ids2 = HashSet::new();
1559 key_ids2.insert(2);
1560 public_keys.signer_key_ids.insert(1, key_ids2);
1561
1562 let mut signer =
1563 Signer::<v2::Signer>::new(1, 1, 2, 2, 0, vec![1], private_key, public_keys, &mut rng)
1564 .unwrap();
1565
1566 let kex_proof = DkgPublicShares::kex_prove(0, 1, &vec![], &kex_private_key, &mut rng);
1567 let public_share = DkgPublicShares {
1568 dkg_id: 0,
1569 signer_id: 1,
1570 comms: vec![],
1571 kex_public_key,
1572 kex_proof: kex_proof.clone(),
1573 };
1574 signer.dkg_public_share(&public_share).unwrap();
1575 assert_eq!(1, signer.dkg_public_shares.len());
1576
1577 let private_share = DkgPrivateShares {
1578 dkg_id: 0,
1579 signer_id: 1,
1580 shares: vec![(1, HashMap::new())],
1581 };
1582 signer.dkg_private_shares(&private_share, &mut rng).unwrap();
1583 assert_eq!(1, signer.dkg_private_shares.len());
1584
1585 let dup_private_share = DkgPrivateShares {
1587 dkg_id: 0,
1588 signer_id: 1,
1589 shares: vec![(1, HashMap::new())],
1590 };
1591 signer
1592 .dkg_private_shares(&dup_private_share, &mut rng)
1593 .unwrap();
1594 assert_eq!(1, signer.dkg_private_shares.len());
1595 assert_eq!(
1596 private_share,
1597 signer.dkg_private_shares.iter().next().unwrap().1.clone()
1598 );
1599 }
1600
1601 #[test]
1602 #[cfg(feature = "with_v1")]
1603 fn can_dkg_end_v1() {
1604 can_dkg_end::<v1::Signer>();
1605 }
1606
1607 #[test]
1608 fn can_dkg_end_v2() {
1609 can_dkg_end::<v2::Signer>();
1610 }
1611
1612 fn can_dkg_end<SignerType: SignerTrait>() {
1613 let mut rng = create_rng();
1614 let private_key = Scalar::random(&mut rng);
1615 let public_key = ecdsa::PublicKey::new(&private_key).unwrap();
1616 let mut public_keys: PublicKeys = Default::default();
1617 let mut key_ids = HashSet::new();
1618
1619 public_keys.signers.insert(0, public_key);
1620 public_keys.key_ids.insert(1, public_key);
1621
1622 key_ids.insert(1);
1623 public_keys.signer_key_ids.insert(0, key_ids);
1624
1625 let mut signer =
1626 Signer::<SignerType>::new(1, 1, 1, 1, 0, vec![1], private_key, public_keys, &mut rng)
1627 .unwrap();
1628 signer.verify_packet_sigs = false;
1629 assert!(!signer.can_dkg_end());
1631
1632 let dkg_begin = Message::DkgBegin(DkgBegin { dkg_id: 1 });
1634 let dkg_begin_packet = Packet {
1635 msg: dkg_begin,
1636 sig: vec![],
1637 };
1638 let dkg_public_shares = signer
1639 .process(&dkg_begin_packet, &mut rng)
1640 .expect("failed to process DkgBegin");
1641 let dkg_public_shares_packet = Packet {
1642 msg: dkg_public_shares[0].clone(),
1643 sig: vec![],
1644 };
1645 let _ = signer
1646 .process(&dkg_public_shares_packet, &mut rng)
1647 .expect("failed to process DkgPublicShares");
1648 let dkg_private_begin = Message::DkgPrivateBegin(DkgPrivateBegin {
1649 dkg_id: 1,
1650 signer_ids: vec![0],
1651 key_ids: vec![],
1652 });
1653 let dkg_private_begin_packet = Packet {
1654 msg: dkg_private_begin,
1655 sig: vec![],
1656 };
1657 let dkg_private_shares = signer
1658 .process(&dkg_private_begin_packet, &mut rng)
1659 .expect("failed to process DkgBegin");
1660 let dkg_private_shares_packet = Packet {
1661 msg: dkg_private_shares[0].clone(),
1662 sig: vec![],
1663 };
1664 let _ = signer
1665 .process(&dkg_private_shares_packet, &mut rng)
1666 .expect("failed to process DkgPrivateShares");
1667 let dkg_end_begin = DkgEndBegin {
1668 dkg_id: 1,
1669 signer_ids: vec![0],
1670 key_ids: vec![],
1671 };
1672 let _ = signer
1673 .dkg_end_begin(&dkg_end_begin)
1674 .expect("failed to process DkgPrivateShares");
1675
1676 assert!(signer.can_dkg_end());
1678 }
1679
1680 #[test]
1681 #[cfg(feature = "with_v1")]
1682 fn dkg_ended_v1() {
1683 dkg_ended::<v1::Signer>();
1684 }
1685
1686 #[test]
1687 fn dkg_ended_v2() {
1688 dkg_ended::<v2::Signer>();
1689 }
1690 fn dkg_ended<SignerType: SignerTrait>() {
1693 let mut rng = create_rng();
1698 let mut signer = Signer::<SignerType>::new(
1699 1,
1700 1,
1701 1,
1702 1,
1703 0,
1704 vec![1],
1705 Default::default(),
1706 Default::default(),
1707 &mut rng,
1708 )
1709 .unwrap();
1710
1711 let Ok(Message::DkgEnd(dkg_end)) = signer.dkg_ended(&mut rng) else {
1712 panic!("Unexpected Error");
1713 };
1714 assert!(
1715 matches!(dkg_end.status, DkgStatus::Failure(_)),
1716 "Expected DkgStatus::Failure"
1717 );
1718 }
1719}