miden_protocol/block/account_tree/
account_id_key.rs1use miden_crypto::merkle::smt::LeafIndex;
2
3use super::AccountId;
4use crate::Word;
5use crate::crypto::merkle::smt::SMT_DEPTH;
6use crate::errors::AccountIdError;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub struct AccountIdKey(AccountId);
16
17impl AccountIdKey {
18 const KEY_SUFFIX_IDX: usize = 2;
20 const KEY_PREFIX_IDX: usize = 3;
21
22 pub fn new(id: AccountId) -> Self {
24 Self(id)
25 }
26
27 pub fn account_id(&self) -> AccountId {
29 self.0
30 }
31
32 pub fn as_word(&self) -> Word {
37 let mut key = Word::empty();
38
39 key[Self::KEY_SUFFIX_IDX] = self.0.suffix();
40 key[Self::KEY_PREFIX_IDX] = self.0.prefix().as_felt();
41
42 key
43 }
44
45 pub fn try_from_word(word: Word) -> Result<AccountId, AccountIdError> {
49 AccountId::try_from_elements(word[Self::KEY_SUFFIX_IDX], word[Self::KEY_PREFIX_IDX])
50 }
51
52 pub fn to_leaf_index(&self) -> LeafIndex<SMT_DEPTH> {
57 LeafIndex::from(self.as_word())
58 }
59}
60
61impl From<AccountId> for AccountIdKey {
62 fn from(id: AccountId) -> Self {
63 Self(id)
64 }
65}
66
67#[cfg(test)]
71mod tests {
72
73 use miden_core::ZERO;
74
75 use super::{AccountId, *};
76 use crate::account::{AccountIdVersion, AccountStorageMode, AccountType};
77 #[test]
78 fn test_as_word_layout() {
79 let id = AccountId::dummy(
80 [1u8; 15],
81 AccountIdVersion::Version0,
82 AccountType::RegularAccountImmutableCode,
83 AccountStorageMode::Private,
84 );
85 let key = AccountIdKey::from(id);
86 let word = key.as_word();
87
88 assert_eq!(word[0], ZERO);
89 assert_eq!(word[1], ZERO);
90 assert_eq!(word[2], id.suffix());
91 assert_eq!(word[3], id.prefix().as_felt());
92 }
93
94 #[test]
95 fn test_roundtrip_word_conversion() {
96 let id = AccountId::dummy(
97 [1u8; 15],
98 AccountIdVersion::Version0,
99 AccountType::RegularAccountImmutableCode,
100 AccountStorageMode::Private,
101 );
102
103 let key = AccountIdKey::from(id);
104 let recovered =
105 AccountIdKey::try_from_word(key.as_word()).expect("valid account id conversion");
106
107 assert_eq!(id, recovered);
108 }
109
110 #[test]
111 fn test_leaf_index_consistency() {
112 let id = AccountId::dummy(
113 [1u8; 15],
114 AccountIdVersion::Version0,
115 AccountType::RegularAccountImmutableCode,
116 AccountStorageMode::Private,
117 );
118 let key = AccountIdKey::from(id);
119
120 let idx1 = key.to_leaf_index();
121 let idx2 = key.to_leaf_index();
122
123 assert_eq!(idx1, idx2);
124 }
125
126 #[test]
127 fn test_from_conversion() {
128 let id = AccountId::dummy(
129 [1u8; 15],
130 AccountIdVersion::Version0,
131 AccountType::RegularAccountImmutableCode,
132 AccountStorageMode::Private,
133 );
134 let key: AccountIdKey = id.into();
135
136 assert_eq!(key.account_id(), id);
137 }
138
139 #[test]
140 fn test_multiple_roundtrips() {
141 for _ in 0..100 {
142 let id = AccountId::dummy(
143 [1u8; 15],
144 AccountIdVersion::Version0,
145 AccountType::RegularAccountImmutableCode,
146 AccountStorageMode::Private,
147 );
148 let key = AccountIdKey::from(id);
149
150 let recovered =
151 AccountIdKey::try_from_word(key.as_word()).expect("valid account id conversion");
152
153 assert_eq!(id, recovered);
154 }
155 }
156}