1use std::fmt::Debug;
2
3use cosmwasm_std::{Empty, Order, Storage};
4use cw_storage_plus::{Bound, Item, Map, PrimaryKey};
5use serde::{de::DeserializeOwned, Serialize};
6
7use crate::{Hasher, MerkleTree, MerkleTreeError};
8
9use super::SparseMerkleTree;
10
11pub struct SparseMerkleTreeWithHistoryBounded<
13 'a,
14 L: Serialize + DeserializeOwned + Clone + Debug + PartialEq + PrimaryKey<'a>,
15 H: Hasher<L>,
16 const HISTORY_LEVEL: u32,
17> {
18 pub history_index: Item<'a, u32>,
19 pub root_history: Map<'a, L, Empty>,
20 pub root_index: Map<'a, u32, L>,
21 pub tree: SparseMerkleTree<'a, L, H>,
22}
23
24impl<
25 'a,
26 L: Serialize + DeserializeOwned + Clone + Debug + PartialEq + PrimaryKey<'a>,
27 H: Hasher<L>,
28 const HISTORY_LEVEL: u32,
29 > SparseMerkleTreeWithHistoryBounded<'a, L, H, HISTORY_LEVEL>
30{
31 pub const fn new(
32 hashes_ns: &'a str,
33 leafs_ns: &'a str,
34 level_ns: &'a str,
35 root_ns: &'a str,
36 root_history_ns: &'a str,
37 root_index_ns: &'a str,
38 history_index_ns: &'a str,
39 ) -> Self {
40 Self {
41 history_index: Item::new(history_index_ns),
42 root_history: Map::new(root_history_ns),
43 root_index: Map::new(root_index_ns),
44 tree: SparseMerkleTree::new(hashes_ns, leafs_ns, level_ns, root_ns),
45 }
46 }
47
48 pub fn update_history_level(&self, storage: &mut dyn Storage) -> Result<(), MerkleTreeError> {
51 let updated_idx = self.history_index.may_load(storage)?.unwrap_or_default() % HISTORY_LEVEL;
52 self.history_index.save(storage, &updated_idx)?;
53
54 let mut root_range = self
55 .root_index
56 .range(
57 storage,
58 Some(Bound::inclusive(HISTORY_LEVEL)),
59 None,
60 Order::Ascending,
61 )
62 .collect::<Vec<_>>()
63 .into_iter();
64 while let Some(Ok((idx, root))) = root_range.next() {
65 self.root_index.remove(storage, idx);
66 self.root_history.remove(storage, root);
67 }
68
69 Ok(())
70 }
71}
72
73impl<
74 'a,
75 L: Serialize + DeserializeOwned + Clone + Debug + PartialEq + PrimaryKey<'a>,
76 H: Hasher<L>,
77 const HISTORY_LEVEL: u32,
78 > MerkleTree<L, H> for SparseMerkleTreeWithHistoryBounded<'a, L, H, HISTORY_LEVEL>
79{
80 fn init(
81 &self,
82 storage: &mut dyn Storage,
83 level: u8,
84 default_leaf: L,
85 hasher: &H,
86 ) -> Result<(), MerkleTreeError> {
87 self.tree.init(storage, level, default_leaf, hasher)
88 }
89
90 fn is_valid_root(&self, storage: &dyn Storage, root: &L) -> Result<bool, MerkleTreeError> {
91 Ok(self.root_history.has(storage, root.clone()))
92 }
93
94 fn insert(
95 &self,
96 storage: &mut dyn Storage,
97 leaf: L,
98 hasher: &H,
99 ) -> Result<(u64, L), MerkleTreeError> {
100 let (index, latest_root) = self.tree.insert(storage, leaf, hasher)?;
101 let cur_idx = self.history_index.may_load(storage)?.unwrap_or_default();
102 let next_idx = (cur_idx + 1) % HISTORY_LEVEL;
103
104 if let Some(root) = self.root_index.may_load(storage, next_idx)? {
106 self.root_history.remove(storage, root);
107 }
108
109 self.root_history
111 .save(storage, latest_root.clone(), &Empty {})?;
112 self.root_index.save(storage, next_idx, &latest_root)?;
113
114 self.history_index.save(storage, &next_idx)?;
116
117 Ok((index, latest_root))
118 }
119
120 fn get_latest_root(&self, storage: &dyn Storage) -> Result<L, MerkleTreeError> {
121 self.tree.get_latest_root(storage)
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use std::error::Error;
128
129 use cosmwasm_std::{testing::MockStorage, Uint256};
130
131 use crate::{test_utils::Blake2, Hasher, MerkleTree};
132
133 use super::SparseMerkleTreeWithHistoryBounded;
134
135 const TREE: SparseMerkleTreeWithHistoryBounded<Vec<u8>, Blake2, 5> =
136 SparseMerkleTreeWithHistoryBounded::new(
137 "hashes",
138 "leafs",
139 "level",
140 "zeros",
141 "root_history",
142 "root_index",
143 "history_index",
144 );
145 const ZERO: [u8; 32] = [
146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
147 0, 0,
148 ];
149
150 #[test]
151 fn init() -> Result<(), Box<dyn Error>> {
152 let mut storage = MockStorage::new();
153 let zero_vec = ZERO.to_vec();
154
155 TREE.init(
156 &mut storage,
157 20,
158 Blake2.hash_two(&zero_vec, &zero_vec)?,
159 &Blake2,
160 )?;
161
162 assert_eq!(
163 TREE.get_latest_root(&storage)?,
164 [
165 20, 114, 250, 18, 41, 94, 49, 107, 184, 78, 231, 47, 187, 225, 122, 14, 76, 178,
166 156, 226, 121, 99, 103, 48, 22, 79, 157, 174, 92, 246, 92, 50
167 ]
168 );
169
170 Ok(())
171 }
172
173 #[test]
174 fn insert() -> Result<(), Box<dyn Error>> {
175 let mut storage = MockStorage::new();
176 let zero_vec = ZERO.to_vec();
177 let one_vec = Uint256::one().to_be_bytes().to_vec();
178
179 TREE.init(
180 &mut storage,
181 20,
182 Blake2.hash_two(&zero_vec, &zero_vec)?,
183 &Blake2,
184 )?;
185
186 let leaf = Blake2.hash_two(&one_vec, &one_vec)?;
187
188 let (index, new_root) = TREE.insert(&mut storage, leaf.clone(), &Blake2)?;
189
190 assert_eq!(index, 0);
191 assert_eq!(
192 new_root,
193 [
194 144, 77, 181, 73, 235, 223, 13, 204, 30, 18, 199, 252, 182, 160, 89, 248, 240, 219,
195 173, 150, 189, 114, 165, 70, 40, 159, 110, 9, 165, 185, 17, 229
196 ]
197 );
198 assert_eq!(new_root, TREE.get_latest_root(&storage)?);
199 assert!(TREE.is_valid_root(&storage, &new_root)?);
200
201 let (index, new_root) = TREE.insert(&mut storage, leaf, &Blake2)?;
202
203 assert_eq!(index, 1);
204 assert_eq!(
205 new_root,
206 [
207 69, 102, 154, 15, 149, 187, 157, 26, 123, 248, 50, 67, 177, 207, 6, 143, 94, 80,
208 242, 17, 127, 26, 94, 197, 222, 220, 255, 245, 136, 20, 62, 132
209 ]
210 );
211 assert_eq!(new_root, TREE.get_latest_root(&storage)?);
212 assert!(TREE.is_valid_root(&storage, &new_root)?);
213
214 Ok(())
215 }
216
217 #[test]
218 fn root_history() -> Result<(), Box<dyn Error>> {
219 let mut storage = MockStorage::new();
220 let zero_vec = ZERO.to_vec();
221 let one_vec = Uint256::one().to_be_bytes().to_vec();
222
223 TREE.init(
224 &mut storage,
225 20,
226 Blake2.hash_two(&zero_vec, &zero_vec)?,
227 &Blake2,
228 )?;
229
230 let leaf = Blake2.hash_two(&one_vec, &one_vec)?;
231
232 let (_, very_old_root) = TREE.insert(&mut storage, leaf.clone(), &Blake2)?;
233 let (_, old_root) = TREE.insert(&mut storage, leaf.clone(), &Blake2)?;
234 let _ = TREE.insert(&mut storage, leaf.clone(), &Blake2)?;
235 let _ = TREE.insert(&mut storage, leaf.clone(), &Blake2)?;
236 let _ = TREE.insert(&mut storage, leaf.clone(), &Blake2)?;
237 let (_, new_root) = TREE.insert(&mut storage, leaf, &Blake2)?;
238
239 assert!(!TREE.is_valid_root(&storage, &very_old_root)?);
240 assert!(TREE.is_valid_root(&storage, &old_root)?);
241 assert!(TREE.is_valid_root(&storage, &new_root)?);
242
243 Ok(())
244 }
245}