miden_lib/account/auth/
mod.rs1use alloc::{string::ToString, vec::Vec};
2
3use miden_objects::{
4 AccountError, Digest, Felt, FieldElement,
5 account::{AccountCode, AccountComponent, StorageMap, StorageSlot},
6 crypto::dsa::rpo_falcon512::PublicKey,
7};
8
9use crate::account::components::{
10 no_auth_library, rpo_falcon_512_library, rpo_falcon_512_procedure_acl_library,
11};
12
13pub struct RpoFalcon512 {
27 public_key: PublicKey,
28}
29
30impl RpoFalcon512 {
31 pub fn new(public_key: PublicKey) -> Self {
33 Self { public_key }
34 }
35}
36
37impl From<RpoFalcon512> for AccountComponent {
38 fn from(falcon: RpoFalcon512) -> Self {
39 AccountComponent::new(
40 rpo_falcon_512_library(),
41 vec![StorageSlot::Value(falcon.public_key.into())],
42 )
43 .expect("falcon component should satisfy the requirements of a valid account component")
44 .with_supports_all_types()
45 }
46}
47
48pub struct RpoFalcon512ProcedureAcl {
68 public_key: PublicKey,
69 auth_trigger_procedures: Vec<Digest>,
70}
71
72impl RpoFalcon512ProcedureAcl {
73 pub fn new(
79 public_key: PublicKey,
80 auth_trigger_procedures: Vec<Digest>,
81 ) -> Result<Self, AccountError> {
82 let max_procedures = AccountCode::MAX_NUM_PROCEDURES;
83 if auth_trigger_procedures.len() > max_procedures {
84 return Err(AccountError::AssumptionViolated(
85 "Cannot track more than {max_procedures} procedures (account limit)".to_string(),
86 ));
87 }
88
89 Ok(Self { public_key, auth_trigger_procedures })
90 }
91}
92
93impl From<RpoFalcon512ProcedureAcl> for AccountComponent {
94 fn from(falcon: RpoFalcon512ProcedureAcl) -> Self {
95 let mut storage_slots = Vec::with_capacity(3);
96
97 storage_slots.push(StorageSlot::Value(falcon.public_key.into()));
99
100 let num_procs = Felt::from(falcon.auth_trigger_procedures.len() as u32);
102 storage_slots.push(StorageSlot::Value([num_procs, Felt::ZERO, Felt::ZERO, Felt::ZERO]));
103
104 let map_entries =
108 falcon.auth_trigger_procedures.iter().enumerate().map(|(i, proc_root)| {
109 (
110 [Felt::from(i as u32), Felt::ZERO, Felt::ZERO, Felt::ZERO].into(),
111 proc_root.into(),
112 )
113 });
114
115 storage_slots.push(StorageSlot::Map(StorageMap::with_entries(map_entries).unwrap()));
117
118 AccountComponent::new(rpo_falcon_512_procedure_acl_library(), storage_slots)
119 .expect("Procedure ACL auth component should satisfy the requirements of a valid account component")
120 .with_supports_all_types()
121 }
122}
123
124pub struct NoAuth;
139
140impl NoAuth {
141 pub fn new() -> Self {
143 Self
144 }
145}
146
147impl Default for NoAuth {
148 fn default() -> Self {
149 Self::new()
150 }
151}
152
153impl From<NoAuth> for AccountComponent {
154 fn from(_: NoAuth) -> Self {
155 AccountComponent::new(no_auth_library(), vec![])
156 .expect("NoAuth component should satisfy the requirements of a valid account component")
157 .with_supports_all_types()
158 }
159}
160
161#[cfg(test)]
165mod tests {
166 use miden_objects::{Word, ZERO, account::AccountBuilder};
167
168 use super::*;
169 use crate::account::{components::basic_wallet_library, wallets::BasicWallet};
170
171 #[test]
172 fn test_rpo_falcon_512_procedure_acl_no_procedures() {
173 let public_key = PublicKey::new([ZERO; 4]);
174 let component =
175 RpoFalcon512ProcedureAcl::new(public_key, vec![]).expect("component creation failed");
176
177 let (account, _) = AccountBuilder::new([0; 32])
178 .with_auth_component(component)
179 .with_component(BasicWallet)
180 .build()
181 .expect("account building failed");
182
183 let public_key_slot = account.storage().get_item(0).expect("storage slot 0 access failed");
184 assert_eq!(public_key_slot, Word::from(public_key).into());
185
186 let num_procs_slot = account.storage().get_item(1).expect("storage slot 1 access failed");
187 assert_eq!(num_procs_slot, [Felt::ZERO, Felt::ZERO, Felt::ZERO, Felt::ZERO].into());
188
189 let proc_root = account
190 .storage()
191 .get_map_item(2, [Felt::ZERO, Felt::ZERO, Felt::ZERO, Felt::ZERO])
192 .expect("storage map access failed");
193 assert_eq!(proc_root, Word::default());
195 }
196
197 #[test]
198 fn test_rpo_falcon_512_procedure_acl_with_two_procedures() {
199 let public_key = PublicKey::new([ZERO; 4]);
200
201 let auth_trigger_procedures: Vec<Digest> = basic_wallet_library()
205 .module_infos()
206 .next()
207 .expect("at least one module expected")
208 .procedures()
209 .map(|(_, proc_info)| proc_info.digest)
210 .collect();
211
212 assert_eq!(auth_trigger_procedures.len(), 2);
213
214 let component = RpoFalcon512ProcedureAcl::new(public_key, auth_trigger_procedures.clone())
215 .expect("component creation failed");
216
217 let (account, _) = AccountBuilder::new([0; 32])
218 .with_auth_component(component)
219 .with_component(BasicWallet)
220 .build()
221 .expect("account building failed");
222
223 let public_key_slot = account.storage().get_item(0).expect("storage slot 0 access failed");
224 assert_eq!(public_key_slot, Word::from(public_key).into());
225
226 let num_procs_slot = account.storage().get_item(1).expect("storage slot 1 access failed");
227 assert_eq!(num_procs_slot, [Felt::new(2), Felt::ZERO, Felt::ZERO, Felt::ZERO].into());
228
229 let proc_root_0 = account
230 .storage()
231 .get_map_item(2, [Felt::ZERO, Felt::ZERO, Felt::ZERO, Felt::ZERO])
232 .expect("storage map access failed");
233 assert_eq!(proc_root_0, Word::from(auth_trigger_procedures[0]));
234
235 let proc_root_1 = account
236 .storage()
237 .get_map_item(2, [Felt::ONE, Felt::ZERO, Felt::ZERO, Felt::ZERO])
238 .expect("storage map access failed");
239 assert_eq!(proc_root_1, Word::from(auth_trigger_procedures[1]));
240 }
241
242 #[test]
243 fn test_no_auth_component() {
244 let (_account, _) = AccountBuilder::new([0; 32])
246 .with_auth_component(NoAuth)
247 .with_component(BasicWallet)
248 .build()
249 .expect("account building failed");
250 }
251}