miden_objects/account/storage/slot/
mod.rs

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