alto_types/
lib.rs

1//! Common types used throughout `alto`.
2
3mod block;
4pub use block::{Block, Finalized, Notarized};
5mod consensus;
6use commonware_utils::hex;
7pub use consensus::{
8    leader_index, Activity, Evaluation, Finalization, Identity, Notarization, Seed, Signature,
9};
10pub mod wasm;
11
12pub const NAMESPACE: &[u8] = b"_ALTO";
13
14#[repr(u8)]
15pub enum Kind {
16    Seed = 0,
17    Notarization = 1,
18    Finalization = 2,
19}
20
21impl Kind {
22    pub fn from_u8(value: u8) -> Option<Self> {
23        match value {
24            0 => Some(Self::Seed),
25            1 => Some(Self::Notarization),
26            2 => Some(Self::Finalization),
27            _ => None,
28        }
29    }
30
31    pub fn to_hex(&self) -> String {
32        match self {
33            Self::Seed => hex(&[0]),
34            Self::Notarization => hex(&[1]),
35            Self::Finalization => hex(&[2]),
36        }
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43    use commonware_codec::{DecodeExt, Encode};
44    use commonware_consensus::threshold_simplex::types::{
45        Finalization, Finalize, Notarization, Notarize, Proposal,
46    };
47    use commonware_cryptography::{
48        bls12381::{
49            dkg::ops,
50            primitives::{ops::threshold_signature_recover, poly, variant::MinSig},
51        },
52        hash, Digestible,
53    };
54    use rand::{rngs::StdRng, SeedableRng};
55
56    #[test]
57    fn test_notarized() {
58        // Create network key
59        let mut rng = StdRng::seed_from_u64(0);
60        let (polynomial, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, 4, 3);
61
62        // Create a block
63        let digest = hash(b"hello world");
64        let block = Block::new(digest, 10, 100);
65        let proposal = Proposal::new(11, 8, block.digest());
66
67        // Create a notarization
68        let partials = shares
69            .iter()
70            .map(|share| Notarize::<MinSig, _>::sign(NAMESPACE, share, proposal.clone()))
71            .collect::<Vec<_>>();
72        let proposal_partials = partials
73            .iter()
74            .map(|partial| partial.proposal_signature.clone())
75            .collect::<Vec<_>>();
76        let proposal_recovered =
77            threshold_signature_recover::<MinSig, _>(3, &proposal_partials).unwrap();
78        let seed_partials = partials
79            .into_iter()
80            .map(|partial| partial.seed_signature)
81            .collect::<Vec<_>>();
82        let seed_recovered = threshold_signature_recover::<MinSig, _>(3, &seed_partials).unwrap();
83        let notarization = Notarization::new(proposal, proposal_recovered, seed_recovered);
84        let notarized = Notarized::new(notarization, block.clone());
85
86        // Serialize and deserialize
87        let encoded = notarized.encode();
88        let decoded = Notarized::decode(encoded).expect("failed to decode notarized");
89        assert_eq!(notarized, decoded);
90
91        // Verify notarized
92        let public_key = poly::public::<MinSig>(&polynomial);
93        assert!(notarized.verify(NAMESPACE, public_key));
94    }
95
96    #[test]
97    fn test_finalized() {
98        // Create network key
99        let mut rng = StdRng::seed_from_u64(0);
100        let (polynomial, shares) = ops::generate_shares::<_, MinSig>(&mut rng, None, 4, 3);
101
102        // Create a block
103        let digest = hash(b"hello world");
104        let block = Block::new(digest, 10, 100);
105        let proposal = Proposal::new(11, 8, block.digest());
106
107        // Create a finalization
108        let partials = shares
109            .iter()
110            .map(|share| Notarize::<MinSig, _>::sign(NAMESPACE, share, proposal.clone()))
111            .collect::<Vec<_>>();
112        let seed_partials = partials
113            .into_iter()
114            .map(|partial| partial.seed_signature)
115            .collect::<Vec<_>>();
116        let seed_recovered = threshold_signature_recover::<MinSig, _>(3, &seed_partials).unwrap();
117        let finalize_partials = shares
118            .iter()
119            .map(|share| Finalize::<MinSig, _>::sign(NAMESPACE, share, proposal.clone()))
120            .collect::<Vec<_>>();
121        let finalize_partials = finalize_partials
122            .into_iter()
123            .map(|partial| partial.proposal_signature)
124            .collect::<Vec<_>>();
125        let finalize_recovered =
126            threshold_signature_recover::<MinSig, _>(3, &finalize_partials).unwrap();
127        let finalized = Finalization::new(proposal, finalize_recovered, seed_recovered);
128        let finalized = Finalized::new(finalized, block.clone());
129
130        // Serialize and deserialize
131        let encoded = finalized.encode();
132        let decoded = Finalized::decode(encoded).expect("failed to decode finalized");
133        assert_eq!(finalized, decoded);
134
135        // Verify finalized
136        let public_key = poly::public::<MinSig>(&polynomial);
137        assert!(finalized.verify(NAMESPACE, public_key));
138    }
139}