use bls::{PublicKey, Signature};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet};
use std::fmt;
use crate::error::{Error, Result};
use crate::sdkg::{Ack, Part};
pub type NodeId = u8;
pub(crate) type IdPart = (NodeId, Part);
pub(crate) type IdAck = (NodeId, Ack);
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Serialize, Deserialize)]
pub enum DkgVote {
SinglePart(Part),
SingleAck(BTreeMap<IdPart, Ack>),
AllAcks(BTreeMap<IdPart, BTreeSet<IdAck>>),
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Serialize, Deserialize)]
pub struct DkgSignedVote {
vote: DkgVote,
pub voter: NodeId,
pub sig: Signature,
}
impl fmt::Debug for DkgSignedVote {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}:{:?}", self.voter, self.vote)
}
}
fn verify_sig<M: Serialize>(msg: &M, sig: &Signature, public_key: &PublicKey) -> Result<()> {
let msg_bytes = bincode::serialize(msg)?;
if public_key.verify(sig, msg_bytes) {
Ok(())
} else {
Err(Error::InvalidSignature)
}
}
impl DkgSignedVote {
pub fn new(vote: DkgVote, voter: NodeId, sig: Signature) -> Self {
DkgSignedVote { vote, voter, sig }
}
pub fn get_validated_vote(&self, public_key: &PublicKey) -> Result<DkgVote> {
verify_sig(&self.vote, &self.sig, public_key)?;
Ok(self.vote.clone())
}
pub(crate) fn is_all_acks(&self) -> bool {
matches!(self.vote, DkgVote::AllAcks(_))
}
}
#[cfg(test)]
pub(crate) mod test_utils {
use super::{DkgSignedVote, DkgVote};
#[allow(dead_code)]
#[derive(Debug)]
pub(crate) enum MockDkgVote {
SinglePart,
SingleAck,
AllAcks,
}
impl PartialEq<DkgSignedVote> for MockDkgVote {
fn eq(&self, other: &DkgSignedVote) -> bool {
match self {
MockDkgVote::SinglePart if matches!(other.vote, DkgVote::SinglePart(_)) => true,
MockDkgVote::SingleAck if matches!(other.vote, DkgVote::SingleAck(_)) => true,
MockDkgVote::AllAcks if matches!(other.vote, DkgVote::AllAcks(_)) => true,
_ => false,
}
}
}
}