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::{rpo_falcon_512_library, rpo_falcon_512_procedure_acl_library};
10
11pub struct RpoFalcon512 {
25 public_key: PublicKey,
26}
27
28impl RpoFalcon512 {
29 pub fn new(public_key: PublicKey) -> Self {
31 Self { public_key }
32 }
33}
34
35impl From<RpoFalcon512> for AccountComponent {
36 fn from(falcon: RpoFalcon512) -> Self {
37 AccountComponent::new(
38 rpo_falcon_512_library(),
39 vec![StorageSlot::Value(falcon.public_key.into())],
40 )
41 .expect("falcon component should satisfy the requirements of a valid account component")
42 .with_supports_all_types()
43 }
44}
45
46pub struct RpoFalcon512ProcedureAcl {
66 public_key: PublicKey,
67 auth_trigger_procedures: Vec<Digest>,
68}
69
70impl RpoFalcon512ProcedureAcl {
71 pub fn new(
77 public_key: PublicKey,
78 auth_trigger_procedures: Vec<Digest>,
79 ) -> Result<Self, AccountError> {
80 let max_procedures = AccountCode::MAX_NUM_PROCEDURES;
81 if auth_trigger_procedures.len() > max_procedures {
82 return Err(AccountError::AssumptionViolated(
83 "Cannot track more than {max_procedures} procedures (account limit)".to_string(),
84 ));
85 }
86
87 Ok(Self { public_key, auth_trigger_procedures })
88 }
89}
90
91impl From<RpoFalcon512ProcedureAcl> for AccountComponent {
92 fn from(falcon: RpoFalcon512ProcedureAcl) -> Self {
93 let mut storage_slots = Vec::with_capacity(3);
94
95 storage_slots.push(StorageSlot::Value(falcon.public_key.into()));
97
98 let num_procs = Felt::from(falcon.auth_trigger_procedures.len() as u32);
100 storage_slots.push(StorageSlot::Value([num_procs, Felt::ZERO, Felt::ZERO, Felt::ZERO]));
101
102 let map_entries =
106 falcon.auth_trigger_procedures.iter().enumerate().map(|(i, proc_root)| {
107 (
108 [Felt::from(i as u32), Felt::ZERO, Felt::ZERO, Felt::ZERO].into(),
109 proc_root.into(),
110 )
111 });
112
113 storage_slots.push(StorageSlot::Map(StorageMap::with_entries(map_entries).unwrap()));
115
116 AccountComponent::new(rpo_falcon_512_procedure_acl_library(), storage_slots)
117 .expect("Procedure ACL auth component should satisfy the requirements of a valid account component")
118 .with_supports_all_types()
119 }
120}
121
122#[cfg(test)]
126mod tests {
127 use miden_objects::{Word, ZERO, account::AccountBuilder};
128
129 use super::*;
130 use crate::account::{components::basic_wallet_library, wallets::BasicWallet};
131
132 #[test]
133 fn test_rpo_falcon_512_procedure_acl_no_procedures() {
134 let public_key = PublicKey::new([ZERO; 4]);
135 let component =
136 RpoFalcon512ProcedureAcl::new(public_key, vec![]).expect("component creation failed");
137
138 let (account, _) = AccountBuilder::new([0; 32])
139 .with_auth_component(component)
140 .with_component(BasicWallet)
141 .build()
142 .expect("account building failed");
143
144 let public_key_slot = account.storage().get_item(0).expect("storage slot 0 access failed");
145 assert_eq!(public_key_slot, Word::from(public_key).into());
146
147 let num_procs_slot = account.storage().get_item(1).expect("storage slot 1 access failed");
148 assert_eq!(num_procs_slot, [Felt::ZERO, Felt::ZERO, Felt::ZERO, Felt::ZERO].into());
149
150 let proc_root = account
151 .storage()
152 .get_map_item(2, [Felt::ZERO, Felt::ZERO, Felt::ZERO, Felt::ZERO])
153 .expect("storage map access failed");
154 assert_eq!(proc_root, Word::default());
156 }
157
158 #[test]
159 fn test_rpo_falcon_512_procedure_acl_with_two_procedures() {
160 let public_key = PublicKey::new([ZERO; 4]);
161
162 let auth_trigger_procedures: Vec<Digest> = basic_wallet_library()
166 .module_infos()
167 .next()
168 .expect("at least one module expected")
169 .procedures()
170 .map(|(_, proc_info)| proc_info.digest)
171 .collect();
172
173 assert_eq!(auth_trigger_procedures.len(), 2);
174
175 let component = RpoFalcon512ProcedureAcl::new(public_key, auth_trigger_procedures.clone())
176 .expect("component creation failed");
177
178 let (account, _) = AccountBuilder::new([0; 32])
179 .with_auth_component(component)
180 .with_component(BasicWallet)
181 .build()
182 .expect("account building failed");
183
184 let public_key_slot = account.storage().get_item(0).expect("storage slot 0 access failed");
185 assert_eq!(public_key_slot, Word::from(public_key).into());
186
187 let num_procs_slot = account.storage().get_item(1).expect("storage slot 1 access failed");
188 assert_eq!(num_procs_slot, [Felt::new(2), Felt::ZERO, Felt::ZERO, Felt::ZERO].into());
189
190 let proc_root_0 = account
191 .storage()
192 .get_map_item(2, [Felt::ZERO, Felt::ZERO, Felt::ZERO, Felt::ZERO])
193 .expect("storage map access failed");
194 assert_eq!(proc_root_0, Word::from(auth_trigger_procedures[0]));
195
196 let proc_root_1 = account
197 .storage()
198 .get_map_item(2, [Felt::ONE, Felt::ZERO, Felt::ZERO, Felt::ZERO])
199 .expect("storage map access failed");
200 assert_eq!(proc_root_1, Word::from(auth_trigger_procedures[1]));
201 }
202}