miden_objects/account/storage/
map.rs1use miden_crypto::merkle::{EmptySubtreeRoots, MerkleError};
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_DEPTH, Smt, SmtLeaf, SmtProof},
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(
55 entries: impl IntoIterator<Item = (RpoDigest, Word)>,
56 ) -> Result<Self, MerkleError> {
57 Smt::with_entries(entries).map(|map| StorageMap { map })
58 }
59
60 pub const fn depth(&self) -> u8 {
64 SMT_DEPTH
65 }
66
67 pub fn root(&self) -> RpoDigest {
68 self.map.root() }
70
71 pub fn get_leaf(&self, key: &RpoDigest) -> SmtLeaf {
72 self.map.get_leaf(key) }
74
75 pub fn get_value(&self, key: &RpoDigest) -> Word {
76 self.map.get_value(key) }
78
79 pub fn open(&self, key: &RpoDigest) -> SmtProof {
80 self.map.open(key) }
82
83 pub fn leaves(&self) -> impl Iterator<Item = (LeafIndex<SMT_DEPTH>, &SmtLeaf)> {
86 self.map.leaves() }
88
89 pub fn entries(&self) -> impl Iterator<Item = &(RpoDigest, Word)> {
90 self.map.entries() }
92
93 pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
94 self.map.inner_nodes() }
96
97 pub fn insert(&mut self, key: RpoDigest, value: Word) -> Word {
100 self.map.insert(key, value) }
102
103 pub fn apply_delta(&mut self, delta: &StorageMapDelta) -> Digest {
105 for (&key, &value) in delta.leaves().iter() {
107 self.insert(key, value);
108 }
109
110 self.root()
111 }
112}
113
114impl Default for StorageMap {
115 fn default() -> Self {
116 Self::new()
117 }
118}
119
120impl Serializable for StorageMap {
124 fn write_into<W: ByteWriter>(&self, target: &mut W) {
125 self.map.write_into(target)
126 }
127
128 fn get_size_hint(&self) -> usize {
129 self.map.get_size_hint()
130 }
131}
132
133impl Deserializable for StorageMap {
134 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
135 let smt = Smt::read_from(source)?;
136 Ok(StorageMap { map: smt })
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use assert_matches::assert_matches;
143 use miden_crypto::{Felt, hash::rpo::RpoDigest, merkle::MerkleError};
144
145 use super::{Deserializable, EMPTY_STORAGE_MAP_ROOT, Serializable, StorageMap, Word};
146
147 #[test]
148 fn account_storage_serialization() {
149 let storage_map_default = StorageMap::default();
151 let bytes = storage_map_default.to_bytes();
152 assert_eq!(storage_map_default, StorageMap::read_from_bytes(&bytes).unwrap());
153
154 let storage_map_leaves_2: [(RpoDigest, Word); 2] = [
156 (
157 RpoDigest::new([Felt::new(101), Felt::new(102), Felt::new(103), Felt::new(104)]),
158 [Felt::new(1_u64), Felt::new(2_u64), Felt::new(3_u64), Felt::new(4_u64)],
159 ),
160 (
161 RpoDigest::new([Felt::new(105), Felt::new(106), Felt::new(107), Felt::new(108)]),
162 [Felt::new(5_u64), Felt::new(6_u64), Felt::new(7_u64), Felt::new(8_u64)],
163 ),
164 ];
165 let storage_map = StorageMap::with_entries(storage_map_leaves_2).unwrap();
166
167 let bytes = storage_map.to_bytes();
168 assert_eq!(storage_map, StorageMap::read_from_bytes(&bytes).unwrap());
169 }
170
171 #[test]
172 fn test_empty_storage_map_constants() {
173 assert_eq!(StorageMap::default().root(), EMPTY_STORAGE_MAP_ROOT);
175 }
176
177 #[test]
178 fn account_storage_map_fails_on_duplicate_entries() {
179 let storage_map_leaves_2: [(RpoDigest, Word); 2] = [
181 (
182 RpoDigest::new([Felt::new(101), Felt::new(102), Felt::new(103), Felt::new(104)]),
183 [Felt::new(1_u64), Felt::new(2_u64), Felt::new(3_u64), Felt::new(4_u64)],
184 ),
185 (
186 RpoDigest::new([Felt::new(101), Felt::new(102), Felt::new(103), Felt::new(104)]),
187 [Felt::new(5_u64), Felt::new(6_u64), Felt::new(7_u64), Felt::new(8_u64)],
188 ),
189 ];
190
191 let error = StorageMap::with_entries(storage_map_leaves_2).unwrap_err();
192 assert_matches!(error, MerkleError::DuplicateValuesForIndex(_));
193 }
194}