miden_standards/account/access/pausable/
mod.rs1use miden_protocol::account::component::{
2 AccountComponentCode,
3 AccountComponentMetadata,
4 StorageSchema,
5 StorageSlotSchema,
6};
7use miden_protocol::account::{
8 AccountComponent,
9 AccountProcedureRoot,
10 StorageSlot,
11 StorageSlotName,
12};
13use miden_protocol::utils::sync::LazyLock;
14use miden_protocol::{Felt, Word};
15
16use crate::account::account_component_code;
17use crate::procedure_root;
18
19mod manager;
20pub use manager::PausableManager;
21
22account_component_code!(PAUSABLE_CODE, "access/pausable/mod.masl");
26
27static IS_PAUSED_SLOT_NAME: LazyLock<StorageSlotName> = LazyLock::new(|| {
28 StorageSlotName::new("miden::standards::access::pausable::is_paused")
29 .expect("storage slot name should be valid")
30});
31
32procedure_root!(
33 PAUSABLE_IS_PAUSED_ROOT,
34 Pausable::NAME,
35 Pausable::IS_PAUSED_PROC_NAME,
36 Pausable::code()
37);
38
39#[derive(Debug, Clone, Copy, Default)]
53pub struct PausableStorage {
54 state: bool,
55}
56
57impl PausableStorage {
58 pub const fn new(state: bool) -> Self {
60 Self { state }
61 }
62
63 pub const fn paused() -> Self {
65 Self::new(true)
66 }
67
68 pub const fn unpaused() -> Self {
70 Self::new(false)
71 }
72
73 pub fn state(&self) -> bool {
75 self.state
76 }
77
78 pub fn is_paused_slot() -> &'static StorageSlotName {
80 &IS_PAUSED_SLOT_NAME
81 }
82
83 pub fn is_paused_slot_schema() -> (StorageSlotName, StorageSlotSchema) {
85 (
86 Self::is_paused_slot().clone(),
87 StorageSlotSchema::value(
88 "Pause flag word; zero is unpaused, canonical paused encoding is [1,0,0,0]",
89 [Felt::ZERO; 4],
90 ),
91 )
92 }
93
94 pub fn to_word(&self) -> Word {
96 if self.state {
97 Word::from([1u32, 0, 0, 0])
98 } else {
99 Word::default()
100 }
101 }
102
103 pub fn into_slot(self) -> StorageSlot {
106 StorageSlot::with_value(Self::is_paused_slot().clone(), self.to_word())
107 }
108}
109
110#[derive(Debug, Clone, Copy, Default)]
119pub struct Pausable(PausableStorage);
120
121impl Pausable {
122 pub const NAME: &'static str = "miden::standards::components::access::pausable";
124
125 pub const IS_PAUSED_PROC_NAME: &'static str = "is_paused";
126
127 pub const fn new(state: bool) -> Self {
129 Self(PausableStorage::new(state))
130 }
131
132 pub const fn paused() -> Self {
134 Self::new(true)
135 }
136
137 pub const fn unpaused() -> Self {
139 Self::new(false)
140 }
141
142 pub fn state(&self) -> bool {
144 self.0.state()
145 }
146
147 pub fn storage(&self) -> &PausableStorage {
149 &self.0
150 }
151
152 pub fn code() -> &'static AccountComponentCode {
154 &PAUSABLE_CODE
155 }
156
157 pub fn is_paused_root() -> AccountProcedureRoot {
159 *PAUSABLE_IS_PAUSED_ROOT
160 }
161}
162
163impl From<Pausable> for AccountComponent {
164 fn from(pausable: Pausable) -> Self {
165 let storage_schema = StorageSchema::new([PausableStorage::is_paused_slot_schema()])
166 .expect("storage schema should be valid");
167
168 let metadata = AccountComponentMetadata::new(Pausable::NAME)
169 .with_description(
170 "Pausable: installs the `is_paused` storage slot and exposes \
171 `is_paused` view.",
172 )
173 .with_storage_schema(storage_schema);
174
175 AccountComponent::new(Pausable::code().clone(), vec![pausable.0.into_slot()], metadata)
176 .expect(
177 "pausable component should satisfy the requirements of a valid account component",
178 )
179 }
180}