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) -> usize {
81 self.slots.len()
82 }
83
84 pub fn slot(&self, index: usize) -> Result<&(StorageSlotType, Word), AccountError> {
89 self.slots.get(index).ok_or(AccountError::StorageIndexOutOfBounds {
90 slots_len: self.slots.len() as u8,
91 index: index as u8,
92 })
93 }
94
95 pub fn compute_commitment(&self) -> Digest {
98 Hasher::hash_elements(&self.as_elements())
99 }
100
101 pub fn as_elements(&self) -> Vec<Felt> {
109 self.slots
110 .iter()
111 .flat_map(|slot| StorageSlotHeader::new(slot).as_elements())
112 .collect()
113 }
114}
115
116impl From<&AccountStorage> for AccountStorageHeader {
117 fn from(value: &AccountStorage) -> Self {
118 value.to_header()
119 }
120}
121
122impl Serializable for AccountStorageHeader {
126 fn write_into<W: ByteWriter>(&self, target: &mut W) {
127 let len = self.slots.len() as u8;
128 target.write_u8(len);
129 target.write_many(self.slots())
130 }
131}
132
133impl Deserializable for AccountStorageHeader {
134 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
135 let len = source.read_u8()?;
136 let slots = source.read_many(len as usize)?;
137 Ok(Self::new(slots))
139 }
140}
141
142#[cfg(test)]
146mod tests {
147 use vm_core::{
148 Felt,
149 utils::{Deserializable, Serializable},
150 };
151
152 use super::AccountStorageHeader;
153 use crate::account::{AccountStorage, StorageSlotType};
154
155 #[test]
156 fn test_from_account_storage() {
157 let storage_map = AccountStorage::mock_map();
158
159 let slots = vec![
161 (StorageSlotType::Value, [Felt::new(1), Felt::new(2), Felt::new(3), Felt::new(4)]),
162 (StorageSlotType::Value, [Felt::new(5), Felt::new(6), Felt::new(7), Felt::new(8)]),
163 (StorageSlotType::Map, storage_map.root().into()),
164 ];
165
166 let expected_header = AccountStorageHeader { slots };
167 let account_storage = AccountStorage::mock();
168
169 assert_eq!(expected_header, AccountStorageHeader::from(&account_storage))
170 }
171
172 #[test]
173 fn test_serde_account_storage_header() {
174 let storage = AccountStorage::mock();
176 let storage_header = AccountStorageHeader::from(&storage);
177
178 let bytes = storage_header.to_bytes();
180 let deserialized = AccountStorageHeader::read_from_bytes(&bytes).unwrap();
181
182 assert_eq!(storage_header, deserialized);
184 }
185}