snarkvm_ledger_block/header/
mod.rs1mod metadata;
17pub use metadata::*;
18
19mod bytes;
20mod genesis;
21mod merkle;
22mod serialize;
23mod string;
24mod verify;
25
26use crate::{Ratifications, Transactions};
27use console::{
28 network::prelude::*,
29 program::{HEADER_DEPTH, HeaderLeaf, HeaderPath, HeaderTree},
30 types::Field,
31};
32use snarkvm_synthesizer_program::FinalizeOperation;
33
34use anyhow::Context;
35
36#[derive(Copy, Clone, PartialEq, Eq, Hash)]
38pub struct Header<N: Network> {
39 previous_state_root: N::StateRoot,
41 transactions_root: Field<N>,
43 finalize_root: Field<N>,
45 ratifications_root: Field<N>,
47 solutions_root: Field<N>,
49 subdag_root: Field<N>,
51 metadata: Metadata<N>,
53}
54
55impl<N: Network> Header<N> {
56 pub fn from(
58 previous_state_root: N::StateRoot,
59 transactions_root: Field<N>,
60 finalize_root: Field<N>,
61 ratifications_root: Field<N>,
62 solutions_root: Field<N>,
63 subdag_root: Field<N>,
64 metadata: Metadata<N>,
65 ) -> Result<Self> {
66 let header = Self {
68 previous_state_root,
69 transactions_root,
70 finalize_root,
71 ratifications_root,
72 solutions_root,
73 subdag_root,
74 metadata,
75 };
76 header.check_validity().with_context(|| "Invalid block header")?;
78 Ok(header)
79 }
80
81 pub fn is_valid(&self) -> bool {
85 self.check_validity().is_ok()
86 }
87
88 pub fn check_validity(&self) -> Result<()> {
90 if self.height() == 0u32 {
91 if !self.is_genesis()? {
92 bail!("Block at height 0 is not a gensis block");
93 }
94 return Ok(());
95 }
96
97 self.metadata.check_validity().with_context(|| "Invalid metadata")?;
98
99 ensure!(*self.previous_state_root != Field::zero(), "Previous state root cannot be zero");
100 ensure!(self.transactions_root != Field::zero(), "Transactions root cannot be zero");
101 ensure!(self.finalize_root != Field::zero(), "Finalize root cannot be zero");
102 ensure!(self.ratifications_root != Field::zero(), "Ratifications root cannot be zero");
103
104 Ok(())
105 }
106
107 pub const fn previous_state_root(&self) -> N::StateRoot {
109 self.previous_state_root
110 }
111
112 pub const fn transactions_root(&self) -> Field<N> {
114 self.transactions_root
115 }
116
117 pub const fn finalize_root(&self) -> Field<N> {
119 self.finalize_root
120 }
121
122 pub const fn ratifications_root(&self) -> Field<N> {
124 self.ratifications_root
125 }
126
127 pub const fn solutions_root(&self) -> Field<N> {
129 self.solutions_root
130 }
131
132 pub const fn subdag_root(&self) -> Field<N> {
134 self.subdag_root
135 }
136
137 pub const fn metadata(&self) -> &Metadata<N> {
139 &self.metadata
140 }
141
142 pub const fn network(&self) -> u16 {
144 self.metadata.network()
145 }
146
147 pub const fn round(&self) -> u64 {
149 self.metadata.round()
150 }
151
152 pub const fn height(&self) -> u32 {
154 self.metadata.height()
155 }
156
157 pub const fn cumulative_weight(&self) -> u128 {
159 self.metadata.cumulative_weight()
160 }
161
162 pub const fn cumulative_proof_target(&self) -> u128 {
164 self.metadata.cumulative_proof_target()
165 }
166
167 pub const fn coinbase_target(&self) -> u64 {
169 self.metadata.coinbase_target()
170 }
171
172 pub const fn proof_target(&self) -> u64 {
174 self.metadata.proof_target()
175 }
176
177 pub const fn last_coinbase_target(&self) -> u64 {
179 self.metadata.last_coinbase_target()
180 }
181
182 pub const fn last_coinbase_timestamp(&self) -> i64 {
184 self.metadata.last_coinbase_timestamp()
185 }
186
187 pub const fn timestamp(&self) -> i64 {
189 self.metadata.timestamp()
190 }
191}
192
193#[cfg(test)]
194pub mod test_helpers {
195 use super::*;
196
197 type CurrentNetwork = console::network::MainnetV0;
198
199 pub(crate) fn sample_block_header(rng: &mut TestRng) -> Header<CurrentNetwork> {
201 *crate::test_helpers::sample_genesis_block(rng).header()
202 }
203}