miden_base_sys/bindings/
note.rs

1extern crate alloc;
2use alloc::vec::Vec;
3
4use miden_stdlib_sys::{Felt, Word};
5
6use super::{AccountId, Asset};
7
8#[allow(improper_ctypes)]
9extern "C" {
10    #[link_name = "miden::note::get_inputs"]
11    pub fn extern_note_get_inputs(ptr: *mut Felt) -> usize;
12    #[link_name = "miden::note::get_assets"]
13    pub fn extern_note_get_assets(ptr: *mut Felt) -> usize;
14    #[link_name = "miden::note::get_sender"]
15    pub fn extern_note_get_sender(ptr: *mut AccountId);
16    #[link_name = "miden::note::get_script_root"]
17    pub fn extern_note_get_script_root(ptr: *mut Word);
18    #[link_name = "miden::note::get_serial_number"]
19    pub fn extern_note_get_serial_number(ptr: *mut Word);
20}
21
22/// Get the inputs of the currently executing note.
23pub fn get_inputs() -> Vec<Felt> {
24    const MAX_INPUTS: usize = 256;
25    let mut inputs: Vec<Felt> = Vec::with_capacity(MAX_INPUTS);
26    let num_inputs = unsafe {
27        // Ensure the pointer is a valid Miden pointer
28        //
29        // NOTE: This relies on the fact that BumpAlloc makes all allocations
30        // minimally word-aligned. Each word consists of 4 elements of 4 bytes.
31        // Since Miden VM is field element-addressable, to get a Miden address from a Rust address,
32        // we divide it by 4 to get the address in field elements.
33        let ptr = (inputs.as_mut_ptr() as usize) / 4;
34        // The MASM for this function is here:
35        // https://github.com/0xMiden/miden-base/blob/3cbe8d59dcf4ccc9c380b7c8417ac6178fc6b86a/miden-lib/asm/miden/note.masm#L69-L102
36        // #! Writes the inputs of the currently execute note into memory starting at the specified
37        // address. #!
38        // #! Inputs: [dest_ptr]
39        // #! Outputs: [num_inputs, dest_ptr]
40        // #!
41        // #! - dest_ptr is the memory address to write the inputs.
42        // Compiler generated adapter code at call site will drop the returned dest_ptr
43        // and return the number of inputs
44        extern_note_get_inputs(ptr as *mut Felt)
45    };
46    unsafe {
47        inputs.set_len(num_inputs);
48    }
49    inputs
50}
51
52/// Get the assets of the currently executing note.
53pub fn get_assets() -> Vec<Asset> {
54    const MAX_INPUTS: usize = 256;
55    let mut inputs: Vec<Asset> = Vec::with_capacity(MAX_INPUTS);
56    let num_inputs = unsafe {
57        let ptr = (inputs.as_mut_ptr() as usize) / 4;
58        extern_note_get_assets(ptr as *mut Felt)
59    };
60    unsafe {
61        inputs.set_len(num_inputs);
62    }
63    inputs
64}
65
66/// Returns the sender [`AccountId`] of the note that is currently executing.
67pub fn get_sender() -> AccountId {
68    unsafe {
69        let mut ret_area = ::core::mem::MaybeUninit::<AccountId>::uninit();
70        extern_note_get_sender(ret_area.as_mut_ptr());
71        ret_area.assume_init()
72    }
73}
74
75/// Returns the script root of the currently executing note.
76pub fn get_script_root() -> Word {
77    unsafe {
78        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
79        extern_note_get_script_root(ret_area.as_mut_ptr());
80        ret_area.assume_init().reverse()
81    }
82}
83
84/// Returns the serial number of the currently executing note.
85pub fn get_serial_number() -> Word {
86    unsafe {
87        let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
88        extern_note_get_serial_number(ret_area.as_mut_ptr());
89        ret_area.assume_init().reverse()
90    }
91}