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}