wsts/state_machine/
mod.rs1use std::collections::BTreeMap;
2
3use hashbrown::{HashMap, HashSet};
4use thiserror::Error as ThisError;
5
6use crate::{
7 common::{validate_key_id, validate_signer_id, Signature},
8 curve::{ecdsa, point::Point},
9 errors::AggregatorError,
10 net::DkgFailure,
11 state_machine::coordinator::Error as CoordinatorError,
12 state_machine::signer::{ConfigError, Error as SignerError},
13 taproot::SchnorrProof,
14};
15
16pub trait StateMachine<S, E> {
18 fn move_to(&mut self, state: S) -> Result<(), E>;
20 fn can_move_to(&self, state: &S) -> Result<(), E>;
22}
23
24#[derive(ThisError, Debug, Clone)]
26#[allow(clippy::large_enum_variant)]
27pub enum Error {
28 #[error("signer error {0:?}")]
30 Signer(#[from] SignerError),
31 #[error("coordinator error {0:?}")]
33 Coordinator(#[from] CoordinatorError),
34}
35
36#[derive(ThisError, Debug, Clone)]
38pub enum DkgError {
39 #[error("DKG public timeout, waiting for {0:?}")]
41 DkgPublicTimeout(Vec<u32>),
42 #[error("DKG private timeout, waiting for {0:?}")]
44 DkgPrivateTimeout(Vec<u32>),
45 #[error("DKG end timeout, waiting for {0:?}")]
47 DkgEndTimeout(Vec<u32>),
48 #[error("DKG end failure")]
50 DkgEndFailure {
51 reported_failures: HashMap<u32, DkgFailure>,
53 malicious_signers: HashSet<u32>,
55 },
56}
57
58#[derive(ThisError, Debug, Clone)]
60#[allow(clippy::large_enum_variant)]
61pub enum SignError {
62 #[error("Nonce timeout, valid responses from {0:?}, signers {1:?} are malicious")]
64 NonceTimeout(Vec<u32>, Vec<u32>),
65 #[error("Insufficient signers, {0:?} are malicious")]
67 InsufficientSigners(Vec<u32>),
68 #[error("Signature aggregator error")]
70 Aggregator(#[from] AggregatorError),
71 #[error("Coordinator error")]
73 Coordinator(#[from] CoordinatorError),
74}
75
76#[derive(Debug, Clone)]
78pub enum OperationResult {
79 Dkg(Point),
81 Sign(Signature),
83 SignSchnorr(SchnorrProof),
85 SignTaproot(SchnorrProof),
87 DkgError(DkgError),
89 SignError(SignError),
91}
92
93#[derive(Clone, Default, PartialEq, Eq)]
94pub struct PublicKeys {
96 pub signers: HashMap<u32, ecdsa::PublicKey>,
98 pub key_ids: HashMap<u32, ecdsa::PublicKey>,
100 pub signer_key_ids: HashMap<u32, HashSet<u32>>,
102}
103
104impl PublicKeys {
105 pub fn validate(&self, num_signers: u32, num_keys: u32) -> Result<(), SignerError> {
107 for (signer_id, _key) in &self.signers {
108 if !validate_signer_id(*signer_id, num_signers) {
109 return Err(SignerError::Config(ConfigError::InvalidSignerId(
110 *signer_id,
111 )));
112 }
113 }
114
115 for (key_id, _key) in &self.key_ids {
116 if !validate_key_id(*key_id, num_keys) {
117 return Err(SignerError::Config(ConfigError::InvalidKeyId(*key_id)));
118 }
119 }
120
121 for (signer_id, key_ids) in &self.signer_key_ids {
122 if !validate_signer_id(*signer_id, num_signers) {
123 return Err(SignerError::Config(ConfigError::InvalidSignerId(
124 *signer_id,
125 )));
126 }
127
128 for key_id in key_ids {
129 if !validate_key_id(*key_id, num_keys) {
130 return Err(SignerError::Config(ConfigError::InvalidKeyId(*key_id)));
131 }
132 }
133 }
134
135 Ok(())
136 }
137}
138
139impl std::fmt::Debug for PublicKeys {
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 f.debug_struct("PublicKeys")
142 .field("signers", &BTreeMap::from_iter(self.signers.iter()))
143 .field("key_ids", &BTreeMap::from_iter(self.key_ids.iter()))
144 .finish()
145 }
146}
147
148pub mod coordinator;
150
151pub mod signer;