miden_objects/account/storage/
map.rs1use miden_crypto::merkle::EmptySubtreeRoots;
2
3use super::{
4 ByteReader, ByteWriter, Deserializable, DeserializationError, Digest, Serializable, Word,
5};
6use crate::{
7 account::StorageMapDelta,
8 crypto::{
9 hash::rpo::RpoDigest,
10 merkle::{InnerNodeInfo, LeafIndex, Smt, SmtLeaf, SmtProof, SMT_DEPTH},
11 },
12};
13
14pub const EMPTY_STORAGE_MAP_ROOT: Digest =
19 *EmptySubtreeRoots::entry(StorageMap::STORAGE_MAP_TREE_DEPTH, 0);
20
21#[derive(Debug, Clone, PartialEq, Eq)]
25pub struct StorageMap {
26 map: Smt,
27}
28
29impl StorageMap {
30 pub const STORAGE_MAP_TREE_DEPTH: u8 = SMT_DEPTH;
35
36 pub const EMPTY_VALUE: Word = Smt::EMPTY_VALUE;
38
39 pub fn new() -> Self {
46 StorageMap { map: Smt::new() }
47 }
48
49 pub fn with_entries(entries: impl IntoIterator<Item = (RpoDigest, Word)>) -> Self {
50 let mut storage_map = Smt::new();
51
52 for (key, value) in entries {
53 storage_map.insert(key, value);
54 }
55
56 StorageMap { map: storage_map }
57 }
58
59 pub const fn depth(&self) -> u8 {
63 SMT_DEPTH
64 }
65
66 pub fn root(&self) -> RpoDigest {
67 self.map.root() }
69
70 pub fn get_leaf(&self, key: &RpoDigest) -> SmtLeaf {
71 self.map.get_leaf(key) }
73
74 pub fn get_value(&self, key: &RpoDigest) -> Word {
75 self.map.get_value(key) }
77
78 pub fn open(&self, key: &RpoDigest) -> SmtProof {
79 self.map.open(key) }
81
82 pub fn leaves(&self) -> impl Iterator<Item = (LeafIndex<SMT_DEPTH>, &SmtLeaf)> {
85 self.map.leaves() }
87
88 pub fn entries(&self) -> impl Iterator<Item = &(RpoDigest, Word)> {
89 self.map.entries() }
91
92 pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
93 self.map.inner_nodes() }
95
96 pub fn insert(&mut self, key: RpoDigest, value: Word) -> Word {
99 self.map.insert(key, value) }
101
102 pub fn apply_delta(&mut self, delta: &StorageMapDelta) -> Digest {
104 for (&key, &value) in delta.leaves().iter() {
106 self.insert(key, value);
107 }
108
109 self.root()
110 }
111}
112
113impl Default for StorageMap {
114 fn default() -> Self {
115 Self::new()
116 }
117}
118
119impl Serializable for StorageMap {
123 fn write_into<W: ByteWriter>(&self, target: &mut W) {
124 self.map.write_into(target)
125 }
126
127 fn get_size_hint(&self) -> usize {
128 self.map.get_size_hint()
129 }
130}
131
132impl Deserializable for StorageMap {
133 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
134 let smt = Smt::read_from(source)?;
135 Ok(StorageMap { map: smt })
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use miden_crypto::{hash::rpo::RpoDigest, Felt};
142
143 use super::{Deserializable, Serializable, StorageMap, Word, EMPTY_STORAGE_MAP_ROOT};
144
145 #[test]
146 fn account_storage_serialization() {
147 let storage_map_default = StorageMap::default();
149 let bytes = storage_map_default.to_bytes();
150 assert_eq!(storage_map_default, StorageMap::read_from_bytes(&bytes).unwrap());
151
152 let storage_map_leaves_2: [(RpoDigest, Word); 2] = [
154 (
155 RpoDigest::new([Felt::new(101), Felt::new(102), Felt::new(103), Felt::new(104)]),
156 [Felt::new(1_u64), Felt::new(2_u64), Felt::new(3_u64), Felt::new(4_u64)],
157 ),
158 (
159 RpoDigest::new([Felt::new(105), Felt::new(106), Felt::new(107), Felt::new(108)]),
160 [Felt::new(5_u64), Felt::new(6_u64), Felt::new(7_u64), Felt::new(8_u64)],
161 ),
162 ];
163 let storage_map = StorageMap::with_entries(storage_map_leaves_2);
164
165 let bytes = storage_map.to_bytes();
166 assert_eq!(storage_map, StorageMap::read_from_bytes(&bytes).unwrap());
167 }
168
169 #[test]
170 fn test_empty_storage_map_constants() {
171 assert_eq!(StorageMap::default().root(), EMPTY_STORAGE_MAP_ROOT);
173 }
174}