miden_objects/account/storage/
partial.rs

1use alloc::vec::Vec;
2
3use miden_crypto::merkle::SmtProof;
4use vm_core::utils::{Deserializable, Serializable};
5use vm_processor::Digest;
6
7use super::{AccountStorage, AccountStorageHeader, StorageSlot};
8use crate::AccountError;
9
10/// A partial representation of an account storage, containing only a subset of the storage data.
11///
12/// Partial storage is used to provide verifiable access to specific segments of account storage
13/// without the need to provide the full storage data. It contains all needed parts for loading
14/// account storage data into the transaction kernel.
15#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct PartialStorage {
17    /// Commitment of the account's storage slots.
18    commitment: Digest,
19    /// Account's storage heaer, containing top-level slot values.
20    header: AccountStorageHeader,
21    /// Merkle proofs for a subset of the account's storage maps keys
22    storage_map_proofs: Vec<SmtProof>,
23}
24
25impl PartialStorage {
26    /// Returns a new instance of partial storage with the specified header and storage map proofs.
27    ///
28    /// The storage commitment is computed during instantiation based on the provided header.
29    pub fn new(header: AccountStorageHeader, storage_map_proofs: Vec<SmtProof>) -> Self {
30        let commitment = header.compute_commitment();
31        PartialStorage { header, storage_map_proofs, commitment }
32    }
33
34    /// Returns a reference to the storage map proofs of this partial storage.
35    pub fn storage_map_proofs(&self) -> &[SmtProof] {
36        &self.storage_map_proofs
37    }
38
39    /// Returns a reference to the header of this partial storage.
40    pub fn header(&self) -> &AccountStorageHeader {
41        &self.header
42    }
43
44    /// Returns the commitment of this partial storage.
45    pub fn commitment(&self) -> Digest {
46        self.commitment
47    }
48
49    /// Returns the value of the storage slot at the specified slot index.
50    ///
51    /// # Errors:
52    /// - If the index is out of bounds
53    pub fn get_item(&self, index: u8) -> Result<Digest, AccountError> {
54        self.header.slot(index as usize).map(|(_type, value)| value.into())
55    }
56
57    // TODO: Add from account storage with (slot/[key])?
58}
59
60impl From<&AccountStorage> for PartialStorage {
61    /// Converts a full account storage into a partial storage representation.
62    ///
63    /// This creates a partial storage that contains proofs for all key-value pairs
64    /// in all map slots of the account storage.
65    fn from(account_storage: &AccountStorage) -> Self {
66        let mut storage_map_proofs = Vec::with_capacity(account_storage.slots().len());
67        for slot in account_storage.slots() {
68            if let StorageSlot::Map(map) = slot {
69                let proofs: Vec<SmtProof> = map.entries().map(|(key, _)| map.open(key)).collect();
70                storage_map_proofs.extend(proofs);
71            }
72        }
73
74        let header: AccountStorageHeader = account_storage.to_header();
75        let commitment = header.compute_commitment();
76        PartialStorage { header, storage_map_proofs, commitment }
77    }
78}
79
80impl Serializable for PartialStorage {
81    fn write_into<W: vm_core::utils::ByteWriter>(&self, target: &mut W) {
82        target.write(&self.header);
83        target.write(&self.storage_map_proofs);
84    }
85}
86
87impl Deserializable for PartialStorage {
88    fn read_from<R: vm_core::utils::ByteReader>(
89        source: &mut R,
90    ) -> Result<Self, vm_processor::DeserializationError> {
91        let header: AccountStorageHeader = source.read()?;
92        let storage_map_proofs: Vec<SmtProof> = source.read()?;
93
94        let commitment = header.compute_commitment();
95
96        Ok(PartialStorage { header, storage_map_proofs, commitment })
97    }
98}