-
Notifications
You must be signed in to change notification settings - Fork 106
feat: insert unpadded note inputs into advice_inputs
#2232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
d089d6f to
bc31d97
Compare
bc31d97 to
a5bfeff
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR changes how NoteInputs are stored in the advice map, moving from padded to unpadded values. This simplifies the assembly code by removing the need for rounding logic when reading note inputs.
Key changes:
NoteInputs::to_elements()now returns unpadded values instead of padded values- Assembly code uses
adv.push_mapvaln.8which handles padding automatically when reading from the advice map - Removed rounding logic in
write_inputs_to_memoryprocedure that was previously needed to validate padded input counts
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
crates/miden-protocol/src/note/inputs.rs |
Modified to_elements() to return unpadded values, simplifying the API while maintaining correct commitment computation |
crates/miden-protocol/asm/protocol/active_note.masm |
Changed to adv.push_mapvaln.8 and removed rounding logic, as padding is now handled by the VM instruction |
crates/miden-testing/src/kernel_tests/tx/test_note.rs |
Updated test cases to use 8 values (exact block size) instead of 13, and added assertions to verify advice map contents contain unpadded values |
CHANGELOG.md |
Documented the breaking change in advice map format |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
bobbinth
left a comment
There was a problem hiding this 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 a few small comments inline.
| # drop the hasher state and dest_ptr' | ||
| dropw dropw dropw drop | ||
| # OS => [NOTE_INPUTS_COMMITMENT, num_inputs, dest_ptr] | ||
|
|
||
| # compute and validate the inputs commitment (over the unpadded values) | ||
| dup.5 dup.5 swap | ||
| exec.note::compute_inputs_commitment | ||
| assert_eqw.err=ERR_NOTE_DATA_DOES_NOT_MATCH_COMMITMENT | ||
| # => [num_inputs, dest_ptr] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't really need to call compute_inputs_commitment here. The pipe_words_to_memory (or pipe_double_words_to_memory) have already done the heavy-lifting of computing the hash - so, we just need to extract it from the stack. This could be done like so:
# => [C, B, A, dest_ptr', NOTE_INPUTS_COMMITMENT, num_inputs, dest_ptr]
exec.rpo256::squeeze_digest
# => [COMPUTED_COMMITMENT, dest_ptr', NOTE_INPUTS_COMMITMENT, num_inputs, dest_ptr]
movup.4 drop
# => [COMPUTED_COMMITMENT, NOTE_INPUTS_COMMITMENT, num_inputs, dest_ptr]
assert_eqw.err=ERR_NOTE_DATA_DOES_NOT_MATCH_COMMITMENT
# => [num_inputs, dest_ptr]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue with this is that pipe_words_to_memory computes the hash over the padded inputs (we need to pad with zeros to obtain full words for copying) - and with this PR, we've switched to committing to unpadded inputs, so the results will mismatch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree this is a bit wasteful - we're only using the instruction to move data from advice stack to memory, and performing the verification separately. Ideally we'd have either a way to:
- A) purely move words to memory without hashing, call it
copy_words_to_memory - B) pipe an arbitrary number of elements, with the hashing done with
exec.rpo256::hash_elements- i.e. similar to the currentpipe_{words/double_words}_to_memory, but one that works over the exact number of elements, not full words. Call itpipe_elements_to_memory.
I can foresee use cases for both instructions, so maybe both are useful independently of which approach we take here?
In any case for this PR we won't have this instruction in miden-vm ready. But once the new instruction(s) is available, I'd prefer approach B) here, as actually reduces the surface of exposed procedures and lets us get rid of the note::compute_inputs_commitment procedure (pipe_elements_to_memory would take care of exactly computing the inputs commitment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue with this is that
pipe_words_to_memorycomputes the hash over the padded inputs (we need to pad with zeros to obtain full words for copying) - and with this PR, we've switched to committing to unpadded inputs, so the results will mismatch.
This shouldn't be an issue. Because of how the padding rule works for RPO, padding the last permutation with zeros should not change the resulting hash. Previously, there was an issue which how to do this but adv.push_mapvaln.8 instruction solves this.
So, we should be able to use pipe_double_words_to_memory and then just get the digest from the values on the stack. This would avoid the need to hash the memory again.
purely move words to memory without hashing, call it
copy_words_to_memory
This could work but it would double the cost (in terms of the number of cycles and memory accesses). The main idea of pipe_double_words_to_memory (and other instructions) is that we can copy to memory and hash at the same time. The ability to specify the padding amount adv.push_mapvaln let's us work with any number of inputs.
pipe an arbitrary number of elements, with the hashing done with
exec.rpo256::hash_elements- i.e. similar to the currentpipe_{words/double_words}_to_memory, but one that works over the exact number of elements, not full words. Call itpipe_elements_to_memory.
We could (and maybe should) add such a procedure - but it would be much more expensive (like several times more expensive) then the pipe_double_words_to_memory approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In any case for this PR we won't have this instruction in
miden-vmready. But once the new instruction(s) is available, I'd prefer approach B) here, as actually reduces the surface of exposed procedures and lets us get rid of thenote::compute_inputs_commitmentprocedure (pipe_elements_to_memorywould take care of exactly computing the inputs commitment)
The main motivation for introducing adv.push_mapvaln.8 was to avoid using such a procedure :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, done in chore: squeeze rpo digest instead of rehashing
bobbinth
left a comment
There was a problem hiding this 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!
For
NoteInputsconstructed from avalues: Vec<Felt>, the advice map used be populated with:With this PR, the first entry 1. changes to:
Since we're now using the padded version of
adv.push_mapvaln.8, the data written to memory stays the same (padded to the next multiple of 8), but the trailing zeros are not used to compute (and to verify) the commitment.closes #2129 (although not by changing
build_recipient, as indicated here)closes #2036
EDIT: the first iteration still committed to padded values. Changed to commit to unpadded inputs