1use codec::Encode;
21use mmr_lib::helper;
22
23#[cfg(not(feature = "std"))]
24use alloc::vec::Vec;
25use sp_runtime::traits::{CheckedAdd, CheckedSub, Header, One};
26
27use crate::{Error, LeafIndex, NodeIndex};
28
29pub fn first_mmr_block_num<H: Header>(
31 best_block_num: H::Number,
32 mmr_leaf_count: LeafIndex,
33) -> Result<H::Number, Error> {
34 let mmr_blocks_count = mmr_leaf_count.try_into().map_err(|_| {
35 Error::InvalidNumericOp
36 .log_debug("The number of leaves couldn't be converted to a block number.")
37 })?;
38 best_block_num
39 .checked_sub(&mmr_blocks_count)
40 .and_then(|last_non_mmr_block| last_non_mmr_block.checked_add(&One::one()))
41 .ok_or_else(|| {
42 Error::InvalidNumericOp
43 .log_debug("The best block should be greater than the number of mmr blocks.")
44 })
45}
46
47pub fn block_num_to_leaf_index<H: Header>(
49 block_num: H::Number,
50 first_mmr_block_num: H::Number,
51) -> Result<LeafIndex, Error> {
52 let leaf_idx = block_num.checked_sub(&first_mmr_block_num).ok_or_else(|| {
53 Error::InvalidNumericOp
54 .log_debug("The provided block should be greater than the first mmr block.")
55 })?;
56
57 leaf_idx.try_into().map_err(|_| {
58 Error::InvalidNumericOp.log_debug("Couldn't convert the leaf index to `LeafIndex`.")
59 })
60}
61
62pub struct NodesUtils {
64 no_of_leaves: LeafIndex,
65}
66
67impl NodesUtils {
68 pub fn new(no_of_leaves: LeafIndex) -> Self {
70 Self { no_of_leaves }
71 }
72
73 pub fn number_of_peaks(&self) -> NodeIndex {
75 self.number_of_leaves().count_ones() as NodeIndex
76 }
77
78 pub fn number_of_leaves(&self) -> LeafIndex {
80 self.no_of_leaves
81 }
82
83 pub fn size(&self) -> NodeIndex {
85 2 * self.no_of_leaves - self.number_of_peaks()
86 }
87
88 pub fn leaf_index_that_added_node(node_index: NodeIndex) -> LeafIndex {
90 let rightmost_leaf_pos = Self::rightmost_leaf_node_index_from_pos(node_index);
91 Self::leaf_node_index_to_leaf_index(rightmost_leaf_pos)
92 }
93
94 fn leaf_node_index_to_leaf_index(pos: NodeIndex) -> LeafIndex {
96 if pos == 0 {
97 return 0
98 }
99 let peaks = helper::get_peaks(pos);
100 (pos + peaks.len() as u64) >> 1
101 }
102
103 pub fn leaf_index_to_leaf_node_index(leaf_index: NodeIndex) -> LeafIndex {
105 helper::leaf_index_to_pos(leaf_index)
106 }
107
108 fn rightmost_leaf_node_index_from_pos(pos: NodeIndex) -> NodeIndex {
111 pos - (helper::pos_height_in_tree(pos) as u64)
112 }
113
114 pub fn right_branch_ending_in_leaf(leaf_index: LeafIndex) -> Vec<NodeIndex> {
118 let pos = helper::leaf_index_to_pos(leaf_index);
119 let num_parents = leaf_index.trailing_ones() as u64;
120 return (pos..=pos + num_parents).collect()
121 }
122
123 pub fn node_temp_offchain_key<H: Header>(
127 prefix: &[u8],
128 pos: NodeIndex,
129 parent_hash: H::Hash,
130 ) -> Vec<u8> {
131 (prefix, pos, parent_hash).encode()
132 }
133
134 pub fn node_canon_offchain_key(prefix: &[u8], pos: NodeIndex) -> alloc::vec::Vec<u8> {
140 (prefix, pos).encode()
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147 use mmr_lib::helper::leaf_index_to_pos;
148
149 #[test]
150 fn should_calculate_node_index_from_leaf_index() {
151 for index in 0..100000 {
152 let pos = leaf_index_to_pos(index);
153 assert_eq!(NodesUtils::leaf_node_index_to_leaf_index(pos), index);
154 }
155 }
156
157 #[test]
158 fn should_calculate_right_branch_correctly() {
159 fn left_jump_sequence(leaf_index: LeafIndex) -> Vec<u64> {
160 let pos = leaf_index_to_pos(leaf_index);
161 let mut right_branch_ending_in_leaf = vec![pos];
162 let mut next_pos = pos + 1;
163 while mmr_lib::helper::pos_height_in_tree(next_pos) > 0 {
164 right_branch_ending_in_leaf.push(next_pos);
165 next_pos += 1;
166 }
167 right_branch_ending_in_leaf
168 }
169
170 for leaf_index in 0..100000 {
171 let pos = mmr_lib::helper::leaf_index_to_pos(leaf_index);
172 assert_eq!(NodesUtils::right_branch_ending_in_leaf(pos), left_jump_sequence(pos));
173 }
174 }
175
176 #[test]
177 fn should_calculate_rightmost_leaf_node_index_from_pos() {
178 for pos in 0..100000 {
179 let leaf_pos = NodesUtils::rightmost_leaf_node_index_from_pos(pos);
180 let leaf_index = NodesUtils::leaf_node_index_to_leaf_index(leaf_pos);
181 assert!(NodesUtils::right_branch_ending_in_leaf(leaf_index).contains(&pos));
182 }
183 }
184
185 #[test]
186 fn should_calculate_depth_correctly() {
187 assert_eq!(
188 vec![0, 1, 2, 3, 4, 9, 15, 21]
189 .into_iter()
190 .map(|n| NodesUtils::new(n).number_of_leaves())
191 .collect::<Vec<_>>(),
192 vec![0, 1, 2, 3, 4, 9, 15, 21]
193 );
194 }
195
196 #[test]
197 fn should_calculate_number_of_peaks_correctly() {
198 assert_eq!(
199 vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 21]
200 .into_iter()
201 .map(|n| NodesUtils::new(n).number_of_peaks())
202 .collect::<Vec<_>>(),
203 vec![0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 3]
204 );
205 }
206
207 #[test]
208 fn should_calculate_the_size_correctly() {
209 let leaves = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 21];
210 let sizes = vec![0, 1, 3, 4, 7, 8, 10, 11, 15, 16, 18, 19, 22, 23, 25, 26, 39];
211 assert_eq!(
212 leaves
213 .clone()
214 .into_iter()
215 .map(|n| NodesUtils::new(n).size())
216 .collect::<Vec<_>>(),
217 sizes.clone()
218 );
219 }
220}