extern crate alloc;
use alloc::vec::Vec;
use miden_stdlib_sys::{Felt, Word, WordAligned};
use super::{
AccountId, MAX_ATTACHMENT_WORDS, MAX_ATTACHMENTS_PER_NOTE, NoteType, RawAccountId,
RawFoundIndex, Recipient, Tag, assert_attachment_count,
};
const MAX_NOTE_STORAGE_ITEMS: usize = 1024;
#[allow(improper_ctypes)]
unsafe extern "C" {
#[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
#[link_name = "miden::protocol::note::compute_and_store_recipient"]
fn extern_note_build_recipient(
storage_ptr: *mut Felt,
num_storage_items: usize,
serial_num_f0: Felt,
serial_num_f1: Felt,
serial_num_f2: Felt,
serial_num_f3: Felt,
script_root_f0: Felt,
script_root_f1: Felt,
script_root_f2: Felt,
script_root_f3: Felt,
ptr: *mut Recipient,
);
#[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
#[link_name = "miden::protocol::note::compute_storage_commitment"]
fn extern_note_compute_storage_commitment(
storage_ptr: *const Felt,
num_storage_items: usize,
ptr: *mut Word,
);
#[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
#[link_name = "miden::protocol::note::compute_recipient"]
fn extern_note_compute_recipient(
serial_num_f0: Felt,
serial_num_f1: Felt,
serial_num_f2: Felt,
serial_num_f3: Felt,
script_root_f0: Felt,
script_root_f1: Felt,
script_root_f2: Felt,
script_root_f3: Felt,
storage_commitment_f0: Felt,
storage_commitment_f1: Felt,
storage_commitment_f2: Felt,
storage_commitment_f3: Felt,
ptr: *mut Recipient,
);
#[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
#[link_name = "miden::protocol::note::metadata_into_sender"]
fn extern_note_metadata_into_sender(
metadata_f0: Felt,
metadata_f1: Felt,
metadata_f2: Felt,
metadata_f3: Felt,
ptr: *mut RawAccountId,
);
#[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
#[link_name = "miden::protocol::note::metadata_into_attachment_schemes"]
fn extern_note_metadata_into_attachment_schemes(
metadata_f0: Felt,
metadata_f1: Felt,
metadata_f2: Felt,
metadata_f3: Felt,
ptr: *mut Word,
);
#[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
#[link_name = "miden::protocol::note::metadata_into_note_type"]
fn extern_note_metadata_into_note_type(
metadata_f0: Felt,
metadata_f1: Felt,
metadata_f2: Felt,
metadata_f3: Felt,
) -> Felt;
#[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
#[link_name = "miden::protocol::note::metadata_into_tag"]
fn extern_note_metadata_into_tag(
metadata_f0: Felt,
metadata_f1: Felt,
metadata_f2: Felt,
metadata_f3: Felt,
) -> Felt;
#[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
#[link_name = "miden::protocol::note::find_attachment_idx"]
fn extern_note_find_attachment_idx(
attachment_scheme: Felt,
metadata_f0: Felt,
metadata_f1: Felt,
metadata_f2: Felt,
metadata_f3: Felt,
ptr: *mut RawFoundIndex,
);
#[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
#[link_name = "intrinsics::note::script_root"]
fn extern_note_script_root(ptr: *mut Word);
}
#[doc(hidden)]
pub fn __entrypoint_root() -> Word {
unsafe {
let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
extern_note_script_root(ret_area.as_mut_ptr());
ret_area.into_inner().assume_init()
}
}
pub fn compute_and_store_recipient(
serial_num: Word,
script_root: Word,
storage: Vec<Felt>,
) -> Recipient {
assert!(
storage.len() <= MAX_NOTE_STORAGE_ITEMS,
"note storage cannot contain more than {MAX_NOTE_STORAGE_ITEMS} items"
);
let rust_ptr = if storage.is_empty() {
0
} else {
storage.as_ptr().addr() as u32
};
let miden_ptr = rust_ptr / 4;
assert_eq!(miden_ptr % 4, 0, "storage pointer must be word-aligned");
unsafe {
let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Recipient>::uninit());
extern_note_build_recipient(
miden_ptr as *mut Felt,
storage.len(),
serial_num[0],
serial_num[1],
serial_num[2],
serial_num[3],
script_root[0],
script_root[1],
script_root[2],
script_root[3],
ret_area.as_mut_ptr(),
);
ret_area.into_inner().assume_init()
}
}
pub fn build_recipient(serial_num: Word, script_root: Word, storage: Vec<Felt>) -> Recipient {
compute_and_store_recipient(serial_num, script_root, storage)
}
pub fn compute_storage_commitment(storage: &[Felt]) -> Word {
assert!(
storage.len() <= MAX_NOTE_STORAGE_ITEMS,
"note storage cannot contain more than {MAX_NOTE_STORAGE_ITEMS} items"
);
let rust_ptr = if storage.is_empty() {
0
} else {
storage.as_ptr().addr() as u32
};
let miden_ptr = rust_ptr / 4;
assert_eq!(miden_ptr % 4, 0, "storage pointer must be word-aligned");
unsafe {
let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
extern_note_compute_storage_commitment(
miden_ptr as *const Felt,
storage.len(),
ret_area.as_mut_ptr(),
);
ret_area.into_inner().assume_init()
}
}
pub fn load_attachment_commitments(attachments_commitment: Word) -> Vec<Word> {
load_attachment_words(attachments_commitment, MAX_ATTACHMENTS_PER_NOTE)
}
pub fn load_attachment(attachment_commitment: Word) -> Vec<Word> {
load_attachment_words(attachment_commitment, MAX_ATTACHMENT_WORDS)
}
pub fn load_indexed_attachment(attachment_commitments: &[Word], attachment_idx: u32) -> Vec<Word> {
assert_attachment_count(attachment_commitments.len());
load_attachment(attachment_commitments[attachment_idx as usize])
}
fn load_attachment_words(commitment: Word, max_words: usize) -> Vec<Word> {
use miden_stdlib_sys::{adv_load_preimage, intrinsics::advice::adv_push_mapvaln};
let num_elements = adv_push_mapvaln(commitment).as_canonical_u64();
assert!(
num_elements <= (max_words * 4) as u64,
"attachment preimage exceeds protocol limit"
);
assert_eq!(num_elements % 4, 0, "attachment must contain whole words");
let elements = adv_load_preimage(Felt::from_u32((num_elements / 4) as u32), commitment);
elements.as_chunks::<4>().0.iter().map(|word| Word::new(*word)).collect()
}
pub fn compute_recipient(
serial_num: Word,
script_root: Word,
storage_commitment: Word,
) -> Recipient {
unsafe {
let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Recipient>::uninit());
extern_note_compute_recipient(
serial_num[0],
serial_num[1],
serial_num[2],
serial_num[3],
script_root[0],
script_root[1],
script_root[2],
script_root[3],
storage_commitment[0],
storage_commitment[1],
storage_commitment[2],
storage_commitment[3],
ret_area.as_mut_ptr(),
);
ret_area.into_inner().assume_init()
}
}
pub fn metadata_into_sender(metadata: Word) -> AccountId {
unsafe {
let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<RawAccountId>::uninit());
extern_note_metadata_into_sender(
metadata[0],
metadata[1],
metadata[2],
metadata[3],
ret_area.as_mut_ptr(),
);
ret_area.into_inner().assume_init().into_account_id()
}
}
pub fn metadata_into_attachment_schemes(metadata: Word) -> Word {
unsafe {
let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
extern_note_metadata_into_attachment_schemes(
metadata[0],
metadata[1],
metadata[2],
metadata[3],
ret_area.as_mut_ptr(),
);
ret_area.into_inner().assume_init()
}
}
pub fn metadata_into_note_type(metadata: Word) -> NoteType {
unsafe {
NoteType::from(extern_note_metadata_into_note_type(
metadata[0],
metadata[1],
metadata[2],
metadata[3],
))
}
}
pub fn metadata_into_tag(metadata: Word) -> Tag {
unsafe {
Tag::from(extern_note_metadata_into_tag(
metadata[0],
metadata[1],
metadata[2],
metadata[3],
))
}
}
pub fn find_attachment_idx(attachment_scheme: Felt, metadata: Word) -> Option<u32> {
unsafe {
let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<RawFoundIndex>::uninit());
extern_note_find_attachment_idx(
attachment_scheme,
metadata[0],
metadata[1],
metadata[2],
metadata[3],
ret_area.as_mut_ptr(),
);
ret_area.into_inner().assume_init().into_attachment_index()
}
}