miden-crypto/src/merkle/smt/full/tests.rs
src/merkle/smt/full/tests.rsRaw
1use super::{Felt, LeafIndex, NodeIndex, Rpo256, RpoDigest, Smt, SmtLeaf, EMPTY_WORD, SMT_DEPTH};
2use crate::{
3 merkle::{EmptySubtreeRoots, MerkleStore},
4 utils::{Deserializable, Serializable},
5 Word, ONE, WORD_SIZE,
6};
7use alloc::vec::Vec;
8
9// SMT
10// --------------------------------------------------------------------------------------------
11
12/// This test checks that inserting twice at the same key functions as expected. The test covers
13/// only the case where the key is alone in its leaf
14#[test]
15fn test_smt_insert_at_same_key() {
16 let mut smt = Smt::default();
17 let mut store: MerkleStore = MerkleStore::default();
18
19 assert_eq!(smt.root(), *EmptySubtreeRoots::entry(SMT_DEPTH, 0));
20
21 let key_1: RpoDigest = {
22 let raw = 0b_01101001_01101100_00011111_11111111_10010110_10010011_11100000_00000000_u64;
23
24 RpoDigest::from([ONE, ONE, ONE, Felt::new(raw)])
25 };
26 let key_1_index: NodeIndex = LeafIndex::<SMT_DEPTH>::from(key_1).into();
27
28 let value_1 = [ONE; WORD_SIZE];
29 let value_2 = [ONE + ONE; WORD_SIZE];
30
31 // Insert value 1 and ensure root is as expected
32 {
33 let leaf_node = build_empty_or_single_leaf_node(key_1, value_1);
34 let tree_root = store.set_node(smt.root(), key_1_index, leaf_node).unwrap().root;
35
36 let old_value_1 = smt.insert(key_1, value_1);
37 assert_eq!(old_value_1, EMPTY_WORD);
38
39 assert_eq!(smt.root(), tree_root);
40 }
41
42 // Insert value 2 and ensure root is as expected
43 {
44 let leaf_node = build_empty_or_single_leaf_node(key_1, value_2);
45 let tree_root = store.set_node(smt.root(), key_1_index, leaf_node).unwrap().root;
46
47 let old_value_2 = smt.insert(key_1, value_2);
48 assert_eq!(old_value_2, value_1);
49
50 assert_eq!(smt.root(), tree_root);
51 }
52}
53
54/// This test checks that inserting twice at the same key functions as expected. The test covers
55/// only the case where the leaf type is `SmtLeaf::Multiple`
56#[test]
57fn test_smt_insert_at_same_key_2() {
58 // The most significant u64 used for both keys (to ensure they map to the same leaf)
59 let key_msb: u64 = 42;
60
61 let key_already_present: RpoDigest =
62 RpoDigest::from([2_u32.into(), 2_u32.into(), 2_u32.into(), Felt::new(key_msb)]);
63 let key_already_present_index: NodeIndex =
64 LeafIndex::<SMT_DEPTH>::from(key_already_present).into();
65 let value_already_present = [ONE + ONE + ONE; WORD_SIZE];
66
67 let mut smt =
68 Smt::with_entries(core::iter::once((key_already_present, value_already_present))).unwrap();
69 let mut store: MerkleStore = {
70 let mut store = MerkleStore::default();
71
72 let leaf_node = build_empty_or_single_leaf_node(key_already_present, value_already_present);
73 store
74 .set_node(*EmptySubtreeRoots::entry(SMT_DEPTH, 0), key_already_present_index, leaf_node)
75 .unwrap();
76 store
77 };
78
79 let key_1: RpoDigest = RpoDigest::from([ONE, ONE, ONE, Felt::new(key_msb)]);
80 let key_1_index: NodeIndex = LeafIndex::<SMT_DEPTH>::from(key_1).into();
81
82 assert_eq!(key_1_index, key_already_present_index);
83
84 let value_1 = [ONE; WORD_SIZE];
85 let value_2 = [ONE + ONE; WORD_SIZE];
86
87 // Insert value 1 and ensure root is as expected
88 {
89 // Note: key_1 comes first because it is smaller
90 let leaf_node = build_multiple_leaf_node(&[
91 (key_1, value_1),
92 (key_already_present, value_already_present),
93 ]);
94 let tree_root = store.set_node(smt.root(), key_1_index, leaf_node).unwrap().root;
95
96 let old_value_1 = smt.insert(key_1, value_1);
97 assert_eq!(old_value_1, EMPTY_WORD);
98
99 assert_eq!(smt.root(), tree_root);
100 }
101
102 // Insert value 2 and ensure root is as expected
103 {
104 let leaf_node = build_multiple_leaf_node(&[
105 (key_1, value_2),
106 (key_already_present, value_already_present),
107 ]);
108 let tree_root = store.set_node(smt.root(), key_1_index, leaf_node).unwrap().root;
109
110 let old_value_2 = smt.insert(key_1, value_2);
111 assert_eq!(old_value_2, value_1);
112
113 assert_eq!(smt.root(), tree_root);
114 }
115}
116
117/// This test ensures that the root of the tree is as expected when we add/remove 3 items at 3
118/// different keys. This also tests that the merkle paths produced are as expected.
119#[test]
120fn test_smt_insert_and_remove_multiple_values() {
121 fn insert_values_and_assert_path(
122 smt: &mut Smt,
123 store: &mut MerkleStore,
124 key_values: &[(RpoDigest, Word)],
125 ) {
126 for &(key, value) in key_values {
127 let key_index: NodeIndex = LeafIndex::<SMT_DEPTH>::from(key).into();
128
129 let leaf_node = build_empty_or_single_leaf_node(key, value);
130 let tree_root = store.set_node(smt.root(), key_index, leaf_node).unwrap().root;
131
132 let _ = smt.insert(key, value);
133
134 assert_eq!(smt.root(), tree_root);
135
136 let expected_path = store.get_path(tree_root, key_index).unwrap();
137 assert_eq!(smt.open(&key).into_parts().0, expected_path.path);
138 }
139 }
140 let mut smt = Smt::default();
141 let mut store: MerkleStore = MerkleStore::default();
142
143 assert_eq!(smt.root(), *EmptySubtreeRoots::entry(SMT_DEPTH, 0));
144
145 let key_1: RpoDigest = {
146 let raw = 0b_01101001_01101100_00011111_11111111_10010110_10010011_11100000_00000000_u64;
147
148 RpoDigest::from([ONE, ONE, ONE, Felt::new(raw)])
149 };
150
151 let key_2: RpoDigest = {
152 let raw = 0b_11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111_u64;
153
154 RpoDigest::from([ONE, ONE, ONE, Felt::new(raw)])
155 };
156
157 let key_3: RpoDigest = {
158 let raw = 0b_00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000_u64;
159
160 RpoDigest::from([ONE, ONE, ONE, Felt::new(raw)])
161 };
162
163 let value_1 = [ONE; WORD_SIZE];
164 let value_2 = [ONE + ONE; WORD_SIZE];
165 let value_3 = [ONE + ONE + ONE; WORD_SIZE];
166
167 // Insert values in the tree
168 let key_values = [(key_1, value_1), (key_2, value_2), (key_3, value_3)];
169 insert_values_and_assert_path(&mut smt, &mut store, &key_values);
170
171 // Remove values from the tree
172 let key_empty_values = [(key_1, EMPTY_WORD), (key_2, EMPTY_WORD), (key_3, EMPTY_WORD)];
173 insert_values_and_assert_path(&mut smt, &mut store, &key_empty_values);
174
175 let empty_root = *EmptySubtreeRoots::entry(SMT_DEPTH, 0);
176 assert_eq!(smt.root(), empty_root);
177
178 // an empty tree should have no leaves or inner nodes
179 assert!(smt.leaves.is_empty());
180 assert!(smt.inner_nodes.is_empty());
181}
182
183/// This tests that inserting the empty value does indeed remove the key-value contained at the
184/// leaf. We insert & remove 3 values at the same leaf to ensure that all cases are covered (empty,
185/// single, multiple).
186#[test]
187fn test_smt_removal() {
188 let mut smt = Smt::default();
189
190 let raw = 0b_01101001_01101100_00011111_11111111_10010110_10010011_11100000_00000000_u64;
191
192 let key_1: RpoDigest = RpoDigest::from([ONE, ONE, ONE, Felt::new(raw)]);
193 let key_2: RpoDigest =
194 RpoDigest::from([2_u32.into(), 2_u32.into(), 2_u32.into(), Felt::new(raw)]);
195 let key_3: RpoDigest =
196 RpoDigest::from([3_u32.into(), 3_u32.into(), 3_u32.into(), Felt::new(raw)]);
197
198 let value_1 = [ONE; WORD_SIZE];
199 let value_2 = [2_u32.into(); WORD_SIZE];
200 let value_3: [Felt; 4] = [3_u32.into(); WORD_SIZE];
201
202 // insert key-value 1
203 {
204 let old_value_1 = smt.insert(key_1, value_1);
205 assert_eq!(old_value_1, EMPTY_WORD);
206
207 assert_eq!(smt.get_leaf(&key_1), SmtLeaf::Single((key_1, value_1)));
208 }
209
210 // insert key-value 2
211 {
212 let old_value_2 = smt.insert(key_2, value_2);
213 assert_eq!(old_value_2, EMPTY_WORD);
214
215 assert_eq!(
216 smt.get_leaf(&key_2),
217 SmtLeaf::Multiple(vec![(key_1, value_1), (key_2, value_2)])
218 );
219 }
220
221 // insert key-value 3
222 {
223 let old_value_3 = smt.insert(key_3, value_3);
224 assert_eq!(old_value_3, EMPTY_WORD);
225
226 assert_eq!(
227 smt.get_leaf(&key_3),
228 SmtLeaf::Multiple(vec![(key_1, value_1), (key_2, value_2), (key_3, value_3)])
229 );
230 }
231
232 // remove key 3
233 {
234 let old_value_3 = smt.insert(key_3, EMPTY_WORD);
235 assert_eq!(old_value_3, value_3);
236
237 assert_eq!(
238 smt.get_leaf(&key_3),
239 SmtLeaf::Multiple(vec![(key_1, value_1), (key_2, value_2)])
240 );
241 }
242
243 // remove key 2
244 {
245 let old_value_2 = smt.insert(key_2, EMPTY_WORD);
246 assert_eq!(old_value_2, value_2);
247
248 assert_eq!(smt.get_leaf(&key_2), SmtLeaf::Single((key_1, value_1)));
249 }
250
251 // remove key 1
252 {
253 let old_value_1 = smt.insert(key_1, EMPTY_WORD);
254 assert_eq!(old_value_1, value_1);
255
256 assert_eq!(smt.get_leaf(&key_1), SmtLeaf::new_empty(key_1.into()));
257 }
258}
259
260/// Tests that 2 key-value pairs stored in the same leaf have the same path
261#[test]
262fn test_smt_path_to_keys_in_same_leaf_are_equal() {
263 let raw = 0b_01101001_01101100_00011111_11111111_10010110_10010011_11100000_00000000_u64;
264
265 let key_1: RpoDigest = RpoDigest::from([ONE, ONE, ONE, Felt::new(raw)]);
266 let key_2: RpoDigest =
267 RpoDigest::from([2_u32.into(), 2_u32.into(), 2_u32.into(), Felt::new(raw)]);
268
269 let value_1 = [ONE; WORD_SIZE];
270 let value_2 = [2_u32.into(); WORD_SIZE];
271
272 let smt = Smt::with_entries([(key_1, value_1), (key_2, value_2)]).unwrap();
273
274 assert_eq!(smt.open(&key_1), smt.open(&key_2));
275}
276
277/// Tests that an empty leaf hashes to the empty word
278#[test]
279fn test_empty_leaf_hash() {
280 let smt = Smt::default();
281
282 let leaf = smt.get_leaf(&RpoDigest::default());
283 assert_eq!(leaf.hash(), EMPTY_WORD.into());
284}
285
286/// Tests that `get_value()` works as expected
287#[test]
288fn test_smt_get_value() {
289 let key_1: RpoDigest = RpoDigest::from([ONE, ONE, ONE, ONE]);
290 let key_2: RpoDigest = RpoDigest::from([2_u32, 2_u32, 2_u32, 2_u32]);
291
292 let value_1 = [ONE; WORD_SIZE];
293 let value_2 = [2_u32.into(); WORD_SIZE];
294
295 let smt = Smt::with_entries([(key_1, value_1), (key_2, value_2)]).unwrap();
296
297 let returned_value_1 = smt.get_value(&key_1);
298 let returned_value_2 = smt.get_value(&key_2);
299
300 assert_eq!(value_1, returned_value_1);
301 assert_eq!(value_2, returned_value_2);
302
303 // Check that a key with no inserted value returns the empty word
304 let key_no_value = RpoDigest::from([42_u32, 42_u32, 42_u32, 42_u32]);
305
306 assert_eq!(EMPTY_WORD, smt.get_value(&key_no_value));
307}
308
309/// Tests that `entries()` works as expected
310#[test]
311fn test_smt_entries() {
312 let key_1: RpoDigest = RpoDigest::from([ONE, ONE, ONE, ONE]);
313 let key_2: RpoDigest = RpoDigest::from([2_u32, 2_u32, 2_u32, 2_u32]);
314
315 let value_1 = [ONE; WORD_SIZE];
316 let value_2 = [2_u32.into(); WORD_SIZE];
317
318 let smt = Smt::with_entries([(key_1, value_1), (key_2, value_2)]).unwrap();
319
320 let mut entries = smt.entries();
321
322 // Note: for simplicity, we assume the order `(k1,v1), (k2,v2)`. If a new implementation
323 // switches the order, it is OK to modify the order here as well.
324 assert_eq!(&(key_1, value_1), entries.next().unwrap());
325 assert_eq!(&(key_2, value_2), entries.next().unwrap());
326 assert!(entries.next().is_none());
327}
328
329// SMT LEAF
330// --------------------------------------------------------------------------------------------
331
332#[test]
333fn test_empty_smt_leaf_serialization() {
334 let empty_leaf = SmtLeaf::new_empty(LeafIndex::new_max_depth(42));
335
336 let mut serialized = empty_leaf.to_bytes();
337 // extend buffer with random bytes
338 serialized.extend([1, 2, 3, 4, 5]);
339 let deserialized = SmtLeaf::read_from_bytes(&serialized).unwrap();
340
341 assert_eq!(empty_leaf, deserialized);
342}
343
344#[test]
345fn test_single_smt_leaf_serialization() {
346 let single_leaf = SmtLeaf::new_single(
347 RpoDigest::from([10_u32, 11_u32, 12_u32, 13_u32]),
348 [1_u32.into(), 2_u32.into(), 3_u32.into(), 4_u32.into()],
349 );
350
351 let mut serialized = single_leaf.to_bytes();
352 // extend buffer with random bytes
353 serialized.extend([1, 2, 3, 4, 5]);
354 let deserialized = SmtLeaf::read_from_bytes(&serialized).unwrap();
355
356 assert_eq!(single_leaf, deserialized);
357}
358
359#[test]
360fn test_multiple_smt_leaf_serialization_success() {
361 let multiple_leaf = SmtLeaf::new_multiple(vec![
362 (
363 RpoDigest::from([10_u32, 11_u32, 12_u32, 13_u32]),
364 [1_u32.into(), 2_u32.into(), 3_u32.into(), 4_u32.into()],
365 ),
366 (
367 RpoDigest::from([100_u32, 101_u32, 102_u32, 13_u32]),
368 [11_u32.into(), 12_u32.into(), 13_u32.into(), 14_u32.into()],
369 ),
370 ])
371 .unwrap();
372
373 let mut serialized = multiple_leaf.to_bytes();
374 // extend buffer with random bytes
375 serialized.extend([1, 2, 3, 4, 5]);
376 let deserialized = SmtLeaf::read_from_bytes(&serialized).unwrap();
377
378 assert_eq!(multiple_leaf, deserialized);
379}
380
381// HELPERS
382// --------------------------------------------------------------------------------------------
383
384fn build_empty_or_single_leaf_node(key: RpoDigest, value: Word) -> RpoDigest {
385 if value == EMPTY_WORD {
386 SmtLeaf::new_empty(key.into()).hash()
387 } else {
388 SmtLeaf::Single((key, value)).hash()
389 }
390}
391
392fn build_multiple_leaf_node(kv_pairs: &[(RpoDigest, Word)]) -> RpoDigest {
393 let elements: Vec<Felt> = kv_pairs
394 .iter()
395 .flat_map(|(key, value)| {
396 let key_elements = key.into_iter();
397 let value_elements = (*value).into_iter();
398
399 key_elements.chain(value_elements)
400 })
401 .collect();
402
403 Rpo256::hash_elements(&elements)
404}