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, AccountType};
77 #[test]
78 fn test_as_word_layout() {
79 let id = AccountId::dummy([1u8; 15], AccountIdVersion::Version1, AccountType::Private);
80 let key = AccountIdKey::from(id);
81 let word = key.as_word();
82
83 assert_eq!(word[0], ZERO);
84 assert_eq!(word[1], ZERO);
85 assert_eq!(word[2], id.suffix());
86 assert_eq!(word[3], id.prefix().as_felt());
87 }
88
89 #[test]
90 fn test_roundtrip_word_conversion() {
91 let id = AccountId::dummy([1u8; 15], AccountIdVersion::Version1, AccountType::Private);
92
93 let key = AccountIdKey::from(id);
94 let recovered =
95 AccountIdKey::try_from_word(key.as_word()).expect("valid account id conversion");
96
97 assert_eq!(id, recovered);
98 }
99
100 #[test]
101 fn test_leaf_index_consistency() {
102 let id = AccountId::dummy([1u8; 15], AccountIdVersion::Version1, AccountType::Private);
103 let key = AccountIdKey::from(id);
104
105 let idx1 = key.to_leaf_index();
106 let idx2 = key.to_leaf_index();
107
108 assert_eq!(idx1, idx2);
109 }
110
111 #[test]
112 fn test_from_conversion() {
113 let id = AccountId::dummy([1u8; 15], AccountIdVersion::Version1, AccountType::Private);
114 let key: AccountIdKey = id.into();
115
116 assert_eq!(key.account_id(), id);
117 }
118
119 #[test]
120 fn test_multiple_roundtrips() {
121 for _ in 0..100 {
122 let id = AccountId::dummy([1u8; 15], AccountIdVersion::Version1, AccountType::Private);
123 let key = AccountIdKey::from(id);
124
125 let recovered =
126 AccountIdKey::try_from_word(key.as_word()).expect("valid account id conversion");
127
128 assert_eq!(id, recovered);
129 }
130 }
131}