use commonware_codec::{Encode, EncodeSize, Error as CodecError, Read, ReadExt, Write};
use commonware_consensus::{
simplex::types::Context, types::Height, Block as ConsensusBlock, CertifiableBlock, Heightable,
};
use commonware_cryptography::{
bls12381::{dkg::SignedDealerLog, primitives::variant::Variant},
Committable, Digest, Digestible, Hasher, Signer,
};
use commonware_runtime::{Buf, BufMut};
use std::num::NonZeroU32;
#[derive(Clone)]
pub struct Block<H, C, V>
where
H: Hasher,
C: Signer,
V: Variant,
{
pub context: Context<H::Digest, C::PublicKey>,
pub parent: H::Digest,
pub height: Height,
pub log: Option<SignedDealerLog<V, C>>,
}
impl<H, C, V> Block<H, C, V>
where
H: Hasher,
C: Signer,
V: Variant,
{
pub const fn new(
context: Context<H::Digest, C::PublicKey>,
parent: H::Digest,
height: Height,
log: Option<SignedDealerLog<V, C>>,
) -> Self {
Self {
context,
parent,
height,
log,
}
}
}
impl<H, C, V> Write for Block<H, C, V>
where
H: Hasher,
C: Signer,
V: Variant,
{
fn write(&self, buf: &mut impl BufMut) {
self.context.write(buf);
self.parent.write(buf);
self.height.write(buf);
self.log.write(buf);
}
}
impl<H, C, V> EncodeSize for Block<H, C, V>
where
H: Hasher,
C: Signer,
V: Variant,
{
fn encode_size(&self) -> usize {
self.context.encode_size()
+ self.parent.encode_size()
+ self.height.encode_size()
+ self.log.encode_size()
}
}
impl<H, C, V> Read for Block<H, C, V>
where
H: Hasher,
C: Signer,
V: Variant,
{
type Cfg = NonZeroU32;
fn read_cfg(buf: &mut impl Buf, cfg: &Self::Cfg) -> Result<Self, CodecError> {
Ok(Self {
context: Context::read(buf)?,
parent: H::Digest::read(buf)?,
height: Height::read(buf)?,
log: Read::read_cfg(buf, cfg)?,
})
}
}
impl<H, C, V> Digestible for Block<H, C, V>
where
H: Hasher,
C: Signer,
V: Variant,
{
type Digest = H::Digest;
fn digest(&self) -> H::Digest {
H::hash(&self.encode())
}
}
impl<H, C, V> Committable for Block<H, C, V>
where
H: Hasher,
C: Signer,
V: Variant,
{
type Commitment = H::Digest;
fn commitment(&self) -> H::Digest {
self.digest()
}
}
impl<H, C, V> Heightable for Block<H, C, V>
where
H: Hasher,
C: Signer,
V: Variant,
{
fn height(&self) -> Height {
self.height
}
}
impl<H, C, V> ConsensusBlock for Block<H, C, V>
where
H: Hasher,
C: Signer,
V: Variant,
{
fn parent(&self) -> Self::Digest {
self.parent
}
}
impl<H, C, V> CertifiableBlock for Block<H, C, V>
where
H: Hasher,
C: Signer,
V: Variant,
{
type Context = Context<H::Digest, C::PublicKey>;
fn context(&self) -> Self::Context {
self.context.clone()
}
}
pub const fn genesis_block<H, C, V>(context: Context<H::Digest, C::PublicKey>) -> Block<H, C, V>
where
H: Hasher,
C: Signer,
V: Variant,
{
Block::new(
context,
<<H as Hasher>::Digest as Digest>::EMPTY,
Height::zero(),
None,
)
}