Skip to main content

miden_standards/account/mint_policies/
auth_controlled.rs

1use miden_protocol::Word;
2use miden_protocol::account::component::{
3    AccountComponentMetadata,
4    FeltSchema,
5    SchemaType,
6    StorageSchema,
7    StorageSlotSchema,
8};
9use miden_protocol::account::{
10    AccountComponent,
11    AccountType,
12    StorageMap,
13    StorageMapKey,
14    StorageSlot,
15    StorageSlotName,
16};
17use miden_protocol::utils::sync::LazyLock;
18
19use super::MintPolicyAuthority;
20use crate::account::components::auth_controlled_library;
21use crate::procedure_digest;
22
23// CONSTANTS
24// ================================================================================================
25
26procedure_digest!(
27    ALLOW_ALL_POLICY_ROOT,
28    AuthControlled::NAME,
29    AuthControlled::ALLOW_ALL_PROC_NAME,
30    auth_controlled_library
31);
32
33static ACTIVE_MINT_POLICY_PROC_ROOT_SLOT_NAME: LazyLock<StorageSlotName> = LazyLock::new(|| {
34    StorageSlotName::new("miden::standards::mint_policy_manager::active_policy_proc_root")
35        .expect("storage slot name should be valid")
36});
37static ALLOWED_MINT_POLICY_PROC_ROOTS_SLOT_NAME: LazyLock<StorageSlotName> = LazyLock::new(|| {
38    StorageSlotName::new("miden::standards::mint_policy_manager::allowed_policy_proc_roots")
39        .expect("storage slot name should be valid")
40});
41/// An [`AccountComponent`] providing configurable mint-policy management for network faucets.
42///
43/// It reexports policy procedures from `miden::standards::mint_policies` and manager procedures
44/// from `miden::standards::mint_policies::policy_manager`:
45/// - `allow_all`
46/// - `set_mint_policy`
47/// - `get_mint_policy`
48///
49/// ## Storage Layout
50///
51/// - [`Self::active_policy_proc_root_slot`]: Procedure root of the active mint policy.
52/// - [`Self::allowed_policy_proc_roots_slot`]: Set of allowed mint policy procedure roots.
53/// - [`Self::policy_authority_slot`]: Policy authority mode
54///   ([`MintPolicyAuthority::AuthControlled`] = tx auth, [`MintPolicyAuthority::OwnerControlled`] =
55///   external owner).
56#[derive(Debug, Clone, Copy)]
57pub struct AuthControlled {
58    initial_policy_root: Word,
59}
60
61/// Initial policy configuration for the [`AuthControlled`] component.
62#[derive(Debug, Clone, Copy, Default)]
63pub enum AuthControlledInitConfig {
64    /// Sets the initial policy to `allow_all`.
65    #[default]
66    AllowAll,
67    /// Sets a custom initial policy root.
68    CustomInitialRoot(Word),
69}
70
71impl AuthControlled {
72    /// The name of the component.
73    pub const NAME: &'static str = "miden::standards::components::mint_policies::auth_controlled";
74
75    const ALLOW_ALL_PROC_NAME: &str = "allow_all";
76
77    /// Creates a new [`AuthControlled`] component from the provided configuration.
78    pub fn new(policy: AuthControlledInitConfig) -> Self {
79        let initial_policy_root = match policy {
80            AuthControlledInitConfig::AllowAll => Self::allow_all_policy_root(),
81            AuthControlledInitConfig::CustomInitialRoot(root) => root,
82        };
83
84        Self { initial_policy_root }
85    }
86
87    /// Creates a new [`AuthControlled`] component with `allow_all` policy as
88    /// default.
89    pub fn allow_all() -> Self {
90        Self::new(AuthControlledInitConfig::AllowAll)
91    }
92
93    /// Returns the [`StorageSlotName`] where the active mint policy procedure root is stored.
94    pub fn active_policy_proc_root_slot() -> &'static StorageSlotName {
95        &ACTIVE_MINT_POLICY_PROC_ROOT_SLOT_NAME
96    }
97
98    /// Returns the [`StorageSlotName`] where allowed policy roots are stored.
99    pub fn allowed_policy_proc_roots_slot() -> &'static StorageSlotName {
100        &ALLOWED_MINT_POLICY_PROC_ROOTS_SLOT_NAME
101    }
102
103    /// Returns the storage slot schema for the active mint policy root.
104    pub fn active_policy_proc_root_slot_schema() -> (StorageSlotName, StorageSlotSchema) {
105        (
106            Self::active_policy_proc_root_slot().clone(),
107            StorageSlotSchema::value(
108                "The procedure root of the active mint policy in the mint policy auth controlled component",
109                [
110                    FeltSchema::felt("proc_root_0"),
111                    FeltSchema::felt("proc_root_1"),
112                    FeltSchema::felt("proc_root_2"),
113                    FeltSchema::felt("proc_root_3"),
114                ],
115            ),
116        )
117    }
118
119    /// Returns the storage slot schema for the allowed policy roots map.
120    pub fn allowed_policy_proc_roots_slot_schema() -> (StorageSlotName, StorageSlotSchema) {
121        (
122            Self::allowed_policy_proc_roots_slot().clone(),
123            StorageSlotSchema::map(
124                "The set of allowed mint policy procedure roots in the mint policy auth controlled component",
125                SchemaType::native_word(),
126                SchemaType::native_word(),
127            ),
128        )
129    }
130
131    /// Returns the [`StorageSlotName`] containing policy authority mode.
132    pub fn policy_authority_slot() -> &'static StorageSlotName {
133        MintPolicyAuthority::slot()
134    }
135
136    /// Returns the storage slot schema for policy authority mode.
137    pub fn policy_authority_slot_schema() -> (StorageSlotName, StorageSlotSchema) {
138        (
139            Self::policy_authority_slot().clone(),
140            StorageSlotSchema::value(
141                "Policy authority mode (AuthControlled = tx auth, OwnerControlled = external owner)",
142                [
143                    FeltSchema::u8("policy_authority"),
144                    FeltSchema::new_void(),
145                    FeltSchema::new_void(),
146                    FeltSchema::new_void(),
147                ],
148            ),
149        )
150    }
151
152    /// Returns the default `allow_all` policy root.
153    pub fn allow_all_policy_root() -> Word {
154        *ALLOW_ALL_POLICY_ROOT
155    }
156
157    /// Returns the policy authority used by this component.
158    pub fn mint_policy_authority(&self) -> MintPolicyAuthority {
159        MintPolicyAuthority::AuthControlled
160    }
161}
162
163impl Default for AuthControlled {
164    fn default() -> Self {
165        Self::allow_all()
166    }
167}
168
169impl From<AuthControlled> for AccountComponent {
170    fn from(auth_controlled: AuthControlled) -> Self {
171        let active_policy_proc_root_slot = StorageSlot::with_value(
172            AuthControlled::active_policy_proc_root_slot().clone(),
173            auth_controlled.initial_policy_root,
174        );
175        let allowed_policy_flag = Word::from([1u32, 0, 0, 0]);
176        let allow_all_policy_root = AuthControlled::allow_all_policy_root();
177
178        let mut allowed_policy_entries =
179            vec![(StorageMapKey::from_raw(allow_all_policy_root), allowed_policy_flag)];
180
181        if auth_controlled.initial_policy_root != allow_all_policy_root {
182            allowed_policy_entries.push((
183                StorageMapKey::from_raw(auth_controlled.initial_policy_root),
184                allowed_policy_flag,
185            ));
186        }
187
188        let allowed_policy_proc_roots = StorageMap::with_entries(allowed_policy_entries)
189            .expect("allowed mint policy roots should have unique keys");
190
191        let allowed_policy_proc_roots_slot = StorageSlot::with_map(
192            AuthControlled::allowed_policy_proc_roots_slot().clone(),
193            allowed_policy_proc_roots,
194        );
195        let policy_authority_slot = StorageSlot::from(auth_controlled.mint_policy_authority());
196
197        let storage_schema = StorageSchema::new(vec![
198            AuthControlled::active_policy_proc_root_slot_schema(),
199            AuthControlled::allowed_policy_proc_roots_slot_schema(),
200            AuthControlled::policy_authority_slot_schema(),
201        ])
202        .expect("storage schema should be valid");
203
204        let metadata =
205            AccountComponentMetadata::new(AuthControlled::NAME, [AccountType::FungibleFaucet])
206                .with_description(
207                    "Mint policy auth controlled component for network fungible faucets",
208                )
209                .with_storage_schema(storage_schema);
210
211        AccountComponent::new(
212            auth_controlled_library(),
213            vec![
214                active_policy_proc_root_slot,
215                allowed_policy_proc_roots_slot,
216                policy_authority_slot,
217            ],
218            metadata,
219        )
220        .expect(
221            "mint policy auth controlled component should satisfy the requirements of a valid account component",
222        )
223    }
224}