feat: insert unpadded note inputs into advice_inputs#2232
Conversation
d089d6f to
bc31d97
Compare
bc31d97 to
a5bfeff
Compare
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
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.
thanks, done in chore: squeeze rpo digest instead of rehashing
Since note storage items are no longer padded (after PR 0xMiden#2232), the actual length of storage_items in the advice map equals num_items. The separate advice map entry for storage item count is therefore redundant. This change removes: - The advice map entry inserting num_storage_items (tx_args.rs) - The lookup and validation of num_storage_items (kernel_process.rs) - The test assertion for the removed advice map entry (test_note.rs) Closes 0xMiden#2317
Since note storage items are no longer padded (after PR 0xMiden#2232), the actual length of storage_items in the advice map equals num_items. The separate advice map entry for storage item count is therefore redundant. This change removes: - The advice map entry inserting num_storage_items (tx_args.rs) - The lookup and validation of num_storage_items (kernel_process.rs) - The test assertion for the removed advice map entry (test_note.rs) Closes 0xMiden#2317
Since note storage items are no longer padded (after PR 0xMiden#2232), the actual length of storage_items in the advice map equals num_items. The separate advice map entry for storage item count is therefore redundant. This change removes: - The advice map entry inserting num_storage_items (tx_args.rs) - The lookup and validation of num_storage_items (kernel_process.rs) - The test assertion for the removed advice map entry (test_note.rs) Closes 0xMiden#2317
Since note storage items are no longer padded (after PR #2232), the actual length of storage_items in the advice map equals num_items. The separate advice map entry for storage item count is therefore redundant. This change removes: - The advice map entry inserting num_storage_items (tx_args.rs) - The lookup and validation of num_storage_items (kernel_process.rs) - The test assertion for the removed advice map entry (test_note.rs) Closes #2317 Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
…den#2376) Since note storage items are no longer padded (after PR 0xMiden#2232), the actual length of storage_items in the advice map equals num_items. The separate advice map entry for storage item count is therefore redundant. This change removes: - The advice map entry inserting num_storage_items (tx_args.rs) - The lookup and validation of num_storage_items (kernel_process.rs) - The test assertion for the removed advice map entry (test_note.rs) Closes 0xMiden#2317 Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
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