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