miden_objects/account/storage/map/
partial.rs

1use miden_core::utils::{Deserializable, Serializable};
2use miden_crypto::Word;
3use miden_crypto::merkle::{
4    InnerNodeInfo,
5    LeafIndex,
6    MerkleError,
7    PartialSmt,
8    SMT_DEPTH,
9    SmtLeaf,
10    SmtProof,
11};
12
13use crate::account::StorageMap;
14
15/// A partial representation of a [`StorageMap`], containing only proofs for a subset of the
16/// key-value pairs.
17///
18/// A partial storage map carries only the Merkle authentication data a transaction will need.
19/// Every included entry pairs a value with its proof, letting the transaction kernel verify reads
20/// (and prepare writes) without needing the complete tree.
21#[derive(Clone, Debug, PartialEq, Eq, Default)]
22pub struct PartialStorageMap {
23    partial_smt: PartialSmt,
24}
25
26impl PartialStorageMap {
27    // CONSTRUCTORS
28    // --------------------------------------------------------------------------------------------
29
30    /// Returns a new instance of partial storage map with the specified partial SMT.
31    pub fn new(partial_smt: PartialSmt) -> Self {
32        PartialStorageMap { partial_smt }
33    }
34
35    pub fn partial_smt(&self) -> &PartialSmt {
36        &self.partial_smt
37    }
38
39    pub fn root(&self) -> Word {
40        self.partial_smt.root()
41    }
42
43    /// Returns an opening of the leaf associated with `key`.
44    ///
45    /// Conceptually, an opening is a Merkle path to the leaf, as well as the leaf itself.
46    /// The key needs to be hashed to have a behavior in line with [`StorageMap`]. For more details
47    /// as to why this is needed, refer to the docs for that struct.
48    ///
49    /// # Errors
50    ///
51    /// Returns an error if:
52    /// - the key is not tracked by this partial storage map.
53    pub fn open(&self, key: &Word) -> Result<SmtProof, MerkleError> {
54        let key = StorageMap::hash_key(*key);
55        self.partial_smt.open(&key)
56    }
57
58    // ITERATORS
59    // --------------------------------------------------------------------------------------------
60
61    /// Returns an iterator over the leaves of the underlying [`PartialSmt`].
62    pub fn leaves(&self) -> impl Iterator<Item = (LeafIndex<SMT_DEPTH>, &SmtLeaf)> {
63        self.partial_smt.leaves()
64    }
65
66    /// Returns an iterator over the key value pairs of the map.
67    pub fn entries(&self) -> impl Iterator<Item = (Word, Word)> {
68        self.partial_smt.entries().copied()
69    }
70
71    /// Returns an iterator over the inner nodes of the underlying [`PartialSmt`].
72    pub fn inner_nodes(&self) -> impl Iterator<Item = InnerNodeInfo> + '_ {
73        self.partial_smt.inner_nodes()
74    }
75
76    // MUTATORS
77    // --------------------------------------------------------------------------------------------
78
79    /// Adds an [`SmtProof`] to this [`PartialStorageMap`].
80    pub fn add(&mut self, proof: SmtProof) -> Result<(), MerkleError> {
81        self.partial_smt.add_proof(proof)
82    }
83}
84
85impl From<StorageMap> for PartialStorageMap {
86    fn from(value: StorageMap) -> Self {
87        let v = value.smt;
88
89        PartialStorageMap { partial_smt: v.into() }
90    }
91}
92
93impl From<PartialSmt> for PartialStorageMap {
94    fn from(partial_smt: PartialSmt) -> Self {
95        PartialStorageMap { partial_smt }
96    }
97}
98
99impl Serializable for PartialStorageMap {
100    fn write_into<W: miden_core::utils::ByteWriter>(&self, target: &mut W) {
101        target.write(&self.partial_smt);
102    }
103}
104
105impl Deserializable for PartialStorageMap {
106    fn read_from<R: miden_core::utils::ByteReader>(
107        source: &mut R,
108    ) -> Result<Self, miden_processor::DeserializationError> {
109        let storage: PartialSmt = source.read()?;
110        Ok(PartialStorageMap { partial_smt: storage })
111    }
112}