Skip to main content

miden_standards/account/components/
mod.rs

1use alloc::collections::BTreeSet;
2use alloc::vec::Vec;
3
4use miden_processor::mast::MastNodeExt;
5use miden_protocol::Word;
6use miden_protocol::account::AccountProcedureRoot;
7use miden_protocol::assembly::{Library, LibraryExport};
8use miden_protocol::utils::serde::Deserializable;
9use miden_protocol::utils::sync::LazyLock;
10
11use crate::account::interface::AccountComponentInterface;
12
13// WALLET LIBRARIES
14// ================================================================================================
15
16// Initialize the Basic Wallet library only once.
17static BASIC_WALLET_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
18    let bytes = include_bytes!(concat!(
19        env!("OUT_DIR"),
20        "/assets/account_components/wallets/basic_wallet.masl"
21    ));
22    Library::read_from_bytes(bytes).expect("Shipped Basic Wallet library is well-formed")
23});
24
25// ACCESS LIBRARIES
26// ================================================================================================
27
28// Initialize the Ownable2Step library only once.
29static OWNABLE2STEP_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
30    let bytes = include_bytes!(concat!(
31        env!("OUT_DIR"),
32        "/assets/account_components/access/ownable2step.masl"
33    ));
34    Library::read_from_bytes(bytes).expect("Shipped Ownable2Step library is well-formed")
35});
36
37// AUTH LIBRARIES
38// ================================================================================================
39
40/// Initialize the ECDSA K256 Keccak library only once.
41static SINGLESIG_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
42    let bytes =
43        include_bytes!(concat!(env!("OUT_DIR"), "/assets/account_components/auth/singlesig.masl"));
44    Library::read_from_bytes(bytes).expect("Shipped Singlesig library is well-formed")
45});
46
47// Initialize the ECDSA K256 Keccak ACL library only once.
48static SINGLESIG_ACL_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
49    let bytes = include_bytes!(concat!(
50        env!("OUT_DIR"),
51        "/assets/account_components/auth/singlesig_acl.masl"
52    ));
53    Library::read_from_bytes(bytes).expect("Shipped Singlesig ACL library is well-formed")
54});
55
56/// Initialize the Multisig library only once.
57static MULTISIG_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
58    let bytes =
59        include_bytes!(concat!(env!("OUT_DIR"), "/assets/account_components/auth/multisig.masl"));
60    Library::read_from_bytes(bytes).expect("Shipped Multisig library is well-formed")
61});
62
63/// Initialize the Multisig PSM library only once.
64static MULTISIG_PSM_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
65    let bytes = include_bytes!(concat!(
66        env!("OUT_DIR"),
67        "/assets/account_components/auth/multisig_psm.masl"
68    ));
69    Library::read_from_bytes(bytes).expect("Shipped Multisig PSM library is well-formed")
70});
71
72// Initialize the NoAuth library only once.
73static NO_AUTH_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
74    let bytes =
75        include_bytes!(concat!(env!("OUT_DIR"), "/assets/account_components/auth/no_auth.masl"));
76    Library::read_from_bytes(bytes).expect("Shipped NoAuth library is well-formed")
77});
78
79// FAUCET LIBRARIES
80// ================================================================================================
81
82// Initialize the Basic Fungible Faucet library only once.
83static BASIC_FUNGIBLE_FAUCET_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
84    let bytes = include_bytes!(concat!(
85        env!("OUT_DIR"),
86        "/assets/account_components/faucets/basic_fungible_faucet.masl"
87    ));
88    Library::read_from_bytes(bytes).expect("Shipped Basic Fungible Faucet library is well-formed")
89});
90
91// Initialize the Network Fungible Faucet library only once.
92static NETWORK_FUNGIBLE_FAUCET_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
93    let bytes = include_bytes!(concat!(
94        env!("OUT_DIR"),
95        "/assets/account_components/faucets/network_fungible_faucet.masl"
96    ));
97    Library::read_from_bytes(bytes).expect("Shipped Network Fungible Faucet library is well-formed")
98});
99
100// Initialize the Mint Policy Owner Controlled library only once.
101static MINT_POLICY_OWNER_CONTROLLED_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
102    let bytes = include_bytes!(concat!(
103        env!("OUT_DIR"),
104        "/assets/account_components/mint_policies/owner_controlled.masl"
105    ));
106    Library::read_from_bytes(bytes)
107        .expect("Shipped Mint Policy Owner Controlled library is well-formed")
108});
109
110// Initialize the Mint Policy Auth Controlled library only once.
111static MINT_POLICY_AUTH_CONTROLLED_LIBRARY: LazyLock<Library> = LazyLock::new(|| {
112    let bytes = include_bytes!(concat!(
113        env!("OUT_DIR"),
114        "/assets/account_components/mint_policies/auth_controlled.masl"
115    ));
116    Library::read_from_bytes(bytes)
117        .expect("Shipped Mint Policy Auth Controlled library is well-formed")
118});
119
120// METADATA LIBRARIES
121// ================================================================================================
122
123/// Returns the Basic Wallet Library.
124pub fn basic_wallet_library() -> Library {
125    BASIC_WALLET_LIBRARY.clone()
126}
127
128/// Returns the Ownable2Step Library.
129pub fn ownable2step_library() -> Library {
130    OWNABLE2STEP_LIBRARY.clone()
131}
132
133/// Returns the Basic Fungible Faucet Library.
134pub fn basic_fungible_faucet_library() -> Library {
135    BASIC_FUNGIBLE_FAUCET_LIBRARY.clone()
136}
137
138/// Returns the Network Fungible Faucet Library.
139pub fn network_fungible_faucet_library() -> Library {
140    NETWORK_FUNGIBLE_FAUCET_LIBRARY.clone()
141}
142
143/// Returns the Mint Policy Owner Controlled Library.
144pub fn owner_controlled_library() -> Library {
145    MINT_POLICY_OWNER_CONTROLLED_LIBRARY.clone()
146}
147
148/// Returns the Mint Policy Auth Controlled Library.
149pub fn auth_controlled_library() -> Library {
150    MINT_POLICY_AUTH_CONTROLLED_LIBRARY.clone()
151}
152
153/// Returns the Singlesig Library.
154pub fn singlesig_library() -> Library {
155    SINGLESIG_LIBRARY.clone()
156}
157
158/// Returns the Singlesig ACL Library.
159pub fn singlesig_acl_library() -> Library {
160    SINGLESIG_ACL_LIBRARY.clone()
161}
162
163/// Returns the Multisig Library.
164pub fn multisig_library() -> Library {
165    MULTISIG_LIBRARY.clone()
166}
167
168/// Returns the Multisig PSM Library.
169pub fn multisig_psm_library() -> Library {
170    MULTISIG_PSM_LIBRARY.clone()
171}
172
173/// Returns the NoAuth Library.
174pub fn no_auth_library() -> Library {
175    NO_AUTH_LIBRARY.clone()
176}
177
178// STANDARD ACCOUNT COMPONENTS
179// ================================================================================================
180
181/// The enum holding the types of standard account components defined in the `miden-standards`
182/// crate.
183pub enum StandardAccountComponent {
184    BasicWallet,
185    BasicFungibleFaucet,
186    NetworkFungibleFaucet,
187    AuthSingleSig,
188    AuthSingleSigAcl,
189    AuthMultisig,
190    AuthMultisigPsm,
191    AuthNoAuth,
192}
193
194impl StandardAccountComponent {
195    /// Returns the iterator over digests of all procedures exported from the component.
196    pub fn procedure_digests(&self) -> impl Iterator<Item = Word> {
197        let library = match self {
198            Self::BasicWallet => BASIC_WALLET_LIBRARY.as_ref(),
199            Self::BasicFungibleFaucet => BASIC_FUNGIBLE_FAUCET_LIBRARY.as_ref(),
200            Self::NetworkFungibleFaucet => NETWORK_FUNGIBLE_FAUCET_LIBRARY.as_ref(),
201            Self::AuthSingleSig => SINGLESIG_LIBRARY.as_ref(),
202            Self::AuthSingleSigAcl => SINGLESIG_ACL_LIBRARY.as_ref(),
203            Self::AuthMultisig => MULTISIG_LIBRARY.as_ref(),
204            Self::AuthMultisigPsm => MULTISIG_PSM_LIBRARY.as_ref(),
205            Self::AuthNoAuth => NO_AUTH_LIBRARY.as_ref(),
206        };
207
208        library
209            .exports()
210            .filter(|export| matches!(export, LibraryExport::Procedure(_)))
211            .map(|proc_export| {
212                library
213                    .mast_forest()
214                    .get_node_by_id(proc_export.unwrap_procedure().node)
215                    .expect("export node not in the forest")
216                    .digest()
217            })
218    }
219
220    /// Checks whether procedures from the current component are present in the procedures map
221    /// and if so it removes these procedures from this map and pushes the corresponding component
222    /// interface to the component interface vector.
223    fn extract_component(
224        &self,
225        procedures_set: &mut BTreeSet<AccountProcedureRoot>,
226        component_interface_vec: &mut Vec<AccountComponentInterface>,
227    ) {
228        // Determine if this component should be extracted based on procedure matching
229        if self.procedure_digests().all(|proc_digest| {
230            procedures_set.contains(&AccountProcedureRoot::from_raw(proc_digest))
231        }) {
232            // Remove the procedure root of any matching procedure.
233            self.procedure_digests().for_each(|component_procedure| {
234                procedures_set.remove(&AccountProcedureRoot::from_raw(component_procedure));
235            });
236
237            // Create the appropriate component interface
238            match self {
239                Self::BasicWallet => {
240                    component_interface_vec.push(AccountComponentInterface::BasicWallet)
241                },
242                Self::BasicFungibleFaucet => {
243                    component_interface_vec.push(AccountComponentInterface::BasicFungibleFaucet)
244                },
245                Self::NetworkFungibleFaucet => {
246                    component_interface_vec.push(AccountComponentInterface::NetworkFungibleFaucet)
247                },
248                Self::AuthSingleSig => {
249                    component_interface_vec.push(AccountComponentInterface::AuthSingleSig)
250                },
251                Self::AuthSingleSigAcl => {
252                    component_interface_vec.push(AccountComponentInterface::AuthSingleSigAcl)
253                },
254                Self::AuthMultisig => {
255                    component_interface_vec.push(AccountComponentInterface::AuthMultisig)
256                },
257                Self::AuthMultisigPsm => {
258                    component_interface_vec.push(AccountComponentInterface::AuthMultisigPsm)
259                },
260                Self::AuthNoAuth => {
261                    component_interface_vec.push(AccountComponentInterface::AuthNoAuth)
262                },
263            }
264        }
265    }
266
267    /// Gets all standard components which could be constructed from the provided procedures map
268    /// and pushes them to the `component_interface_vec`.
269    pub fn extract_standard_components(
270        procedures_set: &mut BTreeSet<AccountProcedureRoot>,
271        component_interface_vec: &mut Vec<AccountComponentInterface>,
272    ) {
273        Self::BasicWallet.extract_component(procedures_set, component_interface_vec);
274        Self::BasicFungibleFaucet.extract_component(procedures_set, component_interface_vec);
275        Self::NetworkFungibleFaucet.extract_component(procedures_set, component_interface_vec);
276        Self::AuthSingleSig.extract_component(procedures_set, component_interface_vec);
277        Self::AuthSingleSigAcl.extract_component(procedures_set, component_interface_vec);
278        Self::AuthMultisigPsm.extract_component(procedures_set, component_interface_vec);
279        Self::AuthMultisig.extract_component(procedures_set, component_interface_vec);
280        Self::AuthNoAuth.extract_component(procedures_set, component_interface_vec);
281    }
282}