Skip to main content

miden_protocol/account/storage/map/
key.rs

1use alloc::string::String;
2
3use miden_crypto::merkle::smt::{LeafIndex, SMT_DEPTH};
4use miden_protocol_macros::WordWrapper;
5
6use crate::utils::serde::{
7    ByteReader,
8    ByteWriter,
9    Deserializable,
10    DeserializationError,
11    Serializable,
12};
13use crate::{Felt, Hasher, Word};
14
15// STORAGE MAP KEY
16// ================================================================================================
17
18/// A raw, user-chosen key for a [`StorageMap`](super::StorageMap).
19///
20/// Storage map keys are user-chosen and thus not necessarily uniformly distributed. To mitigate
21/// potential tree imbalance, keys are hashed before being inserted into the underlying SMT.
22///
23/// Use [`StorageMapKey::hash`] to produce the corresponding [`StorageMapKeyHash`] that is used
24/// in the SMT.
25#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, WordWrapper)]
26pub struct StorageMapKey(Word);
27
28impl StorageMapKey {
29    // CONSTANTS
30    // --------------------------------------------------------------------------------------------
31
32    /// The serialized size of the map key in bytes.
33    pub const SERIALIZED_SIZE: usize = Word::SERIALIZED_SIZE;
34
35    // CONSTRUCTORS
36    // --------------------------------------------------------------------------------------------
37
38    /// Creates a new [`StorageMapKey`] from the given word.
39    pub fn new(word: Word) -> Self {
40        Self::from_raw(word)
41    }
42
43    /// Returns the storage map key based on an empty word.
44    pub fn empty() -> Self {
45        Self::from_raw(Word::empty())
46    }
47
48    /// Creates a [`StorageMapKey`] from a `u32` index.
49    ///
50    /// This is a convenience constructor for the common pattern of using sequential indices
51    /// as storage map keys, producing a key of `[idx, 0, 0, 0]`.
52    pub fn from_index(idx: u32) -> Self {
53        Self::from_raw(Word::from([idx, 0, 0, 0]))
54    }
55
56    // PUBLIC ACCESSORS
57    // --------------------------------------------------------------------------------------------
58
59    /// Hashes this raw map key to produce a [`StorageMapKeyHash`].
60    ///
61    /// Storage map keys are hashed before being inserted into the SMT to ensure a uniform
62    /// key distribution.
63    pub fn hash(&self) -> StorageMapKeyHash {
64        StorageMapKeyHash::from_raw(Hasher::hash_elements(self.0.as_elements()))
65    }
66}
67
68impl From<StorageMapKey> for Word {
69    fn from(key: StorageMapKey) -> Self {
70        key.0
71    }
72}
73
74impl core::fmt::Display for StorageMapKey {
75    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
76        f.write_fmt(format_args!("{}", self.as_word()))
77    }
78}
79
80impl Serializable for StorageMapKey {
81    fn write_into<W: ByteWriter>(&self, target: &mut W) {
82        target.write_many(self.as_word());
83    }
84
85    fn get_size_hint(&self) -> usize {
86        Self::SERIALIZED_SIZE
87    }
88}
89
90impl Deserializable for StorageMapKey {
91    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
92        let key = source.read()?;
93        Ok(StorageMapKey::from_raw(key))
94    }
95}
96
97// STORAGE MAP KEY HASH
98// ================================================================================================
99
100/// A hashed key for a [`StorageMap`](super::StorageMap).
101///
102/// This is produced by hashing a [`StorageMapKey`] and is used as the actual key in the
103/// underlying SMT. Wrapping the hashed key in a distinct type prevents accidentally using a raw
104/// key where a hashed key is expected and vice-versa.
105#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, WordWrapper)]
106pub struct StorageMapKeyHash(Word);
107
108impl StorageMapKeyHash {
109    /// Returns the leaf index in the SMT for this hashed key.
110    pub fn to_leaf_index(&self) -> LeafIndex<SMT_DEPTH> {
111        self.0.into()
112    }
113}
114
115impl From<StorageMapKeyHash> for Word {
116    fn from(key: StorageMapKeyHash) -> Self {
117        key.0
118    }
119}
120
121impl From<StorageMapKey> for StorageMapKeyHash {
122    fn from(key: StorageMapKey) -> Self {
123        key.hash()
124    }
125}