extern crate alloc;
use alloc::vec::Vec;
use miden_stdlib_sys::{Felt, Word};
use super::{AccountId, AttachmentLocation, NoteType, RawAccountId, Recipient, Tag};
const MAX_NOTE_STORAGE_ITEMS: usize = 1024;
const MAX_ATTACHMENTS_PER_NOTE: usize = 4;
const MAX_ATTACHMENT_WORDS: usize = 256;
#[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::write_attachment_commitments_to_memory"]
fn extern_note_write_attachment_commitments_to_memory(
attachments_commitment_f0: Felt,
attachments_commitment_f1: Felt,
attachments_commitment_f2: Felt,
attachments_commitment_f3: Felt,
dest_ptr: *mut Felt,
) -> usize;
#[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
#[link_name = "miden::protocol::note::write_attachment_to_memory"]
fn extern_note_write_attachment_to_memory(
attachment_commitment_f0: Felt,
attachment_commitment_f1: Felt,
attachment_commitment_f2: Felt,
attachment_commitment_f3: Felt,
dest_ptr: *mut Felt,
) -> usize;
#[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
#[link_name = "miden::protocol::note::write_indexed_attachment_to_memory"]
fn extern_note_write_indexed_attachment_to_memory(
num_attachments: Felt,
attachment_commitments_ptr: *const Felt,
attachment_idx: Felt,
dest_ptr: *mut Felt,
) -> usize;
#[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 AttachmentLocation,
);
}
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 = ::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.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 = ::core::mem::MaybeUninit::<Word>::uninit();
extern_note_compute_storage_commitment(
miden_ptr as *const Felt,
storage.len(),
ret_area.as_mut_ptr(),
);
ret_area.assume_init()
}
}
pub fn write_attachment_commitments_to_memory(attachments_commitment: Word) -> Vec<Word> {
let mut commitments: Vec<Word> = Vec::with_capacity(MAX_ATTACHMENTS_PER_NOTE);
let num_attachments = unsafe {
let ptr = (commitments.as_mut_ptr().addr() / 4) as u32;
extern_note_write_attachment_commitments_to_memory(
attachments_commitment[0],
attachments_commitment[1],
attachments_commitment[2],
attachments_commitment[3],
ptr as *mut Felt,
)
};
assert!(
num_attachments <= MAX_ATTACHMENTS_PER_NOTE,
"note cannot contain more than {MAX_ATTACHMENTS_PER_NOTE} attachments"
);
unsafe {
commitments.set_len(num_attachments);
}
commitments
}
pub fn write_attachment_to_memory(attachment_commitment: Word) -> Vec<Word> {
let mut attachment: Vec<Word> = Vec::with_capacity(MAX_ATTACHMENT_WORDS);
let num_words = unsafe {
let ptr = (attachment.as_mut_ptr().addr() / 4) as u32;
extern_note_write_attachment_to_memory(
attachment_commitment[0],
attachment_commitment[1],
attachment_commitment[2],
attachment_commitment[3],
ptr as *mut Felt,
)
};
assert!(
num_words <= MAX_ATTACHMENT_WORDS,
"note attachment cannot contain more than {MAX_ATTACHMENT_WORDS} words"
);
unsafe {
attachment.set_len(num_words);
}
attachment
}
pub fn write_indexed_attachment_to_memory(
attachment_commitments: &[Word],
attachment_idx: Felt,
) -> Vec<Word> {
assert!(
attachment_commitments.len() <= MAX_ATTACHMENTS_PER_NOTE,
"note cannot contain more than {MAX_ATTACHMENTS_PER_NOTE} attachments"
);
let mut attachment: Vec<Word> = Vec::with_capacity(MAX_ATTACHMENT_WORDS);
let num_words = unsafe {
let commitments_ptr = if attachment_commitments.is_empty() {
0
} else {
(attachment_commitments.as_ptr().addr() / 4) as u32
};
let dest_ptr = (attachment.as_mut_ptr().addr() / 4) as u32;
extern_note_write_indexed_attachment_to_memory(
Felt::from_u32(attachment_commitments.len() as u32),
commitments_ptr as *const Felt,
attachment_idx,
dest_ptr as *mut Felt,
)
};
assert!(
num_words <= MAX_ATTACHMENT_WORDS,
"note attachment cannot contain more than {MAX_ATTACHMENT_WORDS} words"
);
unsafe {
attachment.set_len(num_words);
}
attachment
}
pub fn compute_recipient(
serial_num: Word,
script_root: Word,
storage_commitment: Word,
) -> Recipient {
unsafe {
let mut ret_area = ::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.assume_init()
}
}
pub fn metadata_into_sender(metadata: Word) -> AccountId {
unsafe {
let mut ret_area = ::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.assume_init().into_account_id()
}
}
pub fn metadata_into_attachment_schemes(metadata: Word) -> Word {
unsafe {
let mut ret_area = ::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.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) -> AttachmentLocation {
unsafe {
let mut ret_area = ::core::mem::MaybeUninit::<AttachmentLocation>::uninit();
extern_note_find_attachment_idx(
attachment_scheme,
metadata[0],
metadata[1],
metadata[2],
metadata[3],
ret_area.as_mut_ptr(),
);
ret_area.assume_init()
}
}