miden_objects/account/storage/
header.rs1use alloc::vec::Vec;
2
3use vm_processor::Digest;
4
5use super::{AccountStorage, Felt, Hasher, StorageSlot, StorageSlotType, Word};
6use crate::{
7 AccountError, ZERO,
8 utils::serde::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
9};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub struct StorageSlotHeader(StorageSlotType, Word);
21
22impl StorageSlotHeader {
23 pub fn new(value: &(StorageSlotType, Word)) -> Self {
25 Self(value.0, value.1)
26 }
27
28 pub fn as_elements(&self) -> [Felt; StorageSlot::NUM_ELEMENTS_PER_STORAGE_SLOT] {
35 let mut elements = [ZERO; StorageSlot::NUM_ELEMENTS_PER_STORAGE_SLOT];
36 elements[0..4].copy_from_slice(&self.1);
37 elements[4..8].copy_from_slice(&self.0.as_word());
38 elements
39 }
40}
41
42impl From<&StorageSlot> for StorageSlotHeader {
43 fn from(value: &StorageSlot) -> Self {
44 Self(value.slot_type(), value.value())
45 }
46}
47
48#[derive(Debug, Clone, PartialEq, Eq)]
54pub struct AccountStorageHeader {
55 slots: Vec<(StorageSlotType, Word)>,
56}
57
58impl AccountStorageHeader {
59 pub fn new(slots: Vec<(StorageSlotType, Word)>) -> Self {
67 assert!(slots.len() <= AccountStorage::MAX_NUM_STORAGE_SLOTS);
68 Self { slots }
69 }
70
71 pub fn slots(&self) -> impl Iterator<Item = &(StorageSlotType, Word)> {
76 self.slots.iter()
77 }
78
79 pub fn num_slots(&self) -> u8 {
81 self.slots.len() as u8
83 }
84
85 pub fn slot(&self, index: usize) -> Result<&(StorageSlotType, Word), AccountError> {
90 self.slots.get(index).ok_or(AccountError::StorageIndexOutOfBounds {
91 slots_len: self.slots.len() as u8,
92 index: index as u8,
93 })
94 }
95
96 pub fn compute_commitment(&self) -> Digest {
99 Hasher::hash_elements(&self.as_elements())
100 }
101
102 pub fn as_elements(&self) -> Vec<Felt> {
110 self.slots
111 .iter()
112 .flat_map(|slot| StorageSlotHeader::new(slot).as_elements())
113 .collect()
114 }
115}
116
117impl From<&AccountStorage> for AccountStorageHeader {
118 fn from(value: &AccountStorage) -> Self {
119 value.to_header()
120 }
121}
122
123impl Serializable for AccountStorageHeader {
127 fn write_into<W: ByteWriter>(&self, target: &mut W) {
128 let len = self.slots.len() as u8;
129 target.write_u8(len);
130 target.write_many(self.slots())
131 }
132}
133
134impl Deserializable for AccountStorageHeader {
135 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
136 let len = source.read_u8()?;
137 let slots = source.read_many(len as usize)?;
138 Ok(Self::new(slots))
140 }
141}
142
143#[cfg(test)]
147mod tests {
148 use vm_core::{
149 Felt,
150 utils::{Deserializable, Serializable},
151 };
152
153 use super::AccountStorageHeader;
154 use crate::account::{AccountStorage, StorageSlotType};
155
156 #[test]
157 fn test_from_account_storage() {
158 let storage_map = AccountStorage::mock_map();
159
160 let slots = vec![
162 (StorageSlotType::Value, [Felt::new(1), Felt::new(2), Felt::new(3), Felt::new(4)]),
163 (StorageSlotType::Value, [Felt::new(5), Felt::new(6), Felt::new(7), Felt::new(8)]),
164 (StorageSlotType::Map, storage_map.root().into()),
165 ];
166
167 let expected_header = AccountStorageHeader { slots };
168 let account_storage = AccountStorage::mock();
169
170 assert_eq!(expected_header, AccountStorageHeader::from(&account_storage))
171 }
172
173 #[test]
174 fn test_serde_account_storage_header() {
175 let storage = AccountStorage::mock();
177 let storage_header = AccountStorageHeader::from(&storage);
178
179 let bytes = storage_header.to_bytes();
181 let deserialized = AccountStorageHeader::read_from_bytes(&bytes).unwrap();
182
183 assert_eq!(storage_header, deserialized);
185 }
186}