Skip to main content

miden_standards/account/policies/transfer/
basic_blocklist.rs

1use alloc::collections::BTreeSet;
2
3use miden_protocol::account::component::{
4    AccountComponentCode,
5    AccountComponentMetadata,
6    StorageSchema,
7};
8use miden_protocol::account::{AccountComponent, AccountId, AccountProcedureRoot};
9
10use crate::account::account_component_code;
11use crate::account::policies::transfer::blocklist::BlocklistStorage;
12use crate::procedure_root;
13
14// BASIC BLOCKLIST TRANSFER POLICY
15// ================================================================================================
16
17account_component_code!(
18    BASIC_BLOCKLIST_TRANSFER_POLICY_CODE,
19    "faucets/policies/transfer/basic_blocklist.masl"
20);
21
22procedure_root!(
23    BASIC_BLOCKLIST_TRANSFER_POLICY_ROOT,
24    BasicBlocklist::NAME,
25    BasicBlocklist::PROC_NAME,
26    BasicBlocklist::code()
27);
28
29/// The basic blocklist transfer policy account component.
30///
31/// Installs the per-faucet `blocked_accounts` storage map (defined by [`BlocklistStorage`])
32/// plus the `check_policy` predicate procedure. Pair with a
33/// [`crate::account::policies::TokenPolicyManager`] whose send / receive policy maps include
34/// [`BasicBlocklist::root`]. When active, transfers fail if the native account (asset
35/// recipient or note creator) is currently blocked on the issuing faucet.
36///
37/// The wrapped [`BTreeSet<AccountId>`] captures the initial blocklist contents (it can be
38/// empty for a faucet that starts unblocked). Use [`Default`] for an empty blocklist or
39/// [`Self::with_blocked_accounts`] to seed the storage map at component construction time.
40///
41/// Block / unblock administration is intentionally not part of this component. The
42/// `block_account` / `unblock_account` procedures live in the standards library and require an
43/// auth-wrapped admin component (see [`super::BlocklistOwnerControlled`]) to be safely exposed
44/// on a production faucet.
45#[derive(Debug, Clone, Default)]
46pub struct BasicBlocklist(BTreeSet<AccountId>);
47
48impl BasicBlocklist {
49    /// The name of the component.
50    pub const NAME: &'static str =
51        "miden::standards::components::faucets::policies::transfer::basic_blocklist";
52
53    pub(crate) const PROC_NAME: &str = "check_policy";
54
55    /// Creates a basic blocklist with the given initial blocked accounts.
56    pub fn with_blocked_accounts<I>(blocked_accounts: I) -> Self
57    where
58        I: IntoIterator<Item = AccountId>,
59    {
60        Self(blocked_accounts.into_iter().collect())
61    }
62
63    /// Returns the initial blocked accounts captured in this component.
64    pub fn blocked_accounts(&self) -> &BTreeSet<AccountId> {
65        &self.0
66    }
67
68    /// Returns the [`AccountComponentCode`] of this component.
69    pub fn code() -> &'static AccountComponentCode {
70        &BASIC_BLOCKLIST_TRANSFER_POLICY_CODE
71    }
72
73    /// Returns the MAST root of the basic blocklist transfer policy procedure.
74    pub fn root() -> AccountProcedureRoot {
75        *BASIC_BLOCKLIST_TRANSFER_POLICY_ROOT
76    }
77}
78
79impl From<BasicBlocklist> for AccountComponent {
80    fn from(blocklist: BasicBlocklist) -> Self {
81        let storage = BlocklistStorage::with_blocked_accounts(blocklist.0);
82        let storage_schema = StorageSchema::new([BlocklistStorage::blocked_accounts_slot_schema()])
83            .expect("storage schema should be valid");
84
85        let metadata = AccountComponentMetadata::new(BasicBlocklist::NAME)
86            .with_description(
87                "Basic blocklist transfer policy: predicate procedure plus the `blocked_accounts` \
88                 storage map it reads",
89            )
90            .with_storage_schema(storage_schema);
91
92        AccountComponent::new(BasicBlocklist::code().clone(), vec![storage.into_slot()], metadata)
93            .expect(
94                "basic blocklist transfer policy component should satisfy the requirements of a valid account component",
95            )
96    }
97}