1extern crate alloc;
2
3use alloc::vec::Vec;
4
5use miden_stdlib_sys::{Felt, Word};
6
7use super::{AccountId, AttachmentLocation, NoteType, RawAccountId, Recipient, Tag};
8
9const MAX_NOTE_STORAGE_ITEMS: usize = 1024;
10const MAX_ATTACHMENTS_PER_NOTE: usize = 4;
11const MAX_ATTACHMENT_WORDS: usize = 256;
12
13#[allow(improper_ctypes)]
14unsafe extern "C" {
15 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
16 #[link_name = "miden::protocol::note::compute_and_store_recipient"]
17 fn extern_note_build_recipient(
18 storage_ptr: *mut Felt,
19 num_storage_items: usize,
20 serial_num_f0: Felt,
21 serial_num_f1: Felt,
22 serial_num_f2: Felt,
23 serial_num_f3: Felt,
24 script_root_f0: Felt,
25 script_root_f1: Felt,
26 script_root_f2: Felt,
27 script_root_f3: Felt,
28 ptr: *mut Recipient,
29 );
30 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
31 #[link_name = "miden::protocol::note::compute_storage_commitment"]
32 fn extern_note_compute_storage_commitment(
33 storage_ptr: *const Felt,
34 num_storage_items: usize,
35 ptr: *mut Word,
36 );
37 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
38 #[link_name = "miden::protocol::note::write_attachment_commitments_to_memory"]
39 fn extern_note_write_attachment_commitments_to_memory(
40 attachments_commitment_f0: Felt,
41 attachments_commitment_f1: Felt,
42 attachments_commitment_f2: Felt,
43 attachments_commitment_f3: Felt,
44 dest_ptr: *mut Felt,
45 ) -> usize;
46 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
47 #[link_name = "miden::protocol::note::write_attachment_to_memory"]
48 fn extern_note_write_attachment_to_memory(
49 attachment_commitment_f0: Felt,
50 attachment_commitment_f1: Felt,
51 attachment_commitment_f2: Felt,
52 attachment_commitment_f3: Felt,
53 dest_ptr: *mut Felt,
54 ) -> usize;
55 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
56 #[link_name = "miden::protocol::note::write_indexed_attachment_to_memory"]
57 fn extern_note_write_indexed_attachment_to_memory(
58 num_attachments: Felt,
59 attachment_commitments_ptr: *const Felt,
60 attachment_idx: Felt,
61 dest_ptr: *mut Felt,
62 ) -> usize;
63 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
64 #[link_name = "miden::protocol::note::compute_recipient"]
65 fn extern_note_compute_recipient(
66 serial_num_f0: Felt,
67 serial_num_f1: Felt,
68 serial_num_f2: Felt,
69 serial_num_f3: Felt,
70 script_root_f0: Felt,
71 script_root_f1: Felt,
72 script_root_f2: Felt,
73 script_root_f3: Felt,
74 storage_commitment_f0: Felt,
75 storage_commitment_f1: Felt,
76 storage_commitment_f2: Felt,
77 storage_commitment_f3: Felt,
78 ptr: *mut Recipient,
79 );
80 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
81 #[link_name = "miden::protocol::note::metadata_into_sender"]
82 fn extern_note_metadata_into_sender(
83 metadata_f0: Felt,
84 metadata_f1: Felt,
85 metadata_f2: Felt,
86 metadata_f3: Felt,
87 ptr: *mut RawAccountId,
88 );
89 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
90 #[link_name = "miden::protocol::note::metadata_into_attachment_schemes"]
91 fn extern_note_metadata_into_attachment_schemes(
92 metadata_f0: Felt,
93 metadata_f1: Felt,
94 metadata_f2: Felt,
95 metadata_f3: Felt,
96 ptr: *mut Word,
97 );
98 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
99 #[link_name = "miden::protocol::note::metadata_into_note_type"]
100 fn extern_note_metadata_into_note_type(
101 metadata_f0: Felt,
102 metadata_f1: Felt,
103 metadata_f2: Felt,
104 metadata_f3: Felt,
105 ) -> Felt;
106 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
107 #[link_name = "miden::protocol::note::metadata_into_tag"]
108 fn extern_note_metadata_into_tag(
109 metadata_f0: Felt,
110 metadata_f1: Felt,
111 metadata_f2: Felt,
112 metadata_f3: Felt,
113 ) -> Felt;
114 #[cfg_attr(target_family = "wasm", linkage = "extern_weak")]
115 #[link_name = "miden::protocol::note::find_attachment_idx"]
116 fn extern_note_find_attachment_idx(
117 attachment_scheme: Felt,
118 metadata_f0: Felt,
119 metadata_f1: Felt,
120 metadata_f2: Felt,
121 metadata_f3: Felt,
122 ptr: *mut AttachmentLocation,
123 );
124}
125
126pub fn compute_and_store_recipient(
134 serial_num: Word,
135 script_root: Word,
136 storage: Vec<Felt>,
137) -> Recipient {
138 assert!(
139 storage.len() <= MAX_NOTE_STORAGE_ITEMS,
140 "note storage cannot contain more than {MAX_NOTE_STORAGE_ITEMS} items"
141 );
142
143 let rust_ptr = if storage.is_empty() {
144 0
145 } else {
146 storage.as_ptr().addr() as u32
147 };
148 let miden_ptr = rust_ptr / 4;
149
150 assert_eq!(miden_ptr % 4, 0, "storage pointer must be word-aligned");
152
153 unsafe {
154 let mut ret_area = ::core::mem::MaybeUninit::<Recipient>::uninit();
155 extern_note_build_recipient(
156 miden_ptr as *mut Felt,
157 storage.len(),
158 serial_num[0],
159 serial_num[1],
160 serial_num[2],
161 serial_num[3],
162 script_root[0],
163 script_root[1],
164 script_root[2],
165 script_root[3],
166 ret_area.as_mut_ptr(),
167 );
168 ret_area.assume_init()
169 }
170}
171
172pub fn build_recipient(serial_num: Word, script_root: Word, storage: Vec<Felt>) -> Recipient {
176 compute_and_store_recipient(serial_num, script_root, storage)
177}
178
179pub fn compute_storage_commitment(storage: &[Felt]) -> Word {
183 assert!(
184 storage.len() <= MAX_NOTE_STORAGE_ITEMS,
185 "note storage cannot contain more than {MAX_NOTE_STORAGE_ITEMS} items"
186 );
187
188 let rust_ptr = if storage.is_empty() {
189 0
190 } else {
191 storage.as_ptr().addr() as u32
192 };
193 let miden_ptr = rust_ptr / 4;
194
195 assert_eq!(miden_ptr % 4, 0, "storage pointer must be word-aligned");
196
197 unsafe {
198 let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
199 extern_note_compute_storage_commitment(
200 miden_ptr as *const Felt,
201 storage.len(),
202 ret_area.as_mut_ptr(),
203 );
204 ret_area.assume_init()
205 }
206}
207
208pub fn write_attachment_commitments_to_memory(attachments_commitment: Word) -> Vec<Word> {
212 let mut commitments: Vec<Word> = Vec::with_capacity(MAX_ATTACHMENTS_PER_NOTE);
213 let num_attachments = unsafe {
214 let ptr = (commitments.as_mut_ptr().addr() / 4) as u32;
215 extern_note_write_attachment_commitments_to_memory(
216 attachments_commitment[0],
217 attachments_commitment[1],
218 attachments_commitment[2],
219 attachments_commitment[3],
220 ptr as *mut Felt,
221 )
222 };
223 assert!(
224 num_attachments <= MAX_ATTACHMENTS_PER_NOTE,
225 "note cannot contain more than {MAX_ATTACHMENTS_PER_NOTE} attachments"
226 );
227 unsafe {
228 commitments.set_len(num_attachments);
229 }
230 commitments
231}
232
233pub fn write_attachment_to_memory(attachment_commitment: Word) -> Vec<Word> {
237 let mut attachment: Vec<Word> = Vec::with_capacity(MAX_ATTACHMENT_WORDS);
238 let num_words = unsafe {
239 let ptr = (attachment.as_mut_ptr().addr() / 4) as u32;
240 extern_note_write_attachment_to_memory(
241 attachment_commitment[0],
242 attachment_commitment[1],
243 attachment_commitment[2],
244 attachment_commitment[3],
245 ptr as *mut Felt,
246 )
247 };
248 assert!(
249 num_words <= MAX_ATTACHMENT_WORDS,
250 "note attachment cannot contain more than {MAX_ATTACHMENT_WORDS} words"
251 );
252 unsafe {
253 attachment.set_len(num_words);
254 }
255 attachment
256}
257
258pub fn write_indexed_attachment_to_memory(
262 attachment_commitments: &[Word],
263 attachment_idx: Felt,
264) -> Vec<Word> {
265 assert!(
266 attachment_commitments.len() <= MAX_ATTACHMENTS_PER_NOTE,
267 "note cannot contain more than {MAX_ATTACHMENTS_PER_NOTE} attachments"
268 );
269
270 let mut attachment: Vec<Word> = Vec::with_capacity(MAX_ATTACHMENT_WORDS);
271 let num_words = unsafe {
272 let commitments_ptr = if attachment_commitments.is_empty() {
273 0
274 } else {
275 (attachment_commitments.as_ptr().addr() / 4) as u32
276 };
277 let dest_ptr = (attachment.as_mut_ptr().addr() / 4) as u32;
278 extern_note_write_indexed_attachment_to_memory(
279 Felt::from_u32(attachment_commitments.len() as u32),
280 commitments_ptr as *const Felt,
281 attachment_idx,
282 dest_ptr as *mut Felt,
283 )
284 };
285 assert!(
286 num_words <= MAX_ATTACHMENT_WORDS,
287 "note attachment cannot contain more than {MAX_ATTACHMENT_WORDS} words"
288 );
289 unsafe {
290 attachment.set_len(num_words);
291 }
292 attachment
293}
294
295pub fn compute_recipient(
297 serial_num: Word,
298 script_root: Word,
299 storage_commitment: Word,
300) -> Recipient {
301 unsafe {
302 let mut ret_area = ::core::mem::MaybeUninit::<Recipient>::uninit();
303 extern_note_compute_recipient(
304 serial_num[0],
305 serial_num[1],
306 serial_num[2],
307 serial_num[3],
308 script_root[0],
309 script_root[1],
310 script_root[2],
311 script_root[3],
312 storage_commitment[0],
313 storage_commitment[1],
314 storage_commitment[2],
315 storage_commitment[3],
316 ret_area.as_mut_ptr(),
317 );
318 ret_area.assume_init()
319 }
320}
321
322pub fn metadata_into_sender(metadata: Word) -> AccountId {
324 unsafe {
325 let mut ret_area = ::core::mem::MaybeUninit::<RawAccountId>::uninit();
326 extern_note_metadata_into_sender(
327 metadata[0],
328 metadata[1],
329 metadata[2],
330 metadata[3],
331 ret_area.as_mut_ptr(),
332 );
333 ret_area.assume_init().into_account_id()
334 }
335}
336
337pub fn metadata_into_attachment_schemes(metadata: Word) -> Word {
339 unsafe {
340 let mut ret_area = ::core::mem::MaybeUninit::<Word>::uninit();
341 extern_note_metadata_into_attachment_schemes(
342 metadata[0],
343 metadata[1],
344 metadata[2],
345 metadata[3],
346 ret_area.as_mut_ptr(),
347 );
348 ret_area.assume_init()
349 }
350}
351
352pub fn metadata_into_note_type(metadata: Word) -> NoteType {
354 unsafe {
355 NoteType::from(extern_note_metadata_into_note_type(
356 metadata[0],
357 metadata[1],
358 metadata[2],
359 metadata[3],
360 ))
361 }
362}
363
364pub fn metadata_into_tag(metadata: Word) -> Tag {
366 unsafe {
367 Tag::from(extern_note_metadata_into_tag(
368 metadata[0],
369 metadata[1],
370 metadata[2],
371 metadata[3],
372 ))
373 }
374}
375
376pub fn find_attachment_idx(attachment_scheme: Felt, metadata: Word) -> AttachmentLocation {
378 unsafe {
379 let mut ret_area = ::core::mem::MaybeUninit::<AttachmentLocation>::uninit();
380 extern_note_find_attachment_idx(
381 attachment_scheme,
382 metadata[0],
383 metadata[1],
384 metadata[2],
385 metadata[3],
386 ret_area.as_mut_ptr(),
387 );
388 ret_area.assume_init()
389 }
390}