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}