wsts/state_machine/signer/
mod.rs

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)]
35/// Signer states
36pub enum State {
37    /// The signer is idle
38    Idle,
39    /// The signer is distributing DKG public shares
40    DkgPublicDistribute,
41    /// The signer is gathering DKG public shares
42    DkgPublicGather,
43    /// The signer is distributing DKG private shares
44    DkgPrivateDistribute,
45    /// The signer is gathering DKG private shares
46    DkgPrivateGather,
47    /// The signer is distributing signature shares
48    SignGather,
49}
50
51#[derive(thiserror::Error, Clone, Debug)]
52/// Config errors for a signer
53pub enum ConfigError {
54    /// Insufficient keys for the number of signers
55    #[error("Insufficient keys for the number of signers")]
56    InsufficientKeys,
57    /// The threshold was invalid
58    #[error("InvalidThreshold")]
59    InvalidThreshold,
60    /// The signer ID was invalid
61    #[error("Invalid signer ID {0}")]
62    InvalidSignerId(u32),
63    /// The key ID was invalid
64    #[error("Invalid key ID {0}")]
65    InvalidKeyId(u32),
66}
67
68#[derive(thiserror::Error, Clone, Debug)]
69/// The error type for a signer
70pub enum Error {
71    /// Config error
72    #[error("Config error {0}")]
73    Config(#[from] ConfigError),
74    /// The party ID was invalid
75    #[error("InvalidPartyID")]
76    InvalidPartyID,
77    /// A DKG public share was invalid
78    #[error("InvalidDkgPublicShares")]
79    InvalidDkgPublicShares,
80    /// A DKG private share was invalid
81    #[error("InvalidDkgPrivateShares")]
82    InvalidDkgPrivateShares(Vec<u32>),
83    /// A nonce response was invalid
84    #[error("InvalidNonceResponse")]
85    InvalidNonceResponse,
86    /// A signature share was invalid
87    #[error("InvalidSignatureShare")]
88    InvalidSignatureShare,
89    /// A bad state change was made
90    #[error("Bad State Change: {0}")]
91    BadStateChange(String),
92    /// An encryption error occurred
93    #[error("Encryption error: {0}")]
94    Encryption(#[from] EncryptionError),
95    #[error("integer conversion error")]
96    /// An error during integer conversion operations
97    TryFromInt(#[from] TryFromIntError),
98    #[error("Missing coordinator public key")]
99    /// Missing coordinator public key
100    MissingCoordinatorPublicKey,
101    #[error("A packet had an invalid signature")]
102    /// A packet had an invalid signature
103    InvalidPacketSignature,
104    #[error("A curve point error {0}")]
105    /// A curve point error
106    Point(#[from] PointError),
107    #[error("missing kex public key for key_id {0}")]
108    /// Missing KEX public key for a key_id
109    MissingKexPublicKey(u32),
110}
111
112/// The saved state required to reconstruct a signer
113#[derive(Clone)]
114pub struct SavedState {
115    /// current DKG round ID
116    pub dkg_id: u64,
117    /// current signing round ID
118    pub sign_id: u64,
119    /// current signing iteration ID
120    pub sign_iter_id: u64,
121    /// the threshold of the keys needed for a valid signature
122    pub threshold: u32,
123    /// the threshold of the keys needed for a valid DKG
124    pub dkg_threshold: u32,
125    /// the total number of signers
126    pub total_signers: u32,
127    /// the total number of keys
128    pub total_keys: u32,
129    /// the Signer object
130    pub signer: SignerSavedState,
131    /// the Signer ID
132    pub signer_id: u32,
133    /// the current state
134    pub state: State,
135    /// map of polynomial commitments for each party
136    /// party_id => PolyCommitment
137    pub commitments: HashMap<u32, PolyCommitment>,
138    /// map of decrypted DKG private shares
139    /// src_party_id => (dst_key_id => private_share)
140    decrypted_shares: HashMap<u32, HashMap<u32, Scalar>>,
141    /// shared secrets used to decrypt private shares
142    /// src_party_id => (signer_id, dh shared key)
143    decryption_keys: HashMap<u32, (u32, Point)>,
144    /// invalid private shares
145    /// signer_id => {shared_key, tuple_proof}
146    pub invalid_private_shares: HashMap<u32, BadPrivateShare>,
147    /// public nonces for this signing round
148    pub public_nonces: Vec<PublicNonce>,
149    /// the private key used to sign messages sent over the network
150    network_private_key: Scalar,
151    /// the public keys for all signers and coordinator
152    pub public_keys: PublicKeys,
153    /// the DKG public shares received in this round
154    pub dkg_public_shares: BTreeMap<u32, DkgPublicShares>,
155    /// the DKG private shares received in this round
156    pub dkg_private_shares: BTreeMap<u32, DkgPrivateShares>,
157    /// the DKG private begin message received in this round
158    pub dkg_private_begin_msg: Option<DkgPrivateBegin>,
159    /// the DKG end begin message received in this round
160    pub dkg_end_begin_msg: Option<DkgEndBegin>,
161    /// whether to verify the signature on Packets
162    pub verify_packet_sigs: bool,
163    /// coordinator public key
164    pub coordinator_public_key: Option<ecdsa::PublicKey>,
165    /// Ephemeral private key for key exchange
166    kex_private_key: Scalar,
167    /// Ephemeral public keys for key exchange indexed by key_id
168    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/// A state machine for a signing round
196#[derive(Clone, PartialEq)]
197pub struct Signer<SignerType: SignerTrait> {
198    /// current DKG round ID
199    pub dkg_id: u64,
200    /// current signing round ID
201    pub sign_id: u64,
202    /// current signing iteration ID
203    pub sign_iter_id: u64,
204    /// the threshold of the keys needed for a valid signature
205    pub threshold: u32,
206    /// the threshold of the keys needed for a valid DKG
207    pub dkg_threshold: u32,
208    /// the total number of signers
209    pub total_signers: u32,
210    /// the total number of keys
211    pub total_keys: u32,
212    /// the Signer object
213    pub signer: SignerType,
214    /// the Signer ID
215    pub signer_id: u32,
216    /// the current state
217    pub state: State,
218    /// map of polynomial commitments for each party
219    /// party_id => PolyCommitment
220    pub commitments: HashMap<u32, PolyCommitment>,
221    /// map of decrypted DKG private shares
222    /// src_party_id => (dst_key_id => private_share)
223    pub decrypted_shares: HashMap<u32, HashMap<u32, Scalar>>,
224    /// shared secrets used to decrypt private shares
225    /// src_party_id => (signer_id, dh shared key)
226    pub decryption_keys: HashMap<u32, (u32, Point)>,
227    /// invalid private shares
228    /// signer_id => {shared_key, tuple_proof}
229    pub invalid_private_shares: HashMap<u32, BadPrivateShare>,
230    /// public nonces for this signing round
231    pub public_nonces: Vec<PublicNonce>,
232    /// the private key used to sign messages sent over the network
233    pub network_private_key: Scalar,
234    /// the public keys for all signers and coordinator
235    pub public_keys: PublicKeys,
236    /// the DKG public shares received in this round
237    pub dkg_public_shares: BTreeMap<u32, DkgPublicShares>,
238    /// the DKG private shares received in this round
239    pub dkg_private_shares: BTreeMap<u32, DkgPrivateShares>,
240    /// the DKG private begin message received in this round
241    pub dkg_private_begin_msg: Option<DkgPrivateBegin>,
242    /// the DKG end begin message received in this round
243    pub dkg_end_begin_msg: Option<DkgEndBegin>,
244    /// whether to verify the signature on Packets
245    pub verify_packet_sigs: bool,
246    /// coordinator public key
247    pub coordinator_public_key: Option<ecdsa::PublicKey>,
248    /// Ephemeral private key for key exchange
249    kex_private_key: Scalar,
250    /// Ephemeral public keys for key exchange indexed by key_id
251    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    /// create a Signer
280    #[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        // immediately generate nonces with good entropy to avoid protocol attacks
326        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    /// Load a coordinator from the previously saved `state`
359    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    /// Save the state required to reconstruct the coordinator
390    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    /// Reset internal state
421    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    /// Process the slice of packets
439    #[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    /// process the passed incoming message, and return any outgoing messages needed in response
462    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            } // TODO
492        };
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    /// DKG is done so compute secrets
508    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        // only use the public shares from the DkgEndBegin signers
518        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            // no cached DkgEndBegin message
525            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        // fist check to see if dkg_threshold has been met
533        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                // signer_id sent shares, but make sure that it sent shares for every one of this signer's key_ids
573                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                    // we've handled everything except BadPrivateShares and Point both of which should map to DkgFailure::BadPrivateShares
628                    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    /// do we have all DkgPublicShares?
678    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    /// do we have all DkgPublicShares and DkgPrivateShares?
689    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                // need public shares from active signers
700                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                    // need private shares from active signers
709                    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        // The expected usage is that Signer IDs start at zero and
773        // increment by one until self.total_signers - 1. So the checks
774        // here should be sufficient for catching empty signer ID sets,
775        // duplicate signer IDs, or unknown signer IDs.
776        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        //let _party_state = self.signer.save();
857
858        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            // encrypt each share for the recipient
942            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    /// handle incoming DkgEndBegin
969    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    /// handle incoming DkgPublicShares
984    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        // check that the signer_id exists in the config
998        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    /// handle incoming DkgPrivateShares
1044    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        // go ahead and decrypt here, since we know the signer_id and hence the pubkey of the sender
1050        let src_signer_id = dkg_private_shares.signer_id;
1051
1052        // check that the signer_id exists in the config
1053        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        // make a HashSet of our key_ids so we can quickly query them
1082        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)]
1197/// Test module for signer functionality
1198pub 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        // more signers than keys
1235        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        // threshold == 0
1251        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        // dkg_threshold == 0
1267        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        // threshold > total_keys
1283        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        // dkg_threshold < threshold
1299        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        // signer_id >= num_signers
1315        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        // key_id == 0
1331        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        // key_id > num_keys
1347        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        // public_keys: key_id == 0
1363    }
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        // check that a duplicate public share is ignored
1412        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        // publich_shares_done starts out as false
1454        assert!(!signer.public_shares_done());
1455
1456        // meet the conditions for all public keys received
1457        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        // public_shares_done should be true
1467        assert!(signer.public_shares_done());
1468    }
1469
1470    #[test]
1471    #[cfg(feature = "with_v1")]
1472    /// test basic insertion and detection of duplicates for DkgPrivateShares for v1
1473    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        // check that a duplicate private share is ignored
1521        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    /// test basic insertion and detection of duplicates for DkgPrivateShares for v2
1538    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        // check that a duplicate private share is ignored
1586        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        // can_dkg_end starts out as false
1630        assert!(!signer.can_dkg_end());
1631
1632        // meet the conditions for DKG_END
1633        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        // can_dkg_end should be true
1677        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    //use tracing_subscriber::{fmt, prelude::*, EnvFilter};
1691
1692    fn dkg_ended<SignerType: SignerTrait>() {
1693        /*tracing_subscriber::registry()
1694        .with(fmt::layer())
1695        .with(EnvFilter::from_default_env())
1696        .init();*/
1697        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}