snarkvm_ledger_block/header/
merkle.rs1use super::*;
17
18impl<N: Network> Header<N> {
19 pub fn to_root(&self) -> Result<Field<N>> {
21 Ok(*self.to_tree()?.root())
22 }
23
24 pub fn to_path(&self, leaf: &HeaderLeaf<N>) -> Result<HeaderPath<N>> {
26 self.to_tree()?.prove(leaf.index() as usize, &leaf.to_bits_le())
28 }
29
30 pub fn to_leaf(&self, id: &Field<N>) -> Result<HeaderLeaf<N>> {
32 if id == &*self.previous_state_root {
34 Ok(HeaderLeaf::<N>::new(0, *self.previous_state_root))
35 }
36 else if id == &self.transactions_root {
38 Ok(HeaderLeaf::<N>::new(1, self.transactions_root))
39 }
40 else if id == &self.finalize_root {
42 Ok(HeaderLeaf::<N>::new(2, self.finalize_root))
43 }
44 else if id == &self.ratifications_root {
46 Ok(HeaderLeaf::<N>::new(3, self.ratifications_root))
47 }
48 else if id == &self.solutions_root {
50 Ok(HeaderLeaf::<N>::new(4, self.solutions_root))
51 }
52 else if id == &self.subdag_root {
54 Ok(HeaderLeaf::<N>::new(5, self.subdag_root))
55 }
56 else if id == &self.metadata.to_hash()? {
58 Ok(HeaderLeaf::<N>::new(7, *id))
59 }
60 else {
62 bail!("Non-existent block header leaf ID: {id}")
63 }
64 }
65
66 pub fn to_tree(&self) -> Result<HeaderTree<N>> {
68 let num_leaves = usize::pow(2, HEADER_DEPTH as u32);
70
71 let mut leaves: Vec<Vec<bool>> = Vec::with_capacity(num_leaves);
73 leaves.push(HeaderLeaf::<N>::new(0, *self.previous_state_root).to_bits_le());
74 leaves.push(HeaderLeaf::<N>::new(1, self.transactions_root).to_bits_le());
75 leaves.push(HeaderLeaf::<N>::new(2, self.finalize_root).to_bits_le());
76 leaves.push(HeaderLeaf::<N>::new(3, self.ratifications_root).to_bits_le());
77 leaves.push(HeaderLeaf::<N>::new(4, self.solutions_root).to_bits_le());
78 leaves.push(HeaderLeaf::<N>::new(5, self.subdag_root).to_bits_le());
79 leaves.push(HeaderLeaf::<N>::new(6, Field::zero()).to_bits_le());
80 leaves.push(HeaderLeaf::<N>::new(7, self.metadata.to_hash()?).to_bits_le());
81
82 ensure!(num_leaves == leaves.len(), "Incorrect number of leaves in the Merkle tree for the block header");
84
85 N::merkle_tree_bhp::<HEADER_DEPTH>(&leaves)
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use console::network::MainnetV0;
94
95 type CurrentNetwork = MainnetV0;
96
97 const ITERATIONS: u64 = 1_000;
98
99 fn check_path<N: Network>(header_path: HeaderPath<N>, root: Field<N>, leaf: &HeaderLeaf<N>) -> Result<()> {
100 assert!(N::verify_merkle_path_bhp(&header_path, &root, &leaf.to_bits_le()));
102
103 let expected_bytes = header_path.to_bytes_le()?;
105 assert_eq!(header_path, HeaderPath::<N>::read_le(&expected_bytes[..])?);
106 assert!(HeaderPath::<N>::read_le(&expected_bytes[1..]).is_err());
107 Ok(())
108 }
109
110 #[test]
111 fn test_merkle() -> Result<()> {
112 let rng = &mut TestRng::default();
113
114 for _ in 0..ITERATIONS {
115 let coinbase_target = u64::rand(rng);
116 let proof_target = rng.gen_range(0..coinbase_target);
117
118 let header = Header::<CurrentNetwork>::from(
119 Into::<<CurrentNetwork as Network>::StateRoot>::into(Field::rand(rng)),
120 Field::rand(rng),
121 Field::rand(rng),
122 Field::rand(rng),
123 Field::rand(rng),
124 Field::rand(rng),
125 Metadata::new(
126 CurrentNetwork::ID,
127 u64::rand(rng),
128 u32::rand(rng),
129 u128::rand(rng),
130 u128::rand(rng),
131 coinbase_target,
132 proof_target,
133 u64::rand(rng),
134 rng.gen_range(0..i64::MAX),
135 rng.gen_range(0..i64::MAX),
136 )?,
137 )?;
138
139 let root = header.to_root()?;
141
142 let leaf = header.to_leaf(&*header.previous_state_root())?;
144 assert_eq!(leaf.index(), 0);
145 check_path(header.to_path(&leaf)?, root, &leaf)?;
146
147 let leaf = header.to_leaf(&header.transactions_root())?;
149 assert_eq!(leaf.index(), 1);
150 check_path(header.to_path(&leaf)?, root, &leaf)?;
151
152 let leaf = header.to_leaf(&header.finalize_root())?;
154 assert_eq!(leaf.index(), 2);
155 check_path(header.to_path(&leaf)?, root, &leaf)?;
156
157 let leaf = header.to_leaf(&header.ratifications_root())?;
159 assert_eq!(leaf.index(), 3);
160 check_path(header.to_path(&leaf)?, root, &leaf)?;
161
162 let leaf = header.to_leaf(&header.solutions_root())?;
164 assert_eq!(leaf.index(), 4);
165 check_path(header.to_path(&leaf)?, root, &leaf)?;
166
167 let leaf = header.to_leaf(&header.subdag_root())?;
169 assert_eq!(leaf.index(), 5);
170 check_path(header.to_path(&leaf)?, root, &leaf)?;
171
172 let leaf = header.to_leaf(&CurrentNetwork::hash_bhp1024(&header.metadata().to_bits_le())?)?;
174 assert_eq!(leaf.index(), 7);
175 check_path(header.to_path(&leaf)?, root, &leaf)?;
176 }
177
178 Ok(())
179 }
180}