use bytes::{Buf, BufMut}; use commonware_codec::{varint::UInt, EncodeSize, Error, Read, ReadExt, Write}; use commonware_cryptography::{Committable, Digest, Digestible, Hasher}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct Block { /// The parent block's digest. pub parent: D, /// The height of the block in the blockchain. pub height: u64, /// The timestamp of the block (in milliseconds since the Unix epoch). pub timestamp: u64, /// Pre-computed digest of the block. digest: D, } impl Block { fn compute_digest>(parent: &D, height: u64, timestamp: u64) -> D { let mut hasher = H::new(); hasher.update(parent); hasher.update(&height.to_be_bytes()); hasher.update(×tamp.to_be_bytes()); hasher.finalize() } pub fn new>(parent: D, height: u64, timestamp: u64) -> Self { let digest = Self::compute_digest::(&parent, height, timestamp); Self { parent, height, timestamp, digest, } } } impl Write for Block { fn write(&self, writer: &mut impl BufMut) { self.parent.write(writer); UInt(self.height).write(writer); UInt(self.timestamp).write(writer); self.digest.write(writer); } } impl Read for Block { type Cfg = (); fn read_cfg(reader: &mut impl Buf, _: &Self::Cfg) -> Result { let parent = D::read(reader)?; let height = UInt::read(reader)?.into(); let timestamp = UInt::read(reader)?.into(); let digest = D::read(reader)?; // Pre-compute the digest Ok(Self { parent, height, timestamp, digest, }) } } impl EncodeSize for Block { fn encode_size(&self) -> usize { self.parent.encode_size() + UInt(self.height).encode_size() + UInt(self.timestamp).encode_size() + self.digest.encode_size() } } impl Digestible for Block { type Digest = D; fn digest(&self) -> D { self.digest } } impl Committable for Block { type Commitment = D; fn commitment(&self) -> D { self.digest } } impl crate::Block for Block { fn height(&self) -> u64 { self.height } fn parent(&self) -> Self::Commitment { self.parent } }