Skip to main content

miden_objects/decoded/account/
storage.rs

1pub use proto::account::DecodedStorageSlotId as StorageSlotId;
2
3use crate::decoded::VerificationError;
4use crate::{Verify, proto};
5
6#[cfg(test)]
7mod tests;
8
9impl Verify for StorageSlotId {
10    type Verified = miden_protocol::account::StorageSlotId;
11    type Error = core::convert::Infallible;
12    fn verify(self) -> Result<Self::Verified, Self::Error> {
13        Ok(Self::Verified::new(self.suffix, self.prefix))
14    }
15}
16
17pub use proto::account::DecodedStorageMapEntry as StorageMapEntry;
18
19impl Verify for StorageMapEntry {
20    type Verified = (miden_protocol::account::StorageMapKey, miden_protocol::Word);
21    type Error = core::convert::Infallible;
22    fn verify(self) -> Result<Self::Verified, Self::Error> {
23        Ok((miden_protocol::account::StorageMapKey::from_raw(self.key), self.value))
24    }
25}
26
27pub use proto::account::account_storage_header::DecodedStorageSlot as AccountStorageHeaderStorageSlot;
28
29impl Verify for AccountStorageHeaderStorageSlot {
30    type Verified = miden_protocol::account::StorageSlotHeader;
31    type Error = miden_protocol::errors::StorageSlotNameError;
32    fn verify(self) -> Result<Self::Verified, Self::Error> {
33        use miden_protocol::account::StorageSlotType;
34        use proto::account::account_storage_header::storage_slot::DecodedContent;
35
36        let name = miden_protocol::account::StorageSlotName::new(self.slot_name)?;
37        let (slot_type, value) = match self.content {
38            DecodedContent::Value(value) => (StorageSlotType::Value, value),
39            DecodedContent::MapRoot(root) => (StorageSlotType::Map, root),
40        };
41        Ok(Self::Verified::new(name, slot_type, value))
42    }
43}
44
45pub use proto::account::DecodedAccountStorageHeader as AccountStorageHeader;
46
47impl Verify for AccountStorageHeader {
48    type Verified = miden_protocol::account::AccountStorageHeader;
49    type Error = VerificationError;
50    fn verify(self) -> Result<Self::Verified, Self::Error> {
51        let slots = self.slots.verify()?;
52        Ok(Self::Verified::new(slots)?)
53    }
54}
55
56pub use proto::account::DecodedStorageMap as StorageMap;
57
58impl Verify for StorageMap {
59    type Verified = miden_protocol::account::StorageMap;
60    type Error = VerificationError;
61    fn verify(self) -> Result<Self::Verified, Self::Error> {
62        let entries = self.entries.verify_infallible();
63        // The storage map constructor drops an entry with an empty value. Reject it here for a
64        // clear error.
65        if let Some((key, _)) = entries.iter().find(|(_, value)| value.is_empty()) {
66            return Err(StorageMapEntryError::EmptyValue(*key).into());
67        }
68        Ok(Self::Verified::with_entries(entries)?)
69    }
70}
71
72/// An invariant of a single map entry, distinct from the domain's `StorageMapError`.
73#[derive(Debug, thiserror::Error)]
74pub enum StorageMapEntryError {
75    #[error("storage map entry {0} has an empty value")]
76    EmptyValue(miden_protocol::account::StorageMapKey),
77}
78
79pub use proto::account::DecodedStorageSlot as StorageSlot;
80
81impl Verify for StorageSlot {
82    type Verified = miden_protocol::account::StorageSlot;
83    type Error = VerificationError;
84    fn verify(self) -> Result<Self::Verified, Self::Error> {
85        use miden_protocol::account::StorageSlotContent;
86        use proto::account::storage_slot::DecodedStorageSlotContent;
87
88        let name = miden_protocol::account::StorageSlotName::new(self.slot_name)?;
89        let content = match self.storage_slot_content {
90            DecodedStorageSlotContent::Value(value) => StorageSlotContent::Value(value),
91            DecodedStorageSlotContent::Map(map) => StorageSlotContent::Map(map.verify()?),
92        };
93        Ok(Self::Verified::new(name, content))
94    }
95}
96
97pub use proto::account::DecodedAccountStorage as AccountStorage;
98
99impl Verify for AccountStorage {
100    type Verified = miden_protocol::account::AccountStorage;
101    type Error = VerificationError;
102    fn verify(self) -> Result<Self::Verified, Self::Error> {
103        // Check the slot count before verifying the slots, so an oversized message is rejected
104        // without first building a tree for each of its map slots.
105        let num_slots = self.slots.as_slice().len();
106        if num_slots > Self::Verified::MAX_NUM_STORAGE_SLOTS {
107            return Err(miden_protocol::errors::AccountError::StorageTooManySlots(
108                num_slots as u64,
109            )
110            .into());
111        }
112        Ok(Self::Verified::new(self.slots.verify()?)?)
113    }
114}