Skip to main content

hotmint_types/
crypto.rs

1use ruc::*;
2use serde::{Deserialize, Serialize};
3
4use crate::validator::{ValidatorId, ValidatorSet};
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7pub struct Signature(pub Vec<u8>);
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
10pub struct PublicKey(pub Vec<u8>);
11
12/// Simple aggregate signature: bitfield indicating which validators signed + individual signatures
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct AggregateSignature {
15    pub signers: Vec<bool>,
16    pub signatures: Vec<Signature>,
17}
18
19impl AggregateSignature {
20    pub fn new(validator_count: usize) -> Self {
21        Self {
22            signers: vec![false; validator_count],
23            signatures: Vec::new(),
24        }
25    }
26
27    pub fn add(&mut self, index: usize, sig: Signature) -> Result<()> {
28        if index >= self.signers.len() {
29            return Err(eg!("signer index out of bounds"));
30        }
31        if self.signers[index] {
32            return Err(eg!("duplicate signature from validator {}", index));
33        }
34        self.signers[index] = true;
35        self.signatures.push(sig);
36        Ok(())
37    }
38
39    pub fn count(&self) -> usize {
40        self.signers.iter().filter(|&&s| s).count()
41    }
42}
43
44pub trait Signer: Send + Sync {
45    fn sign(&self, message: &[u8]) -> Signature;
46    fn public_key(&self) -> PublicKey;
47    fn validator_id(&self) -> ValidatorId;
48}
49
50pub trait Verifier: Send + Sync {
51    fn verify(&self, pk: &PublicKey, msg: &[u8], sig: &Signature) -> bool;
52    fn verify_aggregate(&self, vs: &ValidatorSet, msg: &[u8], agg: &AggregateSignature) -> bool;
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn test_aggregate_signature_add() {
61        let mut agg = AggregateSignature::new(4);
62        assert_eq!(agg.count(), 0);
63        agg.add(0, Signature(vec![1])).unwrap();
64        assert_eq!(agg.count(), 1);
65        agg.add(2, Signature(vec![2])).unwrap();
66        assert_eq!(agg.count(), 2);
67    }
68
69    #[test]
70    fn test_aggregate_signature_duplicate_rejected() {
71        let mut agg = AggregateSignature::new(4);
72        agg.add(1, Signature(vec![1])).unwrap();
73        assert!(agg.add(1, Signature(vec![2])).is_err());
74    }
75
76    #[test]
77    fn test_aggregate_signature_out_of_bounds() {
78        let mut agg = AggregateSignature::new(3);
79        assert!(agg.add(3, Signature(vec![1])).is_err());
80        assert!(agg.add(100, Signature(vec![1])).is_err());
81    }
82
83    #[test]
84    fn test_aggregate_signature_zero_size() {
85        let agg = AggregateSignature::new(0);
86        assert_eq!(agg.count(), 0);
87    }
88}