1use crate::{Finalization, Notarization};
2use bytes::{Buf, BufMut};
3use commonware_cryptography::{bls12381::PublicKey, sha256::Digest, Hasher, Sha256};
4use commonware_utils::{Array, SizedSerialize};
5
6#[derive(Clone, Debug, PartialEq, Eq)]
7pub struct Block {
8 pub parent: Digest,
10
11 pub height: u64,
13
14 pub timestamp: u64,
16
17 digest: Digest,
19}
20
21impl Block {
22 fn compute_digest(parent: &Digest, height: u64, timestamp: u64) -> Digest {
23 let mut hasher = Sha256::new();
24 hasher.update(parent);
25 hasher.update(&height.to_be_bytes());
26 hasher.update(×tamp.to_be_bytes());
27 hasher.finalize()
28 }
29
30 pub fn new(parent: Digest, height: u64, timestamp: u64) -> Self {
31 let digest = Self::compute_digest(&parent, height, timestamp);
32 Self {
33 parent,
34 height,
35 timestamp,
36 digest,
37 }
38 }
39
40 pub fn serialize(&self) -> Vec<u8> {
41 let mut bytes = Vec::with_capacity(Self::SERIALIZED_LEN);
42 bytes.extend_from_slice(&self.parent);
43 bytes.put_u64(self.height);
44 bytes.put_u64(self.timestamp);
45 bytes
46 }
47
48 pub fn deserialize(mut bytes: &[u8]) -> Option<Self> {
49 if bytes.len() != Self::SERIALIZED_LEN {
51 return None;
52 }
53 let parent = Digest::read_from(&mut bytes).ok()?;
54 let height = bytes.get_u64();
55 let timestamp = bytes.get_u64();
56
57 let digest = Self::compute_digest(&parent, height, timestamp);
59 Some(Self {
60 parent,
61 height,
62 timestamp,
63 digest,
64 })
65 }
66
67 pub fn digest(&self) -> Digest {
68 self.digest.clone()
69 }
70}
71
72impl SizedSerialize for Block {
73 const SERIALIZED_LEN: usize =
74 Digest::SERIALIZED_LEN + u64::SERIALIZED_LEN + u64::SERIALIZED_LEN;
75}
76
77pub struct Notarized {
78 pub proof: Notarization,
79 pub block: Block,
80}
81
82impl Notarized {
83 pub fn new(proof: Notarization, block: Block) -> Self {
84 Self { proof, block }
85 }
86
87 pub fn serialize(&self) -> Vec<u8> {
88 let block = self.block.serialize();
89 let mut bytes = Vec::with_capacity(Notarization::SERIALIZED_LEN + block.len());
90 bytes.extend_from_slice(&self.proof.serialize());
91 bytes.extend_from_slice(&block);
92 bytes
93 }
94
95 pub fn deserialize(public: Option<&PublicKey>, bytes: &[u8]) -> Option<Self> {
96 let (proof, block) = bytes.split_at_checked(Notarization::SERIALIZED_LEN)?;
98 let proof = Notarization::deserialize(public, proof)?;
99 let block = Block::deserialize(block)?;
100
101 if proof.payload != block.digest() {
103 return None;
104 }
105 Some(Self { proof, block })
106 }
107}
108
109pub struct Finalized {
110 pub proof: Finalization,
111 pub block: Block,
112}
113
114impl Finalized {
115 pub fn new(proof: Finalization, block: Block) -> Self {
116 Self { proof, block }
117 }
118
119 pub fn serialize(&self) -> Vec<u8> {
120 let block = self.block.serialize();
121 let mut bytes = Vec::with_capacity(Finalization::SERIALIZED_LEN + block.len());
122 bytes.extend_from_slice(&self.proof.serialize());
123 bytes.extend_from_slice(&block);
124 bytes
125 }
126
127 pub fn deserialize(public: Option<&PublicKey>, bytes: &[u8]) -> Option<Self> {
128 let (proof, block) = bytes.split_at_checked(Finalization::SERIALIZED_LEN)?;
130 let proof = Finalization::deserialize(public, proof)?;
131 let block = Block::deserialize(block)?;
132
133 if proof.payload != block.digest() {
135 return None;
136 }
137 Some(Self { proof, block })
138 }
139}