miden_objects/account/storage/slot/
mod.rs

1use vm_core::{
2    EMPTY_WORD,
3    utils::{ByteReader, ByteWriter, Deserializable, Serializable},
4};
5use vm_processor::DeserializationError;
6
7use super::{StorageMap, Word, map::EMPTY_STORAGE_MAP_ROOT};
8
9mod r#type;
10pub use r#type::StorageSlotType;
11
12// STORAGE SLOT
13// ================================================================================================
14
15/// An object representing the contents of an account's storage slot.
16///
17/// An account storage slot can be of two types:
18/// - A simple value which contains a single word (4 field elements or ~32 bytes).
19/// - A key value map where both keys and values are words. The capacity of such storage slot is
20///   theoretically unlimited.
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub enum StorageSlot {
23    Value(Word),
24    Map(StorageMap),
25}
26
27impl StorageSlot {
28    /// The number of field elements needed to represent a [StorageSlot] in kernel memory.
29    pub const NUM_ELEMENTS_PER_STORAGE_SLOT: usize = 8;
30
31    /// Returns true if this storage slot has a value equal the default of it's type
32    pub fn is_default(&self) -> bool {
33        match self {
34            StorageSlot::Value(value) => *value == EMPTY_WORD,
35            StorageSlot::Map(map) => map.root() == EMPTY_STORAGE_MAP_ROOT,
36        }
37    }
38
39    /// Returns the empty [Word] for a storage slot of this type
40    pub fn default_word(&self) -> Word {
41        match self {
42            StorageSlot::Value(_) => EMPTY_WORD,
43            StorageSlot::Map(_) => EMPTY_STORAGE_MAP_ROOT.into(),
44        }
45    }
46
47    /// Returns a [`StorageSlot::Value`] with an empty word.
48    pub fn empty_value() -> Self {
49        StorageSlot::Value(EMPTY_WORD)
50    }
51
52    /// Returns an empty [`StorageSlot::Map`].
53    pub fn empty_map() -> Self {
54        StorageSlot::Map(StorageMap::new())
55    }
56
57    /// Returns this storage slot value as a [Word]
58    ///
59    /// Returns:
60    /// - For [StorageSlot::Value] the value
61    /// - For [StorageSlot::Map] the root of the [StorageMap]
62    pub fn value(&self) -> Word {
63        match self {
64            Self::Value(value) => *value,
65            Self::Map(map) => map.root().into(),
66        }
67    }
68
69    /// Returns the type of this storage slot
70    pub fn slot_type(&self) -> StorageSlotType {
71        match self {
72            StorageSlot::Value(_) => StorageSlotType::Value,
73            StorageSlot::Map(_) => StorageSlotType::Map,
74        }
75    }
76}
77
78// SERIALIZATION
79// ================================================================================================
80
81impl Serializable for StorageSlot {
82    fn write_into<W: ByteWriter>(&self, target: &mut W) {
83        target.write(self.slot_type());
84
85        match self {
86            Self::Value(value) => target.write(value),
87            Self::Map(map) => target.write(map),
88        }
89    }
90
91    fn get_size_hint(&self) -> usize {
92        let mut size = self.slot_type().get_size_hint();
93
94        size += match self {
95            StorageSlot::Value(word) => word.get_size_hint(),
96            StorageSlot::Map(storage_map) => storage_map.get_size_hint(),
97        };
98
99        size
100    }
101}
102
103impl Deserializable for StorageSlot {
104    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
105        let storage_slot_type = source.read::<StorageSlotType>()?;
106
107        match storage_slot_type {
108            StorageSlotType::Value => {
109                let word = source.read::<Word>()?;
110                Ok(StorageSlot::Value(word))
111            },
112            StorageSlotType::Map => {
113                let map = source.read::<StorageMap>()?;
114                Ok(StorageSlot::Map(map))
115            },
116        }
117    }
118}
119
120// TESTS
121// ================================================================================================
122
123#[cfg(test)]
124mod tests {
125    use vm_core::utils::{Deserializable, Serializable};
126
127    use crate::account::AccountStorage;
128
129    #[test]
130    fn test_serde_account_storage_slot() {
131        let storage = AccountStorage::mock();
132        let serialized = storage.to_bytes();
133        let deserialized = AccountStorage::read_from_bytes(&serialized).unwrap();
134        assert_eq!(deserialized, storage)
135    }
136}