Skip to content

Commit de42e84

Browse files
feat: add output_not_set_attachment kernel API (#2252)
* feat: Implement `output_note_set_attachment` kernel API * feat: Implement `miden::protocol` set_attachment wrappers * feat: Emit event during `set_attachment` for tx host * chore: add tests for `set_attachment` APIs * chore: regenerate kernel procedure hashes * chore: add changelog * chore: rename `Raw` -> `Word` and `Commitment` -> `Array` * fix: renamed attachment content variants * chore: make attachment content type constants public * chore: move note ptr to idx conversion to helper * chore: merge attachment validation procedures into one * chore: simplify setting output note attachment type info * chore: make `set_attachment` public * fix: commitment to array rename * chore: require attachment_type == 0 when content type is None * chore: enforce none / attachment type restriction in `NoteAttachment`
1 parent d92a830 commit de42e84

19 files changed

Lines changed: 697 additions & 24 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- Add `AccountId::parse()` helper function to parse both hex and bech32 formats ([#2223](https://github.com/0xMiden/miden-base/pull/2223)).
1111
- Add `read_foreign_account_inputs()`, `read_vault_asset_witnesses()`, and `read_storage_map_witness()` for `TransactionInputs` ([#2246](https://github.com/0xMiden/miden-base/pull/2246)).
1212
- [BREAKING] Introduce `NoteAttachment` as part of `NoteMetadata` and remove `aux` and `execution_hint` ([#2249](https://github.com/0xMiden/miden-base/pull/2249)).
13+
- [BREAKING] Introduce `NoteAttachment` as part of `NoteMetadata` and remove `aux` and `execution_hint` ([#2249](https://github.com/0xMiden/miden-base/pull/2249), [#2252](https://github.com/0xMiden/miden-base/pull/2252)).
1314

1415
### Changes
1516

crates/miden-protocol/asm/kernels/transaction/api.masm

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,33 @@ pub proc output_note_add_asset
11891189
# => [pad(16)]
11901190
end
11911191

1192+
#! Sets the attachment of the note specified by the index.
1193+
#!
1194+
#! Inputs: [note_idx, attachment_content_type, attachment_type, ATTACHMENT, pad(9)]
1195+
#! Outputs: [pad(16)]
1196+
#!
1197+
#! Where:
1198+
#! - note_idx is the index of the note on which the attachment is set.
1199+
#! - attachment_content_type is the content type of the attachment.
1200+
#! - attachment_type is the user-defined type of the attachment.
1201+
#! - ATTACHMENT is the attachment to be set.
1202+
#!
1203+
#! Panics if:
1204+
#! - the procedure is called when the active account is not the native one.
1205+
#! - the note index points to a non-existent output note.
1206+
#! - any of the attachment types does not fit into a u32.
1207+
#! - the attachment content type is an unknown variant.
1208+
#!
1209+
#! Invocation: dynexec
1210+
pub proc output_note_set_attachment
1211+
# check that this procedure was executed against the native account
1212+
exec.memory::assert_native_account
1213+
# => [note_idx, attachment_content_type, attachment_type, ATTACHMENT, pad(9)]
1214+
1215+
exec.output_note::set_attachment
1216+
# => [pad(16)]
1217+
end
1218+
11921219
#! Returns the information about assets in the output note with the specified index.
11931220
#!
11941221
#! Inputs: [note_index, pad(15)]

crates/miden-protocol/asm/kernels/transaction/lib/memory.masm

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ const OUTPUT_NOTE_SECTION_OFFSET=16777216
240240
# The offsets at which data of an output note is stored relative to the start of its data segment.
241241
const OUTPUT_NOTE_ID_OFFSET=0
242242
const OUTPUT_NOTE_METADATA_HEADER_OFFSET=4
243+
const OUTPUT_NOTE_METADATA_ATTACHMENT_TYPE_INFO_OFFSET=OUTPUT_NOTE_METADATA_HEADER_OFFSET + 3
243244
const OUTPUT_NOTE_ATTACHMENT_OFFSET=8
244245
const OUTPUT_NOTE_RECIPIENT_OFFSET=12
245246
const OUTPUT_NOTE_ASSETS_COMMITMENT_OFFSET=16
@@ -1891,6 +1892,19 @@ pub proc set_output_note_metadata_header
18911892
mem_storew_be
18921893
end
18931894

1895+
#! Sets the output note's attachment type info in the metadata header.
1896+
#!
1897+
#! Inputs: [note_ptr, attachment_type_info]
1898+
#! Outputs: []
1899+
#!
1900+
#! Where:
1901+
#! - attachment_type_info is the type information of the attachment that will be overwritten.
1902+
#! - note_ptr is the memory address at which the output note data begins.
1903+
pub proc set_output_note_attachment_type_info
1904+
add.OUTPUT_NOTE_METADATA_ATTACHMENT_TYPE_INFO_OFFSET
1905+
mem_store
1906+
end
1907+
18941908
#! Returns the output note's attachment.
18951909
#!
18961910
#! Inputs: [note_ptr]

crates/miden-protocol/asm/kernels/transaction/lib/output_note.masm

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use $kernel::memory
33
use $kernel::note
44
use $kernel::asset
55
use $kernel::constants::MAX_OUTPUT_NOTES_PER_TX
6+
use miden::core::mem
67
use miden::core::word
78

89
# CONSTANTS
@@ -23,6 +24,9 @@ const ATTACHMENT_CONTENT_TYPE_ARRAY=2
2324
# "untyped".
2425
const ATTACHMENT_DEFAULT_TYPE_INFO=0
2526

27+
#! The default attachment type, representing an untyped attachment.
28+
const ATTACHMENT_TYPE_UNTYPED=0
29+
2630
# ERRORS
2731
# =================================================================================================
2832

@@ -32,6 +36,14 @@ const ERR_NOTE_INVALID_TYPE="invalid note type"
3236

3337
const ERR_OUTPUT_NOTE_INDEX_OUT_OF_BOUNDS="requested output note index should be less than the total number of created output notes"
3438

39+
const ERR_OUTPUT_NOTE_INVALID_ATTACHMENT_TYPES="attachment types must fit into u32s"
40+
41+
const ERR_OUTPUT_NOTE_UNKNOWN_ATTACHMENT_CONTENT_TYPE="attachment content type variant must be between 0 and 2"
42+
43+
const ERR_OUTPUT_NOTE_ATTACHMENT_NONE_MUST_HAVE_UNTYPED_ATTACHMENT_TYPE="attachment type of content type none must be 0"
44+
45+
const ERR_OUTPUT_NOTE_ATTACHMENT_NONE_MUST_BE_EMPTY_WORD="attachment of content type none must be set to an empty word"
46+
3547
const ERR_NOTE_INVALID_INDEX="failed to find note at the given index; index must be within [0, num_of_notes]"
3648

3749
const ERR_NOTE_FUNGIBLE_MAX_AMOUNT_EXCEEDED="adding a fungible asset to a note cannot exceed the max_amount of 9223372036854775807"
@@ -53,6 +65,9 @@ const NOTE_BEFORE_ADD_ASSET_EVENT=event("miden::note::before_add_asset")
5365
# Event emitted after an ASSET is added to a note
5466
const NOTE_AFTER_ADD_ASSET_EVENT=event("miden::note::after_add_asset")
5567

68+
# Event emitted before an ATTACHMENT is added to a note
69+
const NOTE_BEFORE_SET_ATTACHMENT_EVENT=event("miden::note::before_set_attachment")
70+
5671
# OUTPUT NOTE PROCEDURES
5772
# =================================================================================================
5873

@@ -185,6 +200,7 @@ end
185200
#! - ASSET can be a fungible or non-fungible asset.
186201
#!
187202
#! Panics if:
203+
#! - the note index points to a non-existent output note.
188204
#! - the ASSET is malformed (e.g., invalid faucet ID).
189205
#! - the max amount of fungible assets is exceeded.
190206
#! - the non-fungible asset already exists in the note.
@@ -239,6 +255,51 @@ pub proc add_asset
239255
# => []
240256
end
241257

258+
#! Sets the attachment of the note specified by the index.
259+
#!
260+
#! Inputs: [note_idx, attachment_content_type, attachment_type, ATTACHMENT]
261+
#! Outputs: []
262+
#!
263+
#! Where:
264+
#! - note_idx is the index of the note on which the attachment is set.
265+
#! - attachment_content_type is the content type of the attachment.
266+
#! - attachment_type is the user-defined type of the attachment.
267+
#! - ATTACHMENT is the attachment to be set.
268+
#!
269+
#! Panics if:
270+
#! - the note index points to a non-existent output note.
271+
#! - any of the attachment types does not fit into a u32.
272+
#! - the attachment content type is an unknown variant.
273+
pub proc set_attachment
274+
dup exec.memory::get_num_output_notes lte assert.err=ERR_NOTE_INVALID_INDEX
275+
# => [note_idx, attachment_content_type, attachment_type, ATTACHMENT]
276+
277+
exec.memory::get_output_note_ptr dup
278+
# => [note_ptr, note_ptr, attachment_content_type, attachment_type, ATTACHMENT]
279+
280+
dupw.1
281+
# => [ATTACHMENT, note_ptr, note_ptr, attachment_content_type, attachment_type, ATTACHMENT]
282+
283+
dup.7 dup.7
284+
# => [attachment_content_type, attachment_type, ATTACHMENT, note_ptr, note_ptr,
285+
# attachment_content_type, attachment_type, ATTACHMENT]
286+
287+
exec.validate_attachment
288+
# => [note_ptr, note_ptr, attachment_content_type, attachment_type, ATTACHMENT]
289+
290+
movdn.3 movdn.3
291+
# => [attachment_content_type, attachment_type, note_ptr, note_ptr, ATTACHMENT]
292+
293+
emit.NOTE_BEFORE_SET_ATTACHMENT_EVENT
294+
# => [attachment_content_type, attachment_type, note_ptr, note_ptr, ATTACHMENT]
295+
296+
exec.set_attachment_type_info
297+
# => [note_ptr, ATTACHMENT]
298+
299+
exec.memory::set_output_note_attachment
300+
# => []
301+
end
302+
242303
#! Assert that the provided note index is less than the total number of output notes.
243304
#!
244305
#! Inputs: [note_index]
@@ -306,6 +367,89 @@ pub proc build_metadata_header
306367
# => [NOTE_METADATA_HEADER]
307368
end
308369

370+
#! Validate the ATTACHMENT against the content type.
371+
#!
372+
#! Inputs: [attachment_content_type, attachment_type, ATTACHMENT]
373+
#! Outputs: []
374+
#!
375+
#! Where:
376+
#! - attachment_type is the user-defined type of the attachment.
377+
#! - attachment_content_type is the content type of the attachment.
378+
#! - ATTACHMENT is the attachment to validate.
379+
#!
380+
#! Panics if:
381+
#! - any of the attachment types does not fit into a u32.
382+
#! - the attachment content type is an unknown variant.
383+
#! - the content type is None and the ATTACHMENT is not an empty word.
384+
proc validate_attachment
385+
u32assert2.err=ERR_OUTPUT_NOTE_INVALID_ATTACHMENT_TYPES
386+
# => [attachment_content_type, attachment_type, ATTACHMENT]
387+
388+
# assert that the attachment content type is valid
389+
dup u32lte.ATTACHMENT_CONTENT_TYPE_ARRAY
390+
assert.err=ERR_OUTPUT_NOTE_UNKNOWN_ATTACHMENT_CONTENT_TYPE
391+
# => [attachment_content_type, attachment_type, ATTACHMENT]
392+
393+
eq.ATTACHMENT_CONTENT_TYPE_NONE
394+
# => [is_attachment_none, attachment_type, ATTACHMENT]
395+
396+
if.true
397+
eq.ATTACHMENT_TYPE_UNTYPED
398+
assert.err=ERR_OUTPUT_NOTE_ATTACHMENT_NONE_MUST_HAVE_UNTYPED_ATTACHMENT_TYPE
399+
# => [ATTACHMENT]
400+
401+
padw assert_eqw.err=ERR_OUTPUT_NOTE_ATTACHMENT_NONE_MUST_BE_EMPTY_WORD
402+
# => []
403+
else
404+
drop dropw
405+
# => []
406+
end
407+
# => []
408+
end
409+
410+
#! Sets an output note's attachment type info in the metadata header.
411+
#!
412+
#! WARNING: The attachment types must be valid.
413+
#!
414+
#! Inputs: [attachment_content_type, attachment_type, note_ptr]
415+
#! Outputs: []
416+
#!
417+
#! Where:
418+
#! - attachment_content_type is the content type of the attachment.
419+
#! - attachment_type is the user-defined type of the attachment.
420+
#! - note_ptr is the memory address at which the output note data begins.
421+
proc set_attachment_type_info
422+
exec.merge_attachment_type_info
423+
# => [attachment_type_info, note_ptr]
424+
425+
swap
426+
# => [note_ptr, attachment_type_info]
427+
428+
exec.memory::set_output_note_attachment_type_info
429+
# => []
430+
end
431+
432+
#! Merges the attachment types into a single felt with the following layout:
433+
#!
434+
#! [30 zero bits | attachment_content_type (2 bits) | attachment_type (32 bits)]
435+
#!
436+
#! WARNING: The attachment types must be valid.
437+
#!
438+
#! Inputs: [attachment_content_type, attachment_type]
439+
#! Outputs: [attachment_type_info]
440+
#!
441+
#! Where:
442+
#! - attachment_content_type is the content type of the attachment.
443+
#! - attachment_type is the user-defined type of the attachment.
444+
#! - attachment_type_info is the felt constructed from the inputs.
445+
proc merge_attachment_type_info
446+
# shift the content type 32 bits to the left, which is the same as multiplying by 2^32
447+
# and set the lower bits to the attachment_type, which is done by adding the values together
448+
mul.0x100000000
449+
add
450+
# => [attachment_type_info]
451+
end
452+
309453
#! Increments the number of output notes by one. Returns the index of the next note to be created.
310454
#!
311455
#! Inputs: []

crates/miden-protocol/asm/protocol/kernel_proc_offsets.masm

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,30 @@ const OUTPUT_NOTE_GET_METADATA_OFFSET=37
6767
const OUTPUT_NOTE_GET_ASSETS_INFO_OFFSET=38
6868
const OUTPUT_NOTE_GET_RECIPIENT_OFFSET=39
6969
const OUTPUT_NOTE_ADD_ASSET_OFFSET=40
70+
const OUTPUT_NOTE_SET_ATTACHMENT_OFFSET=41
7071

7172
### Tx ##########################################
7273

7374
# input notes
74-
const TX_GET_NUM_INPUT_NOTES_OFFSET=41
75-
const TX_GET_INPUT_NOTES_COMMITMENT_OFFSET=42
75+
const TX_GET_NUM_INPUT_NOTES_OFFSET=42
76+
const TX_GET_INPUT_NOTES_COMMITMENT_OFFSET=43
7677

7778
# output notes
78-
const TX_GET_NUM_OUTPUT_NOTES_OFFSET=43
79-
const TX_GET_OUTPUT_NOTES_COMMITMENT_OFFSET=44
79+
const TX_GET_NUM_OUTPUT_NOTES_OFFSET=44
80+
const TX_GET_OUTPUT_NOTES_COMMITMENT_OFFSET=45
8081

8182
# block info
82-
const TX_GET_BLOCK_COMMITMENT_OFFSET=45
83-
const TX_GET_BLOCK_NUMBER_OFFSET=46
84-
const TX_GET_BLOCK_TIMESTAMP_OFFSET=47
83+
const TX_GET_BLOCK_COMMITMENT_OFFSET=46
84+
const TX_GET_BLOCK_NUMBER_OFFSET=47
85+
const TX_GET_BLOCK_TIMESTAMP_OFFSET=48
8586

8687
# foreign context
87-
const TX_START_FOREIGN_CONTEXT_OFFSET=48
88-
const TX_END_FOREIGN_CONTEXT_OFFSET=49
88+
const TX_START_FOREIGN_CONTEXT_OFFSET=49
89+
const TX_END_FOREIGN_CONTEXT_OFFSET=50
8990

9091
# expiration data
91-
const TX_GET_EXPIRATION_DELTA_OFFSET=50 # accessor
92-
const TX_UPDATE_EXPIRATION_BLOCK_DELTA_OFFSET=51 # mutator
92+
const TX_GET_EXPIRATION_DELTA_OFFSET=51 # accessor
93+
const TX_UPDATE_EXPIRATION_BLOCK_DELTA_OFFSET=52 # mutator
9394

9495
# ACCESSORS
9596
# -------------------------------------------------------------------------------------------------
@@ -484,6 +485,19 @@ pub proc output_note_add_asset_offset
484485
push.OUTPUT_NOTE_ADD_ASSET_OFFSET
485486
end
486487

488+
#! Returns the offset of the `output_note_set_attachment` kernel procedure.
489+
#!
490+
#! Inputs: []
491+
#! Outputs: [proc_offset]
492+
#!
493+
#! Where:
494+
#! - proc_offset is the offset of the `output_note_set_attachment` kernel procedure required to get
495+
#! the address where this procedure is stored.
496+
pub proc output_note_set_attachment_offset
497+
push.OUTPUT_NOTE_SET_ATTACHMENT_OFFSET
498+
end
499+
500+
487501
#! Returns the offset of the `output_note_get_assets_info` kernel procedure.
488502
#!
489503
#! Inputs: []

0 commit comments

Comments
 (0)