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<Digest> for Block {
82 fn digest(&self) -> Digest {
83 self.digest
84 }
85}
86
87impl Committable<Digest> for Block {
88 fn commitment(&self) -> Digest {
89 self.digest
90 }
91}
92
93#[derive(Clone, Debug, PartialEq, Eq)]
94pub struct Notarized {
95 pub proof: Notarization<MinSig, Digest>,
96 pub block: Block,
97}
98
99impl Notarized {
100 pub fn new(proof: Notarization<MinSig, Digest>, block: Block) -> Self {
101 Self { proof, block }
102 }
103
104 pub fn verify(&self, namespace: &[u8], identity: &<MinSig as Variant>::Public) -> bool {
105 self.proof.verify(namespace, identity)
106 }
107}
108
109impl Write for Notarized {
110 fn write(&self, buf: &mut impl BufMut) {
111 self.proof.write(buf);
112 self.block.write(buf);
113 }
114}
115
116impl Read for Notarized {
117 type Cfg = ();
118
119 fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result<Self, Error> {
120 let proof = Notarization::<MinSig, Digest>::read(buf)?;
121 let block = Block::read(buf)?;
122
123 if proof.proposal.payload != block.digest() {
125 return Err(Error::Invalid(
126 "types::Notarized",
127 "Proof payload does not match block digest",
128 ));
129 }
130 Ok(Self { proof, block })
131 }
132}
133
134impl EncodeSize for Notarized {
135 fn encode_size(&self) -> usize {
136 self.proof.encode_size() + self.block.encode_size()
137 }
138}
139
140#[derive(Clone, Debug, PartialEq, Eq)]
141pub struct Finalized {
142 pub proof: Finalization<MinSig, Digest>,
143 pub block: Block,
144}
145
146impl Finalized {
147 pub fn new(proof: Finalization<MinSig, Digest>, block: Block) -> Self {
148 Self { proof, block }
149 }
150
151 pub fn verify(&self, namespace: &[u8], identity: &<MinSig as Variant>::Public) -> bool {
152 self.proof.verify(namespace, identity)
153 }
154}
155
156impl Write for Finalized {
157 fn write(&self, buf: &mut impl BufMut) {
158 self.proof.write(buf);
159 self.block.write(buf);
160 }
161}
162
163impl Read for Finalized {
164 type Cfg = ();
165
166 fn read_cfg(buf: &mut impl Buf, _: &Self::Cfg) -> Result<Self, Error> {
167 let proof = Finalization::<MinSig, Digest>::read(buf)?;
168 let block = Block::read(buf)?;
169
170 if proof.proposal.payload != block.digest() {
172 return Err(Error::Invalid(
173 "types::Finalized",
174 "Proof payload does not match block digest",
175 ));
176 }
177 Ok(Self { proof, block })
178 }
179}
180
181impl EncodeSize for Finalized {
182 fn encode_size(&self) -> usize {
183 self.proof.encode_size() + self.block.encode_size()
184 }
185}