Skip to main content

miden_base_sys/bindings/
active_account.rs

1use miden_stdlib_sys::{Felt, Word};
2
3use super::types::{AccountId, Asset, RawAccountId};
4
5#[allow(improper_ctypes)]
6unsafe extern "C" {
7    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
8    #[link_name = "miden::protocol::active_account::get_id"]
9    fn extern_active_account_get_id(ptr: *mut RawAccountId);
10    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
11    #[link_name = "miden::protocol::active_account::get_nonce"]
12    fn extern_active_account_get_nonce() -> Felt;
13    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
14    #[link_name = "miden::protocol::active_account::get_initial_commitment"]
15    fn extern_active_account_get_initial_commitment(ptr: *mut Word);
16    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
17    #[link_name = "miden::protocol::active_account::compute_commitment"]
18    fn extern_active_account_compute_commitment(ptr: *mut Word);
19    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
20    #[link_name = "miden::protocol::active_account::get_code_commitment"]
21    fn extern_active_account_get_code_commitment(ptr: *mut Word);
22    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
23    #[link_name = "miden::protocol::active_account::get_initial_storage_commitment"]
24    fn extern_active_account_get_initial_storage_commitment(ptr: *mut Word);
25    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
26    #[link_name = "miden::protocol::active_account::compute_storage_commitment"]
27    fn extern_active_account_compute_storage_commitment(ptr: *mut Word);
28    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
29    #[link_name = "miden::protocol::active_account::get_asset"]
30    fn extern_active_account_get_asset(
31        asset_key_0: Felt,
32        asset_key_1: Felt,
33        asset_key_2: Felt,
34        asset_key_3: Felt,
35        ptr: *mut Word,
36    );
37    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
38    #[link_name = "miden::protocol::active_account::get_initial_asset"]
39    fn extern_active_account_get_initial_asset(
40        asset_key_0: Felt,
41        asset_key_1: Felt,
42        asset_key_2: Felt,
43        asset_key_3: Felt,
44        ptr: *mut Word,
45    );
46    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
47    #[link_name = "miden::protocol::active_account::get_balance"]
48    fn extern_active_account_get_balance(
49        asset_key_0: Felt,
50        asset_key_1: Felt,
51        asset_key_2: Felt,
52        asset_key_3: Felt,
53    ) -> Felt;
54    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
55    #[link_name = "miden::protocol::active_account::get_initial_balance"]
56    fn extern_active_account_get_initial_balance(
57        asset_key_0: Felt,
58        asset_key_1: Felt,
59        asset_key_2: Felt,
60        asset_key_3: Felt,
61    ) -> Felt;
62    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
63    #[link_name = "miden::protocol::active_account::has_non_fungible_asset"]
64    fn extern_active_account_has_non_fungible_asset(
65        asset_0: Felt,
66        asset_1: Felt,
67        asset_2: Felt,
68        asset_3: Felt,
69    ) -> Felt;
70    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
71    #[link_name = "miden::protocol::active_account::get_initial_vault_root"]
72    fn extern_active_account_get_initial_vault_root(ptr: *mut Word);
73    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
74    #[link_name = "miden::protocol::active_account::get_vault_root"]
75    fn extern_active_account_get_vault_root(ptr: *mut Word);
76    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
77    #[link_name = "miden::protocol::active_account::get_num_procedures"]
78    fn extern_active_account_get_num_procedures() -> Felt;
79    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
80    #[link_name = "miden::protocol::active_account::get_procedure_root"]
81    fn extern_active_account_get_procedure_root(index: Felt, ptr: *mut Word);
82    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
83    #[link_name = "miden::protocol::active_account::has_procedure"]
84    fn extern_active_account_has_procedure(
85        proc_root_0: Felt,
86        proc_root_1: Felt,
87        proc_root_2: Felt,
88        proc_root_3: Felt,
89    ) -> Felt;
90}
91
92/// Returns the account ID of the active account.
93pub fn get_id() -> AccountId {
94    unsafe {
95        let mut ret_area = ::core::mem::MaybeUninit::<RawAccountId>::uninit();
96        extern_active_account_get_id(ret_area.as_mut_ptr());
97        ret_area.assume_init().into_account_id()
98    }
99}
100
101/// Returns the nonce of the active account.
102#[inline]
103pub fn get_nonce() -> Felt {
104    unsafe { extern_active_account_get_nonce() }
105}
106
107/// Returns the active account commitment at the beginning of the transaction.
108#[inline]
109pub fn get_initial_commitment() -> Word {
110    unsafe {
111        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
112        extern_active_account_get_initial_commitment(ret_area.as_mut_ptr());
113        ret_area.assume_init()
114    }
115}
116
117/// Computes and returns the commitment of the current account data.
118#[inline]
119pub fn compute_commitment() -> Word {
120    unsafe {
121        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
122        extern_active_account_compute_commitment(ret_area.as_mut_ptr());
123        ret_area.assume_init()
124    }
125}
126
127/// Returns the code commitment of the active account.
128#[inline]
129pub fn get_code_commitment() -> Word {
130    unsafe {
131        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
132        extern_active_account_get_code_commitment(ret_area.as_mut_ptr());
133        ret_area.assume_init()
134    }
135}
136
137/// Returns the initial storage commitment of the active account.
138#[inline]
139pub fn get_initial_storage_commitment() -> Word {
140    unsafe {
141        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
142        extern_active_account_get_initial_storage_commitment(ret_area.as_mut_ptr());
143        ret_area.assume_init()
144    }
145}
146
147/// Computes the latest storage commitment of the active account.
148#[inline]
149pub fn compute_storage_commitment() -> Word {
150    unsafe {
151        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
152        extern_active_account_compute_storage_commitment(ret_area.as_mut_ptr());
153        ret_area.assume_init()
154    }
155}
156
157/// Returns the current value stored under the specified `asset_key` in the active account vault.
158pub fn get_asset(asset_key: Word) -> Word {
159    unsafe {
160        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
161        extern_active_account_get_asset(
162            asset_key[0],
163            asset_key[1],
164            asset_key[2],
165            asset_key[3],
166            ret_area.as_mut_ptr(),
167        );
168        ret_area.assume_init()
169    }
170}
171
172/// Returns the initial value stored under the specified `asset_key` in the active account vault.
173pub fn get_initial_asset(asset_key: Word) -> Word {
174    unsafe {
175        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
176        extern_active_account_get_initial_asset(
177            asset_key[0],
178            asset_key[1],
179            asset_key[2],
180            asset_key[3],
181            ret_area.as_mut_ptr(),
182        );
183        ret_area.assume_init()
184    }
185}
186
187/// Returns the balance of the fungible asset identified by `asset_key`.
188///
189/// # Panics
190///
191/// Propagates kernel errors if the referenced asset is non-fungible or the
192/// account vault invariants are violated.
193pub fn get_balance(asset_key: Word) -> Felt {
194    unsafe {
195        extern_active_account_get_balance(asset_key[0], asset_key[1], asset_key[2], asset_key[3])
196    }
197}
198
199/// Returns the initial balance of the fungible asset identified by `asset_key`.
200#[inline]
201pub fn get_initial_balance(asset_key: Word) -> Felt {
202    unsafe {
203        extern_active_account_get_initial_balance(
204            asset_key[0],
205            asset_key[1],
206            asset_key[2],
207            asset_key[3],
208        )
209    }
210}
211
212/// Returns `true` if the active account vault currently contains the specified non-fungible asset.
213#[inline]
214pub fn has_non_fungible_asset(asset: Asset) -> bool {
215    unsafe {
216        extern_active_account_has_non_fungible_asset(
217            asset.key[0],
218            asset.key[1],
219            asset.key[2],
220            asset.key[3],
221        ) != Felt::new(0).unwrap()
222    }
223}
224
225/// Returns the vault root of the active account at the beginning of the transaction.
226#[inline]
227pub fn get_initial_vault_root() -> Word {
228    unsafe {
229        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
230        extern_active_account_get_initial_vault_root(ret_area.as_mut_ptr());
231        ret_area.assume_init()
232    }
233}
234
235/// Returns the current vault root of the active account.
236#[inline]
237pub fn get_vault_root() -> Word {
238    unsafe {
239        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
240        extern_active_account_get_vault_root(ret_area.as_mut_ptr());
241        ret_area.assume_init()
242    }
243}
244
245/// Returns the number of procedures exported by the active account.
246#[inline]
247pub fn get_num_procedures() -> Felt {
248    unsafe { extern_active_account_get_num_procedures() }
249}
250
251/// Returns the procedure root for the procedure at `index`.
252#[inline]
253pub fn get_procedure_root(index: u8) -> Word {
254    unsafe {
255        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
256        extern_active_account_get_procedure_root(
257            Felt::new(index as u64).unwrap(),
258            ret_area.as_mut_ptr(),
259        );
260        ret_area.assume_init()
261    }
262}
263
264/// Returns `true` if the procedure identified by `proc_root` exists on the active account.
265#[inline]
266pub fn has_procedure(proc_root: Word) -> bool {
267    unsafe {
268        extern_active_account_has_procedure(proc_root[0], proc_root[1], proc_root[2], proc_root[3])
269            != Felt::new(0).unwrap()
270    }
271}
272
273/// Trait that provides active account operations for components.
274///
275/// This trait is automatically implemented for the storage struct marked with the
276/// `#[component_storage]` macro.
277///
278/// NOTE: when adding methods, also update `ACTIVE_ACCOUNT_METHODS` in
279/// `sdk/base-macros/src/fpi.rs`, which rejects dependency functions that would shadow them.
280pub trait ActiveAccount {
281    /// Guard hook invoked by every active-account operation before it runs.
282    ///
283    /// The default implementation is a no-op. Types that can also represent a *foreign* account
284    /// (for example the struct generated by the `#[account(...)]` macro) override this to reject
285    /// calls made on a foreign binding, because the active-account operations always target the
286    /// transaction's active account rather than the foreign one.
287    #[doc(hidden)]
288    #[inline]
289    fn __assert_active_account(&self) {}
290
291    /// Returns the account ID of the active account.
292    #[inline]
293    fn get_id(&self) -> AccountId {
294        self.__assert_active_account();
295        get_id()
296    }
297
298    /// Returns the nonce of the active account.
299    #[inline]
300    fn get_nonce(&self) -> Felt {
301        self.__assert_active_account();
302        get_nonce()
303    }
304
305    /// Returns the active account commitment at the beginning of the transaction.
306    #[inline]
307    fn get_initial_commitment(&self) -> Word {
308        self.__assert_active_account();
309        get_initial_commitment()
310    }
311
312    /// Computes and returns the commitment of the current account data.
313    #[inline]
314    fn compute_commitment(&self) -> Word {
315        self.__assert_active_account();
316        compute_commitment()
317    }
318
319    /// Returns the code commitment of the active account.
320    #[inline]
321    fn get_code_commitment(&self) -> Word {
322        self.__assert_active_account();
323        get_code_commitment()
324    }
325
326    /// Returns the initial storage commitment of the active account.
327    #[inline]
328    fn get_initial_storage_commitment(&self) -> Word {
329        self.__assert_active_account();
330        get_initial_storage_commitment()
331    }
332
333    /// Computes the latest storage commitment of the active account.
334    #[inline]
335    fn compute_storage_commitment(&self) -> Word {
336        self.__assert_active_account();
337        compute_storage_commitment()
338    }
339
340    /// Returns the current value stored under the specified `asset_key` in the active account
341    /// vault.
342    #[inline]
343    fn get_asset(&self, asset_key: Word) -> Word {
344        self.__assert_active_account();
345        get_asset(asset_key)
346    }
347
348    /// Returns the initial value stored under the specified `asset_key` in the active account
349    /// vault.
350    #[inline]
351    fn get_initial_asset(&self, asset_key: Word) -> Word {
352        self.__assert_active_account();
353        get_initial_asset(asset_key)
354    }
355
356    /// Returns the balance of the fungible asset identified by `asset_key`.
357    ///
358    /// # Panics
359    ///
360    /// Propagates kernel errors if the referenced asset is non-fungible or the
361    /// account vault invariants are violated.
362    #[inline]
363    fn get_balance(&self, asset_key: Word) -> Felt {
364        self.__assert_active_account();
365        get_balance(asset_key)
366    }
367
368    /// Returns the initial balance of the fungible asset identified by `asset_key`.
369    #[inline]
370    fn get_initial_balance(&self, asset_key: Word) -> Felt {
371        self.__assert_active_account();
372        get_initial_balance(asset_key)
373    }
374
375    /// Returns `true` if the active account vault currently contains the specified non-fungible asset.
376    #[inline]
377    fn has_non_fungible_asset(&self, asset: Asset) -> bool {
378        self.__assert_active_account();
379        has_non_fungible_asset(asset)
380    }
381
382    /// Returns the vault root of the active account at the beginning of the transaction.
383    #[inline]
384    fn get_initial_vault_root(&self) -> Word {
385        self.__assert_active_account();
386        get_initial_vault_root()
387    }
388
389    /// Returns the current vault root of the active account.
390    #[inline]
391    fn get_vault_root(&self) -> Word {
392        self.__assert_active_account();
393        get_vault_root()
394    }
395
396    /// Returns the number of procedures exported by the active account.
397    #[inline]
398    fn get_num_procedures(&self) -> Felt {
399        self.__assert_active_account();
400        get_num_procedures()
401    }
402
403    /// Returns the procedure root for the procedure at `index`.
404    #[inline]
405    fn get_procedure_root(&self, index: u8) -> Word {
406        self.__assert_active_account();
407        get_procedure_root(index)
408    }
409
410    /// Returns `true` if the procedure identified by `proc_root` exists on the active account.
411    #[inline]
412    fn has_procedure(&self, proc_root: Word) -> bool {
413        self.__assert_active_account();
414        has_procedure(proc_root)
415    }
416}
417
418/// Marker trait for account API wrapper types.
419///
420/// The `#[note]` and `#[tx_script]` macros instantiate their entrypoint account parameter
421/// through this trait, so that parameter must be a type implementing it. The `ActiveAccount`
422/// supertrait guarantees that parameter is usable as the transaction's active account and keeps
423/// unrelated `Default` types from satisfying the bound. The `#[account(...)]` macro implements
424/// both automatically; it is not a sealed capability boundary, so manual implementations are
425/// possible but normally unnecessary.
426#[diagnostic::on_unimplemented(
427    message = "`{Self}` is not an account wrapper generated by `#[account(...)]`",
428    note = "define a struct with `#[account(...)]` and use it as the entrypoint account parameter"
429)]
430pub trait AccountWrapper: ActiveAccount + Default {
431    /// Creates a binding to the transaction's active account.
432    ///
433    /// This is the account the transaction executes against, as opposed to a foreign account
434    /// reached through FPI (created with `new`).
435    #[inline(always)]
436    fn active() -> Self {
437        Self::default()
438    }
439}