use commonware_consensus::types::Epoch;
use commonware_formatting::hex;
use commonware_utils::NZU64;
use std::num::NonZero;
mod block;
pub use block::{Block, Finalized, Notarized};
mod consensus;
pub use consensus::{
Activity, Context, Finalization, Identity, Notarization, PublicKey, Scheme, Seed, Seedable,
Signature,
};
pub mod wasm;
pub const NAMESPACE: &[u8] = b"_ALTO";
pub const EPOCH: Epoch = Epoch::zero();
pub const EPOCH_LENGTH: NonZero<u64> = NZU64!(u64::MAX);
#[repr(u8)]
pub enum Kind {
Seed = 0,
Notarization = 1,
Finalization = 2,
}
impl Kind {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(Self::Seed),
1 => Some(Self::Notarization),
2 => Some(Self::Finalization),
_ => None,
}
}
pub fn to_hex(&self) -> String {
match self {
Self::Seed => hex(&[0]),
Self::Notarization => hex(&[1]),
Self::Finalization => hex(&[2]),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use commonware_codec::{DecodeExt, Encode};
use commonware_consensus::{
simplex::{
scheme::bls12381_threshold::vrf as bls12381_threshold,
types::{Finalization, Finalize, Notarization, Notarize, Proposal},
},
types::{Height, Round, View},
};
use commonware_cryptography::{
bls12381::primitives::variant::MinSig, certificate::mocks::Fixture, ed25519, sha256,
Digest, Digestible, Hasher, Sha256, Signer,
};
use commonware_parallel::Sequential;
use rand::{rngs::StdRng, SeedableRng};
#[test]
fn test_notarized() {
let mut rng = StdRng::seed_from_u64(0);
let n = 4;
let Fixture { schemes, .. } =
bls12381_threshold::fixture::<MinSig, _>(&mut rng, NAMESPACE, n);
let context = Context {
round: Round::new(EPOCH, View::new(9)),
leader: ed25519::PrivateKey::from_seed(0).public_key(),
parent: (View::new(8), sha256::Digest::EMPTY),
};
let digest = Sha256::hash(b"hello world");
let block = Block::new(context, digest, Height::new(10), 100);
let proposal = Proposal::new(
Round::new(EPOCH, View::new(9)),
View::new(8),
block.digest(),
);
let notarizes: Vec<_> = schemes
.iter()
.map(|scheme| Notarize::sign(scheme, proposal.clone()).unwrap())
.collect();
let notarization =
Notarization::from_notarizes(&schemes[0], ¬arizes, &Sequential).unwrap();
let notarized = Notarized::new(notarization, block.clone());
let encoded = notarized.encode();
let decoded = Notarized::decode(encoded).expect("failed to decode notarized");
assert_eq!(notarized, decoded);
assert!(notarized.verify(&schemes[0], &Sequential));
}
#[test]
fn test_finalized() {
let mut rng = StdRng::seed_from_u64(0);
let n = 4;
let Fixture { schemes, .. } =
bls12381_threshold::fixture::<MinSig, _>(&mut rng, NAMESPACE, n);
let context = Context {
round: Round::new(EPOCH, View::new(9)),
leader: ed25519::PrivateKey::from_seed(0).public_key(),
parent: (View::new(8), sha256::Digest::EMPTY),
};
let digest = Sha256::hash(b"hello world");
let block = Block::new(context, digest, Height::new(10), 100);
let proposal = Proposal::new(
Round::new(EPOCH, View::new(9)),
View::new(8),
block.digest(),
);
let finalizes: Vec<_> = schemes
.iter()
.map(|scheme| Finalize::sign(scheme, proposal.clone()).unwrap())
.collect();
let finalization =
Finalization::from_finalizes(&schemes[0], &finalizes, &Sequential).unwrap();
let finalized = Finalized::new(finalization, block.clone());
let encoded = finalized.encode();
let decoded = Finalized::decode(encoded).expect("failed to decode finalized");
assert_eq!(finalized, decoded);
assert!(finalized.verify(&schemes[0], &Sequential));
}
}