1use alloc::boxed::Box;
2use alloc::string::ToString;
3use alloc::vec::Vec;
4
5use miden_core::utils::{ByteReader, ByteWriter, Deserializable, Serializable};
6use miden_crypto::merkle::{LeafIndex, MerkleError, MutationSet, Smt, SmtLeaf, SmtProof};
7use miden_processor::{DeserializationError, SMT_DEPTH};
8
9use crate::Word;
10use crate::account::{AccountId, AccountIdPrefix};
11use crate::block::AccountWitness;
12use crate::errors::AccountTreeError;
13
14const KEY_PREFIX_IDX: usize = 3;
20const KEY_SUFFIX_IDX: usize = 2;
21
22pub fn account_id_to_smt_key(account_id: AccountId) -> Word {
26 let mut key = Word::empty();
27 key[KEY_SUFFIX_IDX] = account_id.suffix();
28 key[KEY_PREFIX_IDX] = account_id.prefix().as_felt();
29 key
30}
31
32pub fn smt_key_to_account_id(key: Word) -> AccountId {
39 AccountId::try_from([key[KEY_PREFIX_IDX], key[KEY_SUFFIX_IDX]])
40 .expect("account tree should only contain valid IDs")
41}
42
43pub trait AccountTreeBackend: Sized {
53 type Error: core::error::Error + Send + 'static;
54
55 fn num_leaves(&self) -> usize;
57
58 fn leaves<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = (LeafIndex<SMT_DEPTH>, SmtLeaf)>>;
60
61 fn open(&self, key: &Word) -> SmtProof;
63
64 fn apply_mutations(
66 &mut self,
67 set: MutationSet<SMT_DEPTH, Word, Word>,
68 ) -> Result<(), Self::Error>;
69
70 fn apply_mutations_with_reversion(
74 &mut self,
75 set: MutationSet<SMT_DEPTH, Word, Word>,
76 ) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error>;
77
78 fn compute_mutations(
80 &self,
81 updates: Vec<(Word, Word)>,
82 ) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error>;
83
84 fn insert(&mut self, key: Word, value: Word) -> Result<Word, Self::Error>;
86
87 fn get_value(&self, key: &Word) -> Word;
89
90 fn get_leaf(&self, key: &Word) -> SmtLeaf;
92
93 fn root(&self) -> Word;
95}
96
97impl AccountTreeBackend for Smt {
98 type Error = MerkleError;
99
100 fn num_leaves(&self) -> usize {
101 Smt::num_leaves(self)
102 }
103
104 fn leaves<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = (LeafIndex<SMT_DEPTH>, SmtLeaf)>> {
105 Box::new(Smt::leaves(self).map(|(idx, leaf)| (idx, leaf.clone())))
106 }
107
108 fn open(&self, key: &Word) -> SmtProof {
109 Smt::open(self, key)
110 }
111
112 fn apply_mutations(
113 &mut self,
114 set: MutationSet<SMT_DEPTH, Word, Word>,
115 ) -> Result<(), Self::Error> {
116 Smt::apply_mutations(self, set)
117 }
118
119 fn apply_mutations_with_reversion(
120 &mut self,
121 set: MutationSet<SMT_DEPTH, Word, Word>,
122 ) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error> {
123 Smt::apply_mutations_with_reversion(self, set)
124 }
125
126 fn compute_mutations(
127 &self,
128 updates: Vec<(Word, Word)>,
129 ) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error> {
130 Smt::compute_mutations(self, updates)
131 }
132
133 fn insert(&mut self, key: Word, value: Word) -> Result<Word, Self::Error> {
134 Smt::insert(self, key, value)
135 }
136
137 fn get_value(&self, key: &Word) -> Word {
138 Smt::get_value(self, key)
139 }
140
141 fn get_leaf(&self, key: &Word) -> SmtLeaf {
142 Smt::get_leaf(self, key)
143 }
144
145 fn root(&self) -> Word {
146 Smt::root(self)
147 }
148}
149
150#[cfg(feature = "std")]
151use miden_crypto::merkle::{LargeSmt, LargeSmtError, SmtStorage};
152#[cfg(feature = "std")]
153fn large_smt_error_to_merkle_error(err: LargeSmtError) -> MerkleError {
154 match err {
155 LargeSmtError::Storage(storage_err) => {
156 panic!("Storage error encountered: {:?}", storage_err)
157 },
158 LargeSmtError::Merkle(merkle_err) => merkle_err,
159 }
160}
161
162#[cfg(feature = "std")]
163impl<Backend> AccountTreeBackend for LargeSmt<Backend>
164where
165 Backend: SmtStorage,
166{
167 type Error = MerkleError;
168
169 fn num_leaves(&self) -> usize {
170 LargeSmt::num_leaves(self).map_err(large_smt_error_to_merkle_error).unwrap_or(0)
173 }
174
175 fn leaves<'a>(&'a self) -> Box<dyn 'a + Iterator<Item = (LeafIndex<SMT_DEPTH>, SmtLeaf)>> {
176 Box::new(LargeSmt::leaves(self).expect("Only IO can error out here"))
177 }
178
179 fn open(&self, key: &Word) -> SmtProof {
180 LargeSmt::open(self, key)
181 }
182
183 fn apply_mutations(
184 &mut self,
185 set: MutationSet<SMT_DEPTH, Word, Word>,
186 ) -> Result<(), Self::Error> {
187 LargeSmt::apply_mutations(self, set).map_err(large_smt_error_to_merkle_error)
188 }
189
190 fn apply_mutations_with_reversion(
191 &mut self,
192 set: MutationSet<SMT_DEPTH, Word, Word>,
193 ) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error> {
194 LargeSmt::apply_mutations_with_reversion(self, set).map_err(large_smt_error_to_merkle_error)
195 }
196
197 fn compute_mutations(
198 &self,
199 updates: Vec<(Word, Word)>,
200 ) -> Result<MutationSet<SMT_DEPTH, Word, Word>, Self::Error> {
201 LargeSmt::compute_mutations(self, updates).map_err(large_smt_error_to_merkle_error)
202 }
203
204 fn insert(&mut self, key: Word, value: Word) -> Result<Word, Self::Error> {
205 LargeSmt::insert(self, key, value)
206 }
207
208 fn get_value(&self, key: &Word) -> Word {
209 LargeSmt::get_value(self, key)
210 }
211
212 fn get_leaf(&self, key: &Word) -> SmtLeaf {
213 LargeSmt::get_leaf(self, key)
214 }
215
216 fn root(&self) -> Word {
217 LargeSmt::root(self).map_err(large_smt_error_to_merkle_error).unwrap()
218 }
219}
220
221#[derive(Debug, Clone, PartialEq, Eq)]
230pub struct AccountTree<S = Smt> {
231 smt: S,
232}
233
234impl<S> Default for AccountTree<S>
235where
236 S: Default,
237{
238 fn default() -> Self {
239 Self { smt: Default::default() }
240 }
241}
242
243impl<S> AccountTree<S>
244where
245 S: AccountTreeBackend<Error = MerkleError>,
246{
247 pub const DEPTH: u8 = SMT_DEPTH;
252
253 pub(super) const KEY_SUFFIX_IDX: usize = 2;
255 pub(super) const KEY_PREFIX_IDX: usize = 3;
257
258 pub fn new(smt: S) -> Result<Self, AccountTreeError> {
271 for (_leaf_idx, leaf) in smt.leaves() {
272 match leaf {
273 SmtLeaf::Empty(_) => {
274 continue;
276 },
277 SmtLeaf::Single((key, _)) => {
278 Self::smt_key_to_id(key);
280 },
281 SmtLeaf::Multiple(entries) => {
282 if let Some((key, _)) = entries.first() {
285 let account_id = Self::smt_key_to_id(*key);
286 return Err(AccountTreeError::DuplicateIdPrefix {
287 duplicate_prefix: account_id.prefix(),
288 });
289 }
290 },
291 }
292 }
293
294 Ok(Self::new_unchecked(smt))
295 }
296
297 pub fn new_unchecked(smt: S) -> Self {
308 AccountTree { smt }
309 }
310
311 pub fn open(&self, account_id: AccountId) -> AccountWitness {
323 let key = Self::id_to_smt_key(account_id);
324 let proof = self.smt.open(&key);
325
326 AccountWitness::from_smt_proof(account_id, proof)
327 }
328
329 pub fn get(&self, account_id: AccountId) -> Word {
331 let key = Self::id_to_smt_key(account_id);
332 self.smt.get_value(&key)
333 }
334
335 pub fn root(&self) -> Word {
337 self.smt.root()
338 }
339
340 pub fn contains_account_id_prefix(&self, account_id_prefix: AccountIdPrefix) -> bool {
342 let key = Self::id_prefix_to_smt_key(account_id_prefix);
343 let is_empty = matches!(self.smt.get_leaf(&key), SmtLeaf::Empty(_));
344 !is_empty
345 }
346
347 pub fn num_accounts(&self) -> usize {
349 self.smt.num_leaves()
352 }
353
354 pub fn account_commitments(&self) -> impl Iterator<Item = (AccountId, Word)> {
356 self.smt.leaves().map(|(_leaf_idx, leaf)| {
357 let SmtLeaf::Single((key, commitment)) = leaf else {
361 unreachable!("empty and multiple variant should never be encountered")
362 };
363
364 (
365 AccountId::try_from([key[Self::KEY_PREFIX_IDX], key[Self::KEY_SUFFIX_IDX]])
367 .expect("account tree should only contain valid IDs"),
368 commitment,
369 )
370 })
371 }
372
373 pub fn compute_mutations(
391 &self,
392 account_commitments: impl IntoIterator<Item = (AccountId, Word)>,
393 ) -> Result<AccountMutationSet, AccountTreeError> {
394 let mutation_set = self
395 .smt
396 .compute_mutations(Vec::from_iter(
397 account_commitments
398 .into_iter()
399 .map(|(id, commitment)| (Self::id_to_smt_key(id), commitment)),
400 ))
401 .map_err(AccountTreeError::ComputeMutations)?;
402
403 for id_key in mutation_set.new_pairs().keys() {
404 match self.smt.get_leaf(id_key) {
406 SmtLeaf::Empty(_) => (),
408 SmtLeaf::Single((existing_key, _)) => {
409 if existing_key != *id_key {
412 return Err(AccountTreeError::DuplicateIdPrefix {
413 duplicate_prefix: Self::smt_key_to_id(*id_key).prefix(),
414 });
415 }
416 },
417 SmtLeaf::Multiple(_) => {
418 unreachable!(
419 "account tree should never contain duplicate ID prefixes and therefore never a multiple leaf"
420 )
421 },
422 }
423 }
424
425 Ok(AccountMutationSet::new(mutation_set))
426 }
427
428 pub fn insert(
442 &mut self,
443 account_id: AccountId,
444 state_commitment: Word,
445 ) -> Result<Word, AccountTreeError> {
446 let key = Self::id_to_smt_key(account_id);
447 let prev_value = self.smt.insert(key, state_commitment)
450 .expect("account tree should always have a single value per key, and hence cannot exceed the maximum leaf number");
451
452 if self.smt.get_leaf(&key).num_entries() >= 2 {
455 return Err(AccountTreeError::DuplicateIdPrefix {
456 duplicate_prefix: account_id.prefix(),
457 });
458 }
459
460 Ok(prev_value)
461 }
462
463 pub fn apply_mutations(
470 &mut self,
471 mutations: AccountMutationSet,
472 ) -> Result<(), AccountTreeError> {
473 self.smt
474 .apply_mutations(mutations.into_mutation_set())
475 .map_err(AccountTreeError::ApplyMutations)
476 }
477
478 pub fn apply_mutations_with_reversion(
488 &mut self,
489 mutations: AccountMutationSet,
490 ) -> Result<AccountMutationSet, AccountTreeError> {
491 let reversion = self
492 .smt
493 .apply_mutations_with_reversion(mutations.into_mutation_set())
494 .map_err(AccountTreeError::ApplyMutations)?;
495 Ok(AccountMutationSet::new(reversion))
496 }
497
498 pub(super) fn id_to_smt_key(account_id: AccountId) -> Word {
503 let mut key = Word::empty();
506 key[Self::KEY_SUFFIX_IDX] = account_id.suffix();
507 key[Self::KEY_PREFIX_IDX] = account_id.prefix().as_felt();
508
509 key
510 }
511
512 fn id_prefix_to_smt_key(account_id: AccountIdPrefix) -> Word {
514 let mut key = Word::empty();
517 key[Self::KEY_PREFIX_IDX] = account_id.as_felt();
518
519 key
520 }
521
522 pub(super) fn smt_key_to_id(key: Word) -> AccountId {
530 AccountId::try_from([key[Self::KEY_PREFIX_IDX], key[Self::KEY_SUFFIX_IDX]])
531 .expect("account tree should only contain valid IDs")
532 }
533}
534
535impl AccountTree<Smt> {
539 pub fn with_entries<I>(
551 entries: impl IntoIterator<Item = (AccountId, Word), IntoIter = I>,
552 ) -> Result<Self, AccountTreeError>
553 where
554 I: ExactSizeIterator<Item = (AccountId, Word)>,
555 {
556 let smt = Smt::with_entries(
558 entries
559 .into_iter()
560 .map(|(id, commitment)| (account_id_to_smt_key(id), commitment)),
561 )
562 .map_err(|err| {
563 let MerkleError::DuplicateValuesForIndex(leaf_idx) = err else {
564 unreachable!("the only error returned by Smt::with_entries is of this type");
565 };
566
567 AccountTreeError::DuplicateStateCommitments {
570 prefix: AccountIdPrefix::new_unchecked(
571 crate::Felt::try_from(leaf_idx).expect("leaf index should be a valid felt"),
572 ),
573 }
574 })?;
575
576 AccountTree::new(smt)
577 }
578}
579
580impl Serializable for AccountTree {
584 fn write_into<W: ByteWriter>(&self, target: &mut W) {
585 self.account_commitments().collect::<Vec<_>>().write_into(target);
586 }
587}
588
589impl Deserializable for AccountTree {
590 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
591 let entries = Vec::<(AccountId, Word)>::read_from(source)?;
592
593 let mut seen_prefixes = alloc::collections::BTreeSet::new();
595 for (id, _) in &entries {
596 if !seen_prefixes.insert(id.prefix()) {
597 return Err(DeserializationError::InvalidValue(format!(
598 "Duplicate account ID prefix: {}",
599 id.prefix()
600 )));
601 }
602 }
603
604 let smt =
606 Smt::with_entries(entries.into_iter().map(|(k, v)| (account_id_to_smt_key(k), v)))
607 .map_err(|err| DeserializationError::InvalidValue(err.to_string()))?;
608 Ok(Self::new_unchecked(smt))
609 }
610}
611
612#[derive(Debug, Clone, PartialEq, Eq)]
622pub struct AccountMutationSet {
623 mutation_set: MutationSet<SMT_DEPTH, Word, Word>,
624}
625
626impl AccountMutationSet {
627 fn new(mutation_set: MutationSet<SMT_DEPTH, Word, Word>) -> Self {
632 Self { mutation_set }
633 }
634
635 pub fn as_mutation_set(&self) -> &MutationSet<SMT_DEPTH, Word, Word> {
640 &self.mutation_set
641 }
642
643 pub fn into_mutation_set(self) -> MutationSet<SMT_DEPTH, Word, Word> {
648 self.mutation_set
649 }
650}
651
652#[cfg(test)]
656pub(super) mod tests {
657 use std::vec::Vec;
658
659 use assert_matches::assert_matches;
660
661 use super::*;
662 use crate::account::{AccountStorageMode, AccountType};
663 use crate::testing::account_id::{AccountIdBuilder, account_id};
664
665 pub(crate) fn setup_duplicate_prefix_ids() -> [(AccountId, Word); 2] {
666 let id0 = AccountId::try_from(account_id(
667 AccountType::FungibleFaucet,
668 AccountStorageMode::Public,
669 0xaabb_ccdd,
670 ))
671 .unwrap();
672 let id1 = AccountId::try_from(account_id(
673 AccountType::FungibleFaucet,
674 AccountStorageMode::Public,
675 0xaabb_ccff,
676 ))
677 .unwrap();
678 assert_eq!(id0.prefix(), id1.prefix(), "test requires that these ids have the same prefix");
679
680 let commitment0 = Word::from([0, 0, 0, 42u32]);
681 let commitment1 = Word::from([0, 0, 0, 24u32]);
682
683 assert_eq!(id0.prefix(), id1.prefix(), "test requires that these ids have the same prefix");
684 [(id0, commitment0), (id1, commitment1)]
685 }
686
687 #[test]
688 fn insert_fails_on_duplicate_prefix() {
689 let mut tree = AccountTree::<Smt>::default();
690 let [(id0, commitment0), (id1, commitment1)] = setup_duplicate_prefix_ids();
691
692 tree.insert(id0, commitment0).unwrap();
693 assert_eq!(tree.get(id0), commitment0);
694
695 let err = tree.insert(id1, commitment1).unwrap_err();
696
697 assert_matches!(err, AccountTreeError::DuplicateIdPrefix {
698 duplicate_prefix
699 } if duplicate_prefix == id0.prefix());
700 }
701
702 #[test]
703 fn insert_succeeds_on_multiple_updates() {
704 let mut tree = AccountTree::<Smt>::default();
705 let [(id0, commitment0), (_, commitment1)] = setup_duplicate_prefix_ids();
706
707 tree.insert(id0, commitment0).unwrap();
708 tree.insert(id0, commitment1).unwrap();
709 assert_eq!(tree.get(id0), commitment1);
710 }
711
712 #[test]
713 fn apply_mutations() {
714 let id0 = AccountIdBuilder::new().build_with_seed([5; 32]);
715 let id1 = AccountIdBuilder::new().build_with_seed([6; 32]);
716 let id2 = AccountIdBuilder::new().build_with_seed([7; 32]);
717
718 let digest0 = Word::from([0, 0, 0, 1u32]);
719 let digest1 = Word::from([0, 0, 0, 2u32]);
720 let digest2 = Word::from([0, 0, 0, 3u32]);
721 let digest3 = Word::from([0, 0, 0, 4u32]);
722
723 let mut tree = AccountTree::with_entries([(id0, digest0), (id1, digest1)]).unwrap();
724
725 let mutations = tree
726 .compute_mutations([(id0, digest1), (id1, digest2), (id2, digest3)])
727 .unwrap();
728
729 tree.apply_mutations(mutations).unwrap();
730
731 assert_eq!(tree.num_accounts(), 3);
732 assert_eq!(tree.get(id0), digest1);
733 assert_eq!(tree.get(id1), digest2);
734 assert_eq!(tree.get(id2), digest3);
735 }
736
737 #[test]
738 fn duplicates_in_compute_mutations() {
739 let [pair0, pair1] = setup_duplicate_prefix_ids();
740 let id2 = AccountIdBuilder::new().build_with_seed([5; 32]);
741 let commitment2 = Word::from([0, 0, 0, 99u32]);
742
743 let tree = AccountTree::with_entries([pair0, (id2, commitment2)]).unwrap();
744 let err = tree.compute_mutations([pair1]).unwrap_err();
745
746 assert_matches!(err, AccountTreeError::DuplicateIdPrefix {
747 duplicate_prefix
748 } if duplicate_prefix == pair1.0.prefix());
749 }
750
751 #[test]
752 fn account_commitments() {
753 let id0 = AccountIdBuilder::new().build_with_seed([5; 32]);
754 let id1 = AccountIdBuilder::new().build_with_seed([6; 32]);
755 let id2 = AccountIdBuilder::new().build_with_seed([7; 32]);
756
757 let digest0 = Word::from([0, 0, 0, 1u32]);
758 let digest1 = Word::from([0, 0, 0, 2u32]);
759 let digest2 = Word::from([0, 0, 0, 3u32]);
760 let empty_digest = Word::empty();
761
762 let mut tree =
763 AccountTree::with_entries([(id0, digest0), (id1, digest1), (id2, digest2)]).unwrap();
764
765 tree.insert(id2, empty_digest).unwrap();
767
768 assert_eq!(tree.num_accounts(), 2);
769
770 let accounts: Vec<_> = tree.account_commitments().collect();
771 assert_eq!(accounts.len(), 2);
772 assert!(accounts.contains(&(id0, digest0)));
773 assert!(accounts.contains(&(id1, digest1)));
774 }
775
776 #[test]
777 fn account_witness() {
778 let id0 = AccountIdBuilder::new().build_with_seed([5; 32]);
779 let id1 = AccountIdBuilder::new().build_with_seed([6; 32]);
780
781 let digest0 = Word::from([0, 0, 0, 1u32]);
782 let digest1 = Word::from([0, 0, 0, 2u32]);
783
784 let tree = AccountTree::with_entries([(id0, digest0), (id1, digest1)]).unwrap();
785
786 assert_eq!(tree.num_accounts(), 2);
787
788 for id in [id0, id1] {
789 let proof = tree.smt.open(&account_id_to_smt_key(id));
790 let (control_path, control_leaf) = proof.into_parts();
791 let witness = tree.open(id);
792
793 assert_eq!(witness.leaf(), control_leaf);
794 assert_eq!(witness.path(), &control_path);
795 }
796 }
797
798 #[test]
799 fn contains_account_prefix() {
800 let [pair0, pair1] = setup_duplicate_prefix_ids();
802 let tree = AccountTree::with_entries([pair0]).unwrap();
803 assert_eq!(tree.num_accounts(), 1);
804
805 assert!(tree.contains_account_id_prefix(pair0.0.prefix()));
807
808 assert!(tree.contains_account_id_prefix(pair1.0.prefix()));
810
811 let id1 = AccountIdBuilder::new().build_with_seed([7; 32]);
813 assert!(!tree.contains_account_id_prefix(id1.prefix()));
814 }
815
816 #[cfg(feature = "std")]
817 #[test]
818 fn large_smt_backend_basic_operations() {
819 use miden_crypto::merkle::{LargeSmt, MemoryStorage};
820
821 let id0 = AccountIdBuilder::new().build_with_seed([5; 32]);
823 let id1 = AccountIdBuilder::new().build_with_seed([6; 32]);
824 let id2 = AccountIdBuilder::new().build_with_seed([7; 32]);
825
826 let digest0 = Word::from([0, 0, 0, 1u32]);
827 let digest1 = Word::from([0, 0, 0, 2u32]);
828 let digest2 = Word::from([0, 0, 0, 3u32]);
829
830 let tree = LargeSmt::<MemoryStorage>::with_entries(
832 MemoryStorage::default(),
833 [(account_id_to_smt_key(id0), digest0), (account_id_to_smt_key(id1), digest1)],
834 )
835 .map(AccountTree::new_unchecked)
836 .unwrap();
837
838 assert_eq!(tree.num_accounts(), 2);
840 assert_eq!(tree.get(id0), digest0);
841 assert_eq!(tree.get(id1), digest1);
842
843 let witness0 = tree.open(id0);
845 assert_eq!(witness0.id(), id0);
846
847 let mut tree_mut = LargeSmt::<MemoryStorage>::with_entries(
849 MemoryStorage::default(),
850 [(account_id_to_smt_key(id0), digest0), (account_id_to_smt_key(id1), digest1)],
851 )
852 .map(AccountTree::new_unchecked)
853 .unwrap();
854 tree_mut.insert(id2, digest2).unwrap();
855 assert_eq!(tree_mut.num_accounts(), 3);
856 assert_eq!(tree_mut.get(id2), digest2);
857
858 assert_eq!(tree.num_accounts(), 2);
860 }
861
862 #[cfg(feature = "std")]
863 #[test]
864 fn large_smt_backend_duplicate_prefix_check() {
865 use miden_crypto::merkle::{LargeSmt, MemoryStorage};
866
867 let [(id0, commitment0), (id1, commitment1)] = setup_duplicate_prefix_ids();
868
869 let mut tree = AccountTree::new_unchecked(LargeSmt::new(MemoryStorage::default()).unwrap());
870
871 tree.insert(id0, commitment0).unwrap();
872 assert_eq!(tree.get(id0), commitment0);
873
874 let err = tree.insert(id1, commitment1).unwrap_err();
875
876 assert_matches!(
877 err,
878 AccountTreeError::DuplicateIdPrefix { duplicate_prefix }
879 if duplicate_prefix == id0.prefix()
880 );
881 }
882
883 #[cfg(feature = "std")]
884 #[test]
885 fn large_smt_backend_apply_mutations() {
886 use miden_crypto::merkle::{LargeSmt, MemoryStorage};
887
888 let id0 = AccountIdBuilder::new().build_with_seed([5; 32]);
889 let id1 = AccountIdBuilder::new().build_with_seed([6; 32]);
890 let id2 = AccountIdBuilder::new().build_with_seed([7; 32]);
891
892 let digest0 = Word::from([0, 0, 0, 1u32]);
893 let digest1 = Word::from([0, 0, 0, 2u32]);
894 let digest2 = Word::from([0, 0, 0, 3u32]);
895 let digest3 = Word::from([0, 0, 0, 4u32]);
896
897 let mut tree = LargeSmt::with_entries(
898 MemoryStorage::default(),
899 [(account_id_to_smt_key(id0), digest0), (account_id_to_smt_key(id1), digest1)],
900 )
901 .map(AccountTree::new_unchecked)
902 .unwrap();
903
904 let mutations = tree
905 .compute_mutations([(id0, digest1), (id1, digest2), (id2, digest3)])
906 .unwrap();
907
908 tree.apply_mutations(mutations).unwrap();
909
910 assert_eq!(tree.num_accounts(), 3);
911 assert_eq!(tree.get(id0), digest1);
912 assert_eq!(tree.get(id1), digest2);
913 assert_eq!(tree.get(id2), digest3);
914 }
915
916 #[cfg(feature = "std")]
917 #[test]
918 fn large_smt_backend_same_root_as_regular_smt() {
919 use miden_crypto::merkle::{LargeSmt, MemoryStorage};
920
921 let id0 = AccountIdBuilder::new().build_with_seed([5; 32]);
922 let id1 = AccountIdBuilder::new().build_with_seed([6; 32]);
923
924 let digest0 = Word::from([0, 0, 0, 1u32]);
925 let digest1 = Word::from([0, 0, 0, 2u32]);
926
927 let large_tree = LargeSmt::with_entries(
929 MemoryStorage::default(),
930 [(account_id_to_smt_key(id0), digest0), (account_id_to_smt_key(id1), digest1)],
931 )
932 .map(AccountTree::new_unchecked)
933 .unwrap();
934
935 let regular_tree = AccountTree::with_entries([(id0, digest0), (id1, digest1)]).unwrap();
937
938 assert_eq!(large_tree.root(), regular_tree.root());
940
941 let large_commitments: std::collections::BTreeMap<_, _> =
943 large_tree.account_commitments().collect();
944 let regular_commitments: std::collections::BTreeMap<_, _> =
945 regular_tree.account_commitments().collect();
946
947 assert_eq!(large_commitments, regular_commitments);
948 }
949}