use std::collections::BTreeMap;
use hashbrown::{HashMap, HashSet};
use thiserror::Error as ThisError;
use crate::{
common::{validate_key_id, validate_signer_id, Signature},
curve::{ecdsa, point::Point},
errors::AggregatorError,
net::DkgFailure,
state_machine::coordinator::Error as CoordinatorError,
state_machine::signer::{ConfigError, Error as SignerError},
taproot::SchnorrProof,
};
pub trait StateMachine<S, E> {
fn move_to(&mut self, state: S) -> Result<(), E>;
fn can_move_to(&self, state: &S) -> Result<(), E>;
}
#[derive(ThisError, Debug, Clone)]
#[allow(clippy::large_enum_variant)]
pub enum Error {
#[error("signer error {0:?}")]
Signer(#[from] SignerError),
#[error("coordinator error {0:?}")]
Coordinator(#[from] CoordinatorError),
}
#[derive(ThisError, Debug, Clone)]
pub enum DkgError {
#[error("DKG public timeout, waiting for {0:?}")]
DkgPublicTimeout(Vec<u32>),
#[error("DKG private timeout, waiting for {0:?}")]
DkgPrivateTimeout(Vec<u32>),
#[error("DKG end timeout, waiting for {0:?}")]
DkgEndTimeout(Vec<u32>),
#[error("DKG end failure")]
DkgEndFailure(HashMap<u32, DkgFailure>),
}
#[derive(ThisError, Debug, Clone)]
#[allow(clippy::large_enum_variant)]
pub enum SignError {
#[error("Nonce timeout, valid responses from {0:?}, signers {1:?} are malicious")]
NonceTimeout(Vec<u32>, Vec<u32>),
#[error("Insufficient signers, {0:?} are malicious")]
InsufficientSigners(Vec<u32>),
#[error("Signature aggregator error")]
Aggregator(#[from] AggregatorError),
#[error("Coordinator error")]
Coordinator(#[from] CoordinatorError),
}
#[derive(Debug, Clone)]
pub enum OperationResult {
Dkg(Point),
Sign(Signature),
SignSchnorr(SchnorrProof),
SignTaproot(SchnorrProof),
DkgError(DkgError),
SignError(SignError),
}
#[derive(Clone, Default, PartialEq, Eq)]
pub struct PublicKeys {
pub signers: HashMap<u32, ecdsa::PublicKey>,
pub key_ids: HashMap<u32, ecdsa::PublicKey>,
pub signer_key_ids: HashMap<u32, HashSet<u32>>,
}
impl PublicKeys {
pub fn validate(&self, num_signers: u32, num_keys: u32) -> Result<(), SignerError> {
for (signer_id, _key) in &self.signers {
if !validate_signer_id(*signer_id, num_signers) {
return Err(SignerError::Config(ConfigError::InvalidSignerId(
*signer_id,
)));
}
}
for (key_id, _key) in &self.key_ids {
if !validate_key_id(*key_id, num_keys) {
return Err(SignerError::Config(ConfigError::InvalidKeyId(*key_id)));
}
}
for (signer_id, key_ids) in &self.signer_key_ids {
if !validate_signer_id(*signer_id, num_signers) {
return Err(SignerError::Config(ConfigError::InvalidSignerId(
*signer_id,
)));
}
for key_id in key_ids {
if !validate_key_id(*key_id, num_keys) {
return Err(SignerError::Config(ConfigError::InvalidKeyId(*key_id)));
}
}
}
Ok(())
}
}
impl std::fmt::Debug for PublicKeys {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PublicKeys")
.field("signers", &BTreeMap::from_iter(self.signers.iter()))
.field("key_ids", &BTreeMap::from_iter(self.key_ids.iter()))
.finish()
}
}
pub mod coordinator;
pub mod signer;