1use bytes::{Buf, BufMut};
2use commonware_codec::{varint::UInt, EncodeSize, Error, Read, ReadExt, Write};
3use commonware_consensus::threshold_simplex::types::{Finalization, Notarization};
4use commonware_cryptography::{
5 bls12381::primitives::variant::{MinSig, Variant},
6 sha256::Digest,
7 Committable, Digestible, Hasher, Sha256,
8};
9
10#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct Block {
12 pub parent: Digest,
14
15 pub height: u64,
17
18 pub timestamp: u64,
20
21 digest: Digest,
23}
24
25impl Block {
26 fn compute_digest(parent: &Digest, height: u64, timestamp: u64) -> Digest {
27 let mut hasher = Sha256::new();
28 hasher.update(parent);
29 hasher.update(&height.to_be_bytes());
30 hasher.update(×tamp.to_be_bytes());
31 hasher.finalize()
32 }
33
34 pub fn new(parent: Digest, height: u64, timestamp: u64) -> Self {
35 let digest = Self::compute_digest(&parent, height, timestamp);
36 Self {
37 parent,
38 height,
39 timestamp,
40 digest,
41 }
42 }
43}
44
45impl Write for Block {
46 fn write(&self, writer: &mut impl BufMut) {
47 self.parent.write(writer);
48 UInt(self.height).write(writer);
49 UInt(self.timestamp).write(writer);
50 }
51}
52
53impl Read for Block {
54 type Cfg = ();
55
56 fn read_cfg(reader: &mut impl Buf, _: &Self::Cfg) -> Result<Self, Error> {
57 let parent = Digest::read(reader)?;
58 let height = UInt::read(reader)?.into();
59 let timestamp = UInt::read(reader)?.into();
60
61 let digest = Self::compute_digest(&parent, height, timestamp);
63 Ok(Self {
64 parent,
65 height,
66 timestamp,
67
68 digest,
69 })
70 }
71}
72
73impl EncodeSize for Block {
74 fn encode_size(&self) -> usize {
75 self.parent.encode_size()
76 + UInt(self.height).encode_size()
77 + UInt(self.timestamp).encode_size()
78 }
79}
80
81impl Digestible for Block {
82 type Digest = Digest;
83
84 fn digest(&self) -> Digest {
85 self.digest
86 }
87}
88
89impl Committable for Block {
90 type Commitment = Digest;
91
92 fn commitment(&self) -> Digest {
93 self.digest
94 }
95}
96
97#[derive(Clone, Debug, PartialEq, Eq)]
98pub struct Notarized {
99 pub proof: Notarization<MinSig, Digest>,
100 pub block: Block,
101}
102
103impl Notarized {
104 pub fn new(proof: Notarization<MinSig, Digest>, block: Block) -> Self {
105 Self { proof, block }
106 }
107
108 pub fn verify(&self, namespace: &[u8], identity: &<MinSig as Variant>::Public) -> bool {
109 self.proof.verify(namespace, identity)
110 }
111}
112
113impl Write for Notarized {
114 fn write(&self, buf: &mut impl BufMut) {
115 self.proof.write(buf);
116 self.block.write(buf);
117 }
118}
119
120impl Read for Notarized {
121 type Cfg = ();
122
123 fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result<Self, Error> {
124 let proof = Notarization::<MinSig, Digest>::read(buf)?;
125 let block = Block::read(buf)?;
126
127 if proof.proposal.payload != block.digest() {
129 return Err(Error::Invalid(
130 "types::Notarized",
131 "Proof payload does not match block digest",
132 ));
133 }
134 Ok(Self { proof, block })
135 }
136}
137
138impl EncodeSize for Notarized {
139 fn encode_size(&self) -> usize {
140 self.proof.encode_size() + self.block.encode_size()
141 }
142}
143
144#[derive(Clone, Debug, PartialEq, Eq)]
145pub struct Finalized {
146 pub proof: Finalization<MinSig, Digest>,
147 pub block: Block,
148}
149
150impl Finalized {
151 pub fn new(proof: Finalization<MinSig, Digest>, block: Block) -> Self {
152 Self { proof, block }
153 }
154
155 pub fn verify(&self, namespace: &[u8], identity: &<MinSig as Variant>::Public) -> bool {
156 self.proof.verify(namespace, identity)
157 }
158}
159
160impl Write for Finalized {
161 fn write(&self, buf: &mut impl BufMut) {
162 self.proof.write(buf);
163 self.block.write(buf);
164 }
165}
166
167impl Read for Finalized {
168 type Cfg = ();
169
170 fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result<Self, Error> {
171 let proof = Finalization::<MinSig, Digest>::read(buf)?;
172 let block = Block::read(buf)?;
173
174 if proof.proposal.payload != block.digest() {
176 return Err(Error::Invalid(
177 "types::Finalized",
178 "Proof payload does not match block digest",
179 ));
180 }
181 Ok(Self { proof, block })
182 }
183}
184
185impl EncodeSize for Finalized {
186 fn encode_size(&self) -> usize {
187 self.proof.encode_size() + self.block.encode_size()
188 }
189}
190
191impl commonware_consensus::Block for Block {
192 fn parent(&self) -> Digest {
193 self.parent
194 }
195
196 fn height(&self) -> u64 {
197 self.height
198 }
199}