Skip to main content

miden_protocol/account/storage/map/
key.rs

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