1extern crate alloc;
2
3use alloc::vec::Vec;
4
5use miden_stdlib_sys::{Felt, Word, WordAligned};
6
7use super::{
8 AccountId, MAX_ATTACHMENT_WORDS, MAX_ATTACHMENTS_PER_NOTE, NoteType, RawAccountId,
9 RawFoundIndex, Recipient, Tag, assert_attachment_count,
10};
11
12const MAX_NOTE_STORAGE_ITEMS: usize = 1024;
13
14#[allow(improper_ctypes)]
15unsafe extern "C" {
16 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
17 #[link_name = "miden::protocol::note::compute_and_store_recipient"]
18 fn extern_note_build_recipient(
19 storage_ptr: *mut Felt,
20 num_storage_items: usize,
21 serial_num_f0: Felt,
22 serial_num_f1: Felt,
23 serial_num_f2: Felt,
24 serial_num_f3: Felt,
25 script_root_f0: Felt,
26 script_root_f1: Felt,
27 script_root_f2: Felt,
28 script_root_f3: Felt,
29 ptr: *mut Recipient,
30 );
31 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
32 #[link_name = "miden::protocol::note::compute_storage_commitment"]
33 fn extern_note_compute_storage_commitment(
34 storage_ptr: *const Felt,
35 num_storage_items: usize,
36 ptr: *mut Word,
37 );
38 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
39 #[link_name = "miden::protocol::note::compute_recipient"]
40 fn extern_note_compute_recipient(
41 serial_num_f0: Felt,
42 serial_num_f1: Felt,
43 serial_num_f2: Felt,
44 serial_num_f3: Felt,
45 script_root_f0: Felt,
46 script_root_f1: Felt,
47 script_root_f2: Felt,
48 script_root_f3: Felt,
49 storage_commitment_f0: Felt,
50 storage_commitment_f1: Felt,
51 storage_commitment_f2: Felt,
52 storage_commitment_f3: Felt,
53 ptr: *mut Recipient,
54 );
55 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
56 #[link_name = "miden::protocol::note::metadata_into_sender"]
57 fn extern_note_metadata_into_sender(
58 metadata_f0: Felt,
59 metadata_f1: Felt,
60 metadata_f2: Felt,
61 metadata_f3: Felt,
62 ptr: *mut RawAccountId,
63 );
64 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
65 #[link_name = "miden::protocol::note::metadata_into_attachment_schemes"]
66 fn extern_note_metadata_into_attachment_schemes(
67 metadata_f0: Felt,
68 metadata_f1: Felt,
69 metadata_f2: Felt,
70 metadata_f3: Felt,
71 ptr: *mut Word,
72 );
73 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
74 #[link_name = "miden::protocol::note::metadata_into_note_type"]
75 fn extern_note_metadata_into_note_type(
76 metadata_f0: Felt,
77 metadata_f1: Felt,
78 metadata_f2: Felt,
79 metadata_f3: Felt,
80 ) -> Felt;
81 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
82 #[link_name = "miden::protocol::note::metadata_into_tag"]
83 fn extern_note_metadata_into_tag(
84 metadata_f0: Felt,
85 metadata_f1: Felt,
86 metadata_f2: Felt,
87 metadata_f3: Felt,
88 ) -> Felt;
89 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
90 #[link_name = "miden::protocol::note::find_attachment_idx"]
91 fn extern_note_find_attachment_idx(
92 attachment_scheme: Felt,
93 metadata_f0: Felt,
94 metadata_f1: Felt,
95 metadata_f2: Felt,
96 metadata_f3: Felt,
97 ptr: *mut RawFoundIndex,
98 );
99 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
102 #[link_name = "intrinsics::note::script_root"]
103 fn extern_note_script_root(ptr: *mut Word);
104}
105
106#[doc(hidden)]
124pub fn __entrypoint_root() -> Word {
125 unsafe {
126 let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
127 extern_note_script_root(ret_area.as_mut_ptr());
128 ret_area.into_inner().assume_init()
129 }
130}
131
132pub fn compute_and_store_recipient(
140 serial_num: Word,
141 script_root: Word,
142 storage: Vec<Felt>,
143) -> Recipient {
144 assert!(
145 storage.len() <= MAX_NOTE_STORAGE_ITEMS,
146 "note storage cannot contain more than {MAX_NOTE_STORAGE_ITEMS} items"
147 );
148
149 let rust_ptr = if storage.is_empty() {
150 0
151 } else {
152 storage.as_ptr().addr() as u32
153 };
154 let miden_ptr = rust_ptr / 4;
155
156 assert_eq!(miden_ptr % 4, 0, "storage pointer must be word-aligned");
158
159 unsafe {
160 let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Recipient>::uninit());
161 extern_note_build_recipient(
162 miden_ptr as *mut Felt,
163 storage.len(),
164 serial_num[0],
165 serial_num[1],
166 serial_num[2],
167 serial_num[3],
168 script_root[0],
169 script_root[1],
170 script_root[2],
171 script_root[3],
172 ret_area.as_mut_ptr(),
173 );
174 ret_area.into_inner().assume_init()
175 }
176}
177
178pub fn build_recipient(serial_num: Word, script_root: Word, storage: Vec<Felt>) -> Recipient {
182 compute_and_store_recipient(serial_num, script_root, storage)
183}
184
185pub fn compute_storage_commitment(storage: &[Felt]) -> Word {
189 assert!(
190 storage.len() <= MAX_NOTE_STORAGE_ITEMS,
191 "note storage cannot contain more than {MAX_NOTE_STORAGE_ITEMS} items"
192 );
193
194 let rust_ptr = if storage.is_empty() {
195 0
196 } else {
197 storage.as_ptr().addr() as u32
198 };
199 let miden_ptr = rust_ptr / 4;
200
201 assert_eq!(miden_ptr % 4, 0, "storage pointer must be word-aligned");
202
203 unsafe {
204 let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
205 extern_note_compute_storage_commitment(
206 miden_ptr as *const Felt,
207 storage.len(),
208 ret_area.as_mut_ptr(),
209 );
210 ret_area.into_inner().assume_init()
211 }
212}
213
214pub fn load_attachment_commitments(attachments_commitment: Word) -> Vec<Word> {
223 load_attachment_words(attachments_commitment, MAX_ATTACHMENTS_PER_NOTE)
224}
225
226pub fn load_attachment(attachment_commitment: Word) -> Vec<Word> {
235 load_attachment_words(attachment_commitment, MAX_ATTACHMENT_WORDS)
236}
237
238pub fn load_indexed_attachment(attachment_commitments: &[Word], attachment_idx: u32) -> Vec<Word> {
247 assert_attachment_count(attachment_commitments.len());
248 load_attachment(attachment_commitments[attachment_idx as usize])
249}
250
251fn load_attachment_words(commitment: Word, max_words: usize) -> Vec<Word> {
253 use miden_stdlib_sys::{adv_load_preimage, intrinsics::advice::adv_push_mapvaln};
254
255 let num_elements = adv_push_mapvaln(commitment).as_canonical_u64();
256 assert!(
257 num_elements <= (max_words * 4) as u64,
258 "attachment preimage exceeds protocol limit"
259 );
260 assert_eq!(num_elements % 4, 0, "attachment must contain whole words");
261 let elements = adv_load_preimage(Felt::from_u32((num_elements / 4) as u32), commitment);
262 elements.as_chunks::<4>().0.iter().map(|word| Word::new(*word)).collect()
264}
265
266pub fn compute_recipient(
268 serial_num: Word,
269 script_root: Word,
270 storage_commitment: Word,
271) -> Recipient {
272 unsafe {
273 let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Recipient>::uninit());
274 extern_note_compute_recipient(
275 serial_num[0],
276 serial_num[1],
277 serial_num[2],
278 serial_num[3],
279 script_root[0],
280 script_root[1],
281 script_root[2],
282 script_root[3],
283 storage_commitment[0],
284 storage_commitment[1],
285 storage_commitment[2],
286 storage_commitment[3],
287 ret_area.as_mut_ptr(),
288 );
289 ret_area.into_inner().assume_init()
290 }
291}
292
293pub fn metadata_into_sender(metadata: Word) -> AccountId {
295 unsafe {
296 let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<RawAccountId>::uninit());
297 extern_note_metadata_into_sender(
298 metadata[0],
299 metadata[1],
300 metadata[2],
301 metadata[3],
302 ret_area.as_mut_ptr(),
303 );
304 ret_area.into_inner().assume_init().into_account_id()
305 }
306}
307
308pub fn metadata_into_attachment_schemes(metadata: Word) -> Word {
310 unsafe {
311 let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<Word>::uninit());
312 extern_note_metadata_into_attachment_schemes(
313 metadata[0],
314 metadata[1],
315 metadata[2],
316 metadata[3],
317 ret_area.as_mut_ptr(),
318 );
319 ret_area.into_inner().assume_init()
320 }
321}
322
323pub fn metadata_into_note_type(metadata: Word) -> NoteType {
325 unsafe {
326 NoteType::from(extern_note_metadata_into_note_type(
327 metadata[0],
328 metadata[1],
329 metadata[2],
330 metadata[3],
331 ))
332 }
333}
334
335pub fn metadata_into_tag(metadata: Word) -> Tag {
337 unsafe {
338 Tag::from(extern_note_metadata_into_tag(
339 metadata[0],
340 metadata[1],
341 metadata[2],
342 metadata[3],
343 ))
344 }
345}
346
347pub fn find_attachment_idx(attachment_scheme: Felt, metadata: Word) -> Option<u32> {
349 unsafe {
350 let mut ret_area = WordAligned::new(::core::mem::MaybeUninit::<RawFoundIndex>::uninit());
351 extern_note_find_attachment_idx(
352 attachment_scheme,
353 metadata[0],
354 metadata[1],
355 metadata[2],
356 metadata[3],
357 ret_area.as_mut_ptr(),
358 );
359 ret_area.into_inner().assume_init().into_attachment_index()
360 }
361}