Skip to main content

miden_base_sys/bindings/
native_account.rs

1use miden_stdlib_sys::{Felt, Word, WordAligned};
2
3use super::types::{AccountId, Asset, Nonce, RawAccountId};
4
5#[allow(improper_ctypes)]
6unsafe extern "C" {
7    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
8    #[link_name = "miden::protocol::native_account::add_asset"]
9    fn extern_native_account_add_asset(
10        asset_key_0: Felt,
11        asset_key_1: Felt,
12        asset_key_2: Felt,
13        asset_key_3: Felt,
14        asset_value_0: Felt,
15        asset_value_1: Felt,
16        asset_value_2: Felt,
17        asset_value_3: Felt,
18        ptr: *mut Word,
19    );
20    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
21    #[link_name = "miden::protocol::native_account::remove_asset"]
22    fn extern_native_account_remove_asset(
23        asset_key_0: Felt,
24        asset_key_1: Felt,
25        asset_key_2: Felt,
26        asset_key_3: Felt,
27        asset_value_0: Felt,
28        asset_value_1: Felt,
29        asset_value_2: Felt,
30        asset_value_3: Felt,
31        ptr: *mut Word,
32    );
33    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
34    #[link_name = "miden::protocol::native_account::get_id"]
35    fn extern_native_account_get_id(ptr: *mut RawAccountId);
36    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
37    #[link_name = "miden::protocol::native_account::incr_nonce"]
38    fn extern_native_account_incr_nonce() -> Felt;
39    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
40    #[link_name = "miden::protocol::native_account::compute_delta_commitment"]
41    fn extern_native_account_compute_delta_commitment(ptr: *mut Word);
42    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
43    #[link_name = "miden::protocol::native_account::was_procedure_called"]
44    fn extern_native_account_was_procedure_called(
45        proc_root_0: Felt,
46        proc_root_1: Felt,
47        proc_root_2: Felt,
48        proc_root_3: Felt,
49    ) -> Felt;
50    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
51    #[link_name = "miden::protocol::native_account::get_initial_commitment"]
52    fn extern_native_account_get_initial_commitment(ptr: *mut Word);
53    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
54    #[link_name = "miden::protocol::native_account::get_initial_storage_commitment"]
55    fn extern_native_account_get_initial_storage_commitment(ptr: *mut Word);
56    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
57    #[link_name = "miden::protocol::native_account::get_initial_vault_root"]
58    fn extern_native_account_get_initial_vault_root(ptr: *mut Word);
59    #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
60    #[link_name = "miden::protocol::native_account::get_initial_asset"]
61    fn extern_native_account_get_initial_asset(
62        asset_key_0: Felt,
63        asset_key_1: Felt,
64        asset_key_2: Felt,
65        asset_key_3: Felt,
66        ptr: *mut Word,
67    );
68}
69
70/// Adds the specified asset to the vault and returns the resulting asset value word stored under
71/// that asset key.
72///
73/// Panics:
74/// - If the asset is not valid.
75/// - If the total value of two fungible assets is greater than
76///   [`AssetAmount::MAX_U64`](super::types::AssetAmount::MAX_U64).
77/// - If the vault already contains the same non-fungible asset.
78///
79/// # Examples
80///
81/// Implement a basic-wallet style `receive_asset` method by adding the asset to the vault:
82///
83/// ```rust,ignore
84/// use miden::{component, component_storage, native_account::NativeAccount, Asset};
85///
86/// #[component_storage]
87/// struct MyAccountStorage;
88///
89/// #[component]
90/// trait MyAccount {
91///     fn receive_asset(&mut self, asset: Asset);
92/// }
93///
94/// #[component]
95/// impl MyAccount for MyAccountStorage {
96///     fn receive_asset(&mut self, asset: Asset) {
97///         self.add_asset(asset);
98///     }
99/// }
100/// ```
101pub fn add_asset(asset: Asset) -> Word {
102    unsafe {
103        let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
104        extern_native_account_add_asset(
105            asset.key[0],
106            asset.key[1],
107            asset.key[2],
108            asset.key[3],
109            asset.value[0],
110            asset.value[1],
111            asset.value[2],
112            asset.value[3],
113            ret_area.as_mut_ptr(),
114        );
115        ret_area.into_inner().assume_init()
116    }
117}
118
119/// Removes the specified asset from the vault and returns the resulting asset value word.
120///
121/// Panics:
122/// - The fungible asset is not found in the vault.
123/// - The amount of the fungible asset in the vault is less than the amount to be removed.
124/// - The non-fungible asset is not found in the vault.
125pub fn remove_asset(asset: Asset) -> Word {
126    unsafe {
127        let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
128        extern_native_account_remove_asset(
129            asset.key[0],
130            asset.key[1],
131            asset.key[2],
132            asset.key[3],
133            asset.value[0],
134            asset.value[1],
135            asset.value[2],
136            asset.value[3],
137            ret_area.as_mut_ptr(),
138        );
139        ret_area.into_inner().assume_init()
140    }
141}
142
143/// Returns the native account ID for the current transaction.
144pub fn get_id() -> AccountId {
145    unsafe {
146        let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<RawAccountId>::uninit());
147        extern_native_account_get_id(ret_area.as_mut_ptr());
148        ret_area.into_inner().assume_init().into_account_id()
149    }
150}
151
152/// Increments the account nonce by one and returns the new nonce.
153#[inline]
154pub fn incr_nonce() -> Nonce {
155    Nonce {
156        inner: unsafe { extern_native_account_incr_nonce() },
157    }
158}
159
160/// Computes and returns the commitment to the native account's delta for this transaction.
161#[inline]
162pub fn compute_delta_commitment() -> Word {
163    unsafe {
164        let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
165        extern_native_account_compute_delta_commitment(ret_area.as_mut_ptr());
166        ret_area.into_inner().assume_init()
167    }
168}
169
170/// Returns `true` if the procedure identified by `proc_root` was called during the transaction.
171#[inline]
172pub fn was_procedure_called(proc_root: Word) -> bool {
173    unsafe {
174        extern_native_account_was_procedure_called(
175            proc_root[0],
176            proc_root[1],
177            proc_root[2],
178            proc_root[3],
179        ) != Felt::new(0).unwrap()
180    }
181}
182
183/// Returns the native account's commitment at the beginning of the transaction.
184#[inline]
185pub fn get_initial_commitment() -> Word {
186    unsafe {
187        let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
188        extern_native_account_get_initial_commitment(ret_area.as_mut_ptr());
189        ret_area.into_inner().assume_init()
190    }
191}
192
193/// Returns the native account's storage commitment at the beginning of the transaction.
194#[inline]
195pub fn get_initial_storage_commitment() -> Word {
196    unsafe {
197        let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
198        extern_native_account_get_initial_storage_commitment(ret_area.as_mut_ptr());
199        ret_area.into_inner().assume_init()
200    }
201}
202
203/// Returns the native account's vault root at the beginning of the transaction.
204#[inline]
205pub fn get_initial_vault_root() -> Word {
206    unsafe {
207        let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
208        extern_native_account_get_initial_vault_root(ret_area.as_mut_ptr());
209        ret_area.into_inner().assume_init()
210    }
211}
212
213/// Returns the native account's initial value stored under the specified `asset_key` in the vault.
214pub fn get_initial_asset(asset_key: Word) -> Word {
215    unsafe {
216        let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
217        extern_native_account_get_initial_asset(
218            asset_key[0],
219            asset_key[1],
220            asset_key[2],
221            asset_key[3],
222            ret_area.as_mut_ptr(),
223        );
224        ret_area.into_inner().assume_init()
225    }
226}
227
228/// Trait that provides native account operations for components.
229///
230/// This trait is automatically implemented for the storage struct marked with the
231/// `#[component_storage]` macro.
232pub trait NativeAccount {
233    /// Adds the specified asset to the vault and returns the resulting asset value word stored
234    /// under that asset key.
235    ///
236    /// # Panics
237    ///
238    /// - If the asset is not valid.
239    /// - If the total value of two fungible assets is greater than
240    ///   [`AssetAmount::MAX_U64`](super::types::AssetAmount::MAX_U64).
241    /// - If the vault already contains the same non-fungible asset.
242    ///
243    /// # Examples
244    ///
245    /// Implement a basic-wallet style `receive_asset` method by adding the asset to the vault:
246    ///
247    /// ```rust,ignore
248    /// use miden::{component, component_storage, native_account::NativeAccount, Asset};
249    ///
250    /// #[component_storage]
251    /// struct MyAccountStorage;
252    ///
253    /// #[component]
254    /// trait MyAccount {
255    ///     fn receive_asset(&mut self, asset: Asset);
256    /// }
257    ///
258    /// #[component]
259    /// impl MyAccount for MyAccountStorage {
260    ///     fn receive_asset(&mut self, asset: Asset) {
261    ///         self.add_asset(asset);
262    ///     }
263    /// }
264    /// ```
265    #[inline]
266    fn add_asset(&mut self, asset: Asset) -> Word {
267        add_asset(asset)
268    }
269
270    /// Removes the specified asset from the vault and returns the resulting asset value word.
271    ///
272    /// # Panics
273    ///
274    /// - The fungible asset is not found in the vault.
275    /// - The amount of the fungible asset in the vault is less than the amount to be removed.
276    /// - The non-fungible asset is not found in the vault.
277    #[inline]
278    fn remove_asset(&mut self, asset: Asset) -> Word {
279        remove_asset(asset)
280    }
281
282    /// Increments the account nonce by one and returns the new nonce.
283    #[inline]
284    fn incr_nonce(&mut self) -> Nonce {
285        incr_nonce()
286    }
287
288    /// Computes and returns the commitment to the native account's delta for this transaction.
289    #[inline]
290    fn compute_delta_commitment(&self) -> Word {
291        compute_delta_commitment()
292    }
293
294    /// Returns `true` if the procedure identified by `proc_root` was called during the transaction.
295    #[inline]
296    fn was_procedure_called(&self, proc_root: Word) -> bool {
297        was_procedure_called(proc_root)
298    }
299}