Skip to content

Conversation

@PhilippGackstatter
Copy link
Contributor

@PhilippGackstatter PhilippGackstatter commented Jan 9, 2026

Changes

  • Adds a new kernel API output_note_set_attachment to overwrite the attachment of an output note.
  • Adds handling of set_attachment in the tx host to update the note with the new attachment.
  • Adds tests for each public set_attachment API in miden::protocol.

Choices

  • There is a dedicated API for each attachment content type in miden::protocol, i.e. set_none_attachment, set_raw_attachment, set_commitment_attachment. The main use of these is to make it less confusing for users, since a more generic set_attachment API would require setting both attachment content type and attachment type, which are probably easily confused. We can still easily expose set_attachment if there is a need.
    • The set_none_attachment doesn't read very nice, maybe set_empty_attachment would be better (which implies a more comprehensive rename). Another alternative could be set_default_attachment.
  • $kernel::output_note::validate_attachment does not validate that the elements of a NoteAttachmentContentType::Commitment are in the advice provider. I think we could add this, but I'm not yet sure if it's strictly necessary. Since it isn't otherwise accessed in the kernel, the kernel doesn't necessarily care that the preimage is actually present. It would be easy to add this in a separate PR, too.

Follow-Ups

  • Remove aux and exec hint from output_note::create and replace aux with attachment in tests where it makes sense.
  • Extend the new tests or write new ones to check that accessing the attachment after a set_attachment call returns the expected value.

part of #2109

Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you! I left some comments inline - most a pretty minor.

Also, we should update the kernel API docs to add the new public procedures to the Output Notes section.

Comment on lines +735 to +744
let note_idx = u32::try_from(note_ptr)
.map_err(|_| TransactionKernelError::other("failed to convert note_ptr to u32"))
.and_then(|note_ptr| {
note_ptr
.checked_sub(OUTPUT_NOTE_SECTION_OFFSET)
.ok_or_else(|| {
TransactionKernelError::other("failed to calculate note_idx from note_ptr")
})
.map(|note_ptr| note_ptr / NOTE_MEM_SIZE)
})?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe this should be a helper function?

Comment on lines +8 to +10
const ATTACHMENT_CONTENT_TYPE_NONE=0
const ATTACHMENT_CONTENT_TYPE_RAW=1
const ATTACHMENT_CONTENT_TYPE_COMMITMENT=2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make these public?

#! - the attachment_type does not fit into a u32.
#!
#! Invocation: exec
pub proc set_none_attachment
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (feel free to ignore): maybe this could be set_attachment_none or set_attachment_to_none?

Would also be relevant to set_attachment_raw and set_attachment_commitment.

Comment on lines +188 to +189
#! Inputs: [note_idx, attachment_type]
#! Outputs: []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to pass in the attachment_type here? Shouldn't none imply untyped?

Comment on lines 12 to 15
# Constants for different note types
const PUBLIC_NOTE=1 # 0b01
const PRIVATE_NOTE=2 # 0b10
const ENCRYPTED_NOTE=3 # 0b11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer need ENCRYPTED_NOTE, right? Is this something to be removed in a subsequent PR?

Comment on lines 17 to 20
# Constants for note attachment content types
const ATTACHMENT_CONTENT_TYPE_NONE=0
const ATTACHMENT_CONTENT_TYPE_RAW=1
const ATTACHMENT_CONTENT_TYPE_COMMITMENT=2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have these defined in a couple of places. Now that we can export/import constants, I wonder if there is a good central place we could put them in.

Comment on lines +401 to +404
#! Panics if:
#! - any of the attachment types does not fit into a u32.
#! - the attachment content type is an unknown variant.
proc validate_attachment_type_info
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also check that if attachment_type is none, attachment_content_type should be untyped?

#!
#! Panics if:
#! - the content type is None and the ATTACHMENT is not an empty word.
proc validate_attachment
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we split attachment validation into two procedures (this one and validate_attachment_type_info)? We could probably have just one procedure - i.e., something like:

#! Inputs:  [attachment_content_type, attachment_type, ATTACHMENT]
#! Outputs: []
proc validate_attachment
    ...
end

Comment on lines +429 to +438
dup.1 exec.memory::get_output_note_metadata_header
# => [METADATA_HEADER, new_attachment_type_info, note_ptr]
# => [[attachment_type_info, tag, sender_id_prefix, sender_id_suffix_and_note_type], new_attachment_type_info, note_ptr]

swap.4
# => [[new_attachment_type_info, tag, sender_id_prefix, sender_id_suffix_and_note_type], attachment_type_info, note_ptr]
# => [METADATA_HEADER, attachment_type_info, note_ptr]

movup.5 exec.memory::set_output_note_metadata_header
# => [METADATA_HEADER, attachment_type_info]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (feel free to ignore): it may be easier to overwrite just the specific element in the metadata header rather than read the full header, update one element, and then save the full header back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants