miden_protocol/account/storage/
mod.rs1use alloc::string::ToString;
2use alloc::vec::Vec;
3
4use super::{
5 AccountError,
6 AccountStorageDelta,
7 ByteReader,
8 ByteWriter,
9 Deserializable,
10 DeserializationError,
11 Felt,
12 Serializable,
13 Word,
14};
15use crate::account::AccountComponent;
16use crate::crypto::SequentialCommit;
17
18mod slot;
19pub use slot::{StorageSlot, StorageSlotContent, StorageSlotId, StorageSlotName, StorageSlotType};
20
21mod map;
22pub use map::{PartialStorageMap, StorageMap, StorageMapKey, StorageMapKeyHash, StorageMapWitness};
23
24mod header;
25pub use header::{AccountStorageHeader, StorageSlotHeader};
26
27mod partial;
28pub use partial::PartialStorage;
29
30#[derive(Debug, Clone, Default, PartialEq, Eq)]
51pub struct AccountStorage {
52 slots: Vec<StorageSlot>,
53}
54
55impl AccountStorage {
56 pub const MAX_NUM_STORAGE_SLOTS: usize = 255;
58
59 pub fn new(mut slots: Vec<StorageSlot>) -> Result<AccountStorage, AccountError> {
72 let num_slots = slots.len();
73
74 if num_slots > Self::MAX_NUM_STORAGE_SLOTS {
75 return Err(AccountError::StorageTooManySlots(num_slots as u64));
76 }
77
78 slots.sort_unstable();
80
81 for slots in slots.windows(2) {
84 if slots[0].id() == slots[1].id() {
85 return Err(AccountError::DuplicateStorageSlotName(slots[0].name().clone()));
86 }
87 }
88
89 Ok(Self { slots })
90 }
91
92 pub(super) fn from_components(
100 components: Vec<AccountComponent>,
101 ) -> Result<AccountStorage, AccountError> {
102 let storage_slots = components
103 .into_iter()
104 .flat_map(|component| {
105 let AccountComponent { storage_slots, .. } = component;
106 storage_slots.into_iter()
107 })
108 .collect();
109
110 Self::new(storage_slots)
111 }
112
113 pub fn to_elements(&self) -> Vec<Felt> {
124 <Self as SequentialCommit>::to_elements(self)
125 }
126
127 pub fn to_commitment(&self) -> Word {
129 <Self as SequentialCommit>::to_commitment(self)
130 }
131
132 pub fn num_slots(&self) -> u8 {
134 self.slots.len() as u8
137 }
138
139 pub fn slots(&self) -> &[StorageSlot] {
141 &self.slots
142 }
143
144 pub fn into_slots(self) -> Vec<StorageSlot> {
146 self.slots
147 }
148
149 pub fn to_header(&self) -> AccountStorageHeader {
151 AccountStorageHeader::new(self.slots.iter().map(StorageSlotHeader::from).collect())
152 .expect("slots should be valid as ensured by AccountStorage")
153 }
154
155 pub fn get(&self, slot_name: &StorageSlotName) -> Option<&StorageSlot> {
158 self.slots.iter().find(|slot| slot.name().id() == slot_name.id())
159 }
160
161 fn get_mut(&mut self, slot_name: &StorageSlotName) -> Option<&mut StorageSlot> {
164 self.slots.iter_mut().find(|slot| slot.name().id() == slot_name.id())
165 }
166
167 pub fn get_item(&self, slot_name: &StorageSlotName) -> Result<Word, AccountError> {
174 self.get(slot_name)
175 .map(|slot| slot.content().value())
176 .ok_or_else(|| AccountError::StorageSlotNameNotFound { slot_name: slot_name.clone() })
177 }
178
179 pub fn get_map_item(
187 &self,
188 slot_name: &StorageSlotName,
189 key: Word,
190 ) -> Result<Word, AccountError> {
191 self.get(slot_name)
192 .ok_or_else(|| AccountError::StorageSlotNameNotFound { slot_name: slot_name.clone() })
193 .and_then(|slot| match slot.content() {
194 StorageSlotContent::Map(map) => Ok(map.get(&StorageMapKey::from_raw(key))),
195 _ => Err(AccountError::StorageSlotNotMap(slot_name.clone())),
196 })
197 }
198
199 pub(super) fn apply_delta(&mut self, delta: &AccountStorageDelta) -> Result<(), AccountError> {
209 for (slot_name, &value) in delta.values() {
211 self.set_item(slot_name, value)?;
212 }
213
214 for (slot_name, map_delta) in delta.maps() {
216 let slot = self
217 .get_mut(slot_name)
218 .ok_or(AccountError::StorageSlotNameNotFound { slot_name: slot_name.clone() })?;
219
220 let storage_map = match slot.content_mut() {
221 StorageSlotContent::Map(map) => map,
222 _ => return Err(AccountError::StorageSlotNotMap(slot_name.clone())),
223 };
224
225 storage_map.apply_delta(map_delta)?;
226 }
227
228 Ok(())
229 }
230
231 pub fn set_item(
242 &mut self,
243 slot_name: &StorageSlotName,
244 value: Word,
245 ) -> Result<Word, AccountError> {
246 let slot = self.get_mut(slot_name).ok_or_else(|| {
247 AccountError::StorageSlotNameNotFound { slot_name: slot_name.clone() }
248 })?;
249
250 let StorageSlotContent::Value(old_value) = slot.content() else {
251 return Err(AccountError::StorageSlotNotValue(slot_name.clone()));
252 };
253 let old_value = *old_value;
254
255 let mut new_slot = StorageSlotContent::Value(value);
256 core::mem::swap(slot.content_mut(), &mut new_slot);
257
258 Ok(old_value)
259 }
260
261 pub fn set_map_item(
272 &mut self,
273 slot_name: &StorageSlotName,
274 key: StorageMapKey,
275 value: Word,
276 ) -> Result<(Word, Word), AccountError> {
277 let slot = self.get_mut(slot_name).ok_or_else(|| {
278 AccountError::StorageSlotNameNotFound { slot_name: slot_name.clone() }
279 })?;
280
281 let StorageSlotContent::Map(storage_map) = slot.content_mut() else {
282 return Err(AccountError::StorageSlotNotMap(slot_name.clone()));
283 };
284
285 let old_root = storage_map.root();
286
287 let old_value = storage_map.insert(key, value)?;
288
289 Ok((old_root, old_value))
290 }
291}
292
293impl IntoIterator for AccountStorage {
297 type Item = StorageSlot;
298 type IntoIter = alloc::vec::IntoIter<StorageSlot>;
299
300 fn into_iter(self) -> Self::IntoIter {
301 self.slots.into_iter()
302 }
303}
304
305impl SequentialCommit for AccountStorage {
309 type Commitment = Word;
310
311 fn to_elements(&self) -> Vec<Felt> {
312 self.slots()
313 .iter()
314 .flat_map(|slot| {
315 StorageSlotHeader::new(
316 slot.name().clone(),
317 slot.content().slot_type(),
318 slot.content().value(),
319 )
320 .to_elements()
321 })
322 .collect()
323 }
324}
325
326impl Serializable for AccountStorage {
330 fn write_into<W: ByteWriter>(&self, target: &mut W) {
331 target.write_u8(self.slots().len() as u8);
332 target.write_many(self.slots());
333 }
334
335 fn get_size_hint(&self) -> usize {
336 let u8_size = 0u8.get_size_hint();
338 let mut size = u8_size;
339
340 for slot in self.slots() {
341 size += slot.get_size_hint();
342 }
343
344 size
345 }
346}
347
348impl Deserializable for AccountStorage {
349 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
350 let num_slots = source.read_u8()? as usize;
351 let slots = source.read_many::<StorageSlot>(num_slots)?;
352
353 Self::new(slots).map_err(|err| DeserializationError::InvalidValue(err.to_string()))
354 }
355}
356
357#[cfg(test)]
361mod tests {
362 use assert_matches::assert_matches;
363
364 use super::{AccountStorage, Deserializable, Serializable};
365 use crate::account::{AccountStorageHeader, StorageSlot, StorageSlotHeader, StorageSlotName};
366 use crate::errors::AccountError;
367
368 #[test]
369 fn test_serde_account_storage() -> anyhow::Result<()> {
370 let storage = AccountStorage::new(vec![]).unwrap();
372 let bytes = storage.to_bytes();
373 assert_eq!(storage, AccountStorage::read_from_bytes(&bytes).unwrap());
374
375 let storage = AccountStorage::new(vec![
377 StorageSlot::with_empty_value(StorageSlotName::new("miden::test::value")?),
378 StorageSlot::with_empty_map(StorageSlotName::new("miden::test::map")?),
379 ])
380 .unwrap();
381 let bytes = storage.to_bytes();
382 assert_eq!(storage, AccountStorage::read_from_bytes(&bytes).unwrap());
383
384 Ok(())
385 }
386
387 #[test]
388 fn test_get_slot_by_name() -> anyhow::Result<()> {
389 let counter_slot = StorageSlotName::new("miden::test::counter")?;
390 let map_slot = StorageSlotName::new("miden::test::map")?;
391
392 let slots = vec![
393 StorageSlot::with_empty_value(counter_slot.clone()),
394 StorageSlot::with_empty_map(map_slot.clone()),
395 ];
396 let storage = AccountStorage::new(slots.clone())?;
397
398 assert_eq!(storage.get(&counter_slot).unwrap(), &slots[0]);
399 assert_eq!(storage.get(&map_slot).unwrap(), &slots[1]);
400
401 Ok(())
402 }
403
404 #[test]
405 fn test_account_storage_and_header_fail_on_duplicate_slot_name() -> anyhow::Result<()> {
406 let slot_name0 = StorageSlotName::mock(0);
407 let slot_name1 = StorageSlotName::mock(1);
408 let slot_name2 = StorageSlotName::mock(2);
409
410 let mut slots = vec![
411 StorageSlot::with_empty_value(slot_name0.clone()),
412 StorageSlot::with_empty_value(slot_name1.clone()),
413 StorageSlot::with_empty_map(slot_name0.clone()),
414 StorageSlot::with_empty_value(slot_name2.clone()),
415 ];
416
417 let err = AccountStorage::new(slots.clone()).unwrap_err();
420
421 assert_matches!(err, AccountError::DuplicateStorageSlotName(name) => {
422 assert_eq!(name, slot_name0);
423 });
424
425 slots.sort_unstable();
426 let err = AccountStorageHeader::new(slots.iter().map(StorageSlotHeader::from).collect())
427 .unwrap_err();
428
429 assert_matches!(err, AccountError::DuplicateStorageSlotName(name) => {
430 assert_eq!(name, slot_name0);
431 });
432
433 Ok(())
434 }
435}