fix(pqvm): align PQVERIFY/PQHASH opcode ABI to white paper §1058-1091#55
Open
LucienSong wants to merge 1 commit into
Open
fix(pqvm): align PQVERIFY/PQHASH opcode ABI to white paper §1058-1091#55LucienSong wants to merge 1 commit into
LucienSong wants to merge 1 commit into
Conversation
PQVERIFY (0xB0): change from 2 stack inputs (packed flat payload) to 7 separate stack inputs per WP §1058: algo_id, msg_ptr, msg_len, pk_len, pk_ptr, sig_len, sig_ptr -> result Each of sig, pk, and msg is read from its own memory region. algo_id now accepts 0x00=Dilithium3, 0x01=ML-DSA-65, 0x02=SLH-DSA-SHA2-256f. The old flat wire format (1-byte algo_id ‖ packed payload) is removed. PQHASH (0xB1): change from 2 stack inputs + stack return to 3 stack inputs + memory side-effect per WP §1062: data_ptr, data_len, out_ptr -> (side effect) Writes 32-byte BLAKE3-256 result directly to out_ptr instead of pushing a U256. Gas formula unchanged: 30 + 6×⌈len/32⌉. PQADDR (0xB2): rename stack parameter names only (offset→pk_ptr, len→pk_len); ABI was already WP-aligned (§1065). Remove old verify_mldsa65 and verify_slhdsa packed-format helper functions (no longer needed; pq_verify calls verify_signature directly). Update tests to use verify_signature directly instead. Add ALGO_DILITHIUM3 = 0x00 constant alongside existing ALGO_MLDSA65 and ALGO_SLHDSA_SHA2_256F. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the PQVM native opcode ABIs in shell-pqvm to match the Shell-Chain white paper (§1058–1091), notably changing PQVERIFY to a 7-argument ABI and PQHASH to write its output to memory instead of pushing to the stack.
Changes:
- Updated
PQVERIFY (0xB0)to accept(algo_id, msg_ptr, msg_len, pk_len, pk_ptr, sig_len, sig_ptr)and verify signatures from three independent memory regions. - Updated
PQHASH (0xB1)to accept(data_ptr, data_len, out_ptr)and write the 32-byte BLAKE3 digest to memory (no stack output). - Kept
PQADDR (0xB2)behavior while renaming variables for clarity and removing packed-format helper verifiers.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+104
to
+111
| let Some(msg_ptr_u256) = context.interpreter.stack.pop() else { | ||
| context.interpreter.halt_underflow(); | ||
| return; | ||
| }; | ||
| let Some(msg_len_u256) = context.interpreter.stack.pop() else { | ||
| context.interpreter.halt_underflow(); | ||
| return; | ||
| }; |
| //! |----------|----------------------------------------------------------| | ||
| //! | PQVERIFY | 46 000 (ML-DSA-65) / 2 300 000 (SLH-DSA) | | ||
| //! | PQVERIFY | 46 000 (ML-DSA-65 / Dilithium3) / 2 300 000 (SLH-DSA) | | ||
| //! | PQHASH | 30 + 6 × ⌈len/32⌉ | |
Comment on lines
+189
to
237
| let sig_bytes: Vec<u8> = if sig_len > 0 { | ||
| context | ||
| .interpreter | ||
| .memory | ||
| .slice_len(sig_ptr, sig_len) | ||
| .as_ref() | ||
| .to_vec() | ||
| } else { | ||
| vec![] | ||
| }; | ||
| let pk_bytes: Vec<u8> = if pk_len > 0 { | ||
| context | ||
| .interpreter | ||
| .memory | ||
| .slice_len(pk_ptr, pk_len) | ||
| .as_ref() | ||
| .to_vec() | ||
| } else { | ||
| vec![] | ||
| }; | ||
| let msg_bytes: Vec<u8> = if msg_len > 0 { | ||
| context | ||
| .interpreter | ||
| .memory | ||
| .slice_len(msg_ptr, msg_len) | ||
| .as_ref() | ||
| .to_vec() | ||
| } else { | ||
| vec![] | ||
| }; | ||
|
|
||
| let valid = match algo_byte { | ||
| ALGO_MLDSA65 | ALGO_DILITHIUM3 => { | ||
| let sig_type = if algo_byte == ALGO_MLDSA65 { | ||
| SignatureType::MlDsa65 | ||
| } else { | ||
| SignatureType::Dilithium3 | ||
| }; | ||
| verify_signature(sig_type, &pk_bytes, &msg_bytes, &sig_bytes).unwrap_or(false) | ||
| } | ||
| ALGO_SLHDSA_SHA2_256F => verify_signature( | ||
| SignatureType::SphincsSha2256f, | ||
| &pk_bytes, | ||
| &msg_bytes, | ||
| &sig_bytes, | ||
| ) | ||
| .unwrap_or(false), | ||
| _ => false, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 3 of the white-paper alignment plan — PQVM execution layer cleanup.
Phase 3a — PQVM opcode ABI alignment (WP §1058-1091)
PQVERIFY rewritten from 2 stack args (flat packed blob) to 7 separate args:
algo_id, msg_ptr, msg_len, pk_len, pk_ptr, sig_len, sig_ptr → resultALGO_DILITHIUM3 = 0x00constant (WP §1073)verify_signature(algo, pk, msg, sig)directly; removes old packed-format helpersPQHASH rewritten from 2 stack args + stack return to 3 args + memory side-effect:
data_ptr, data_len, out_ptr → (side effect: 32-byte BLAKE3 written to out_ptr)PQADDR parameter names corrected to
algo_id, pk_ptr, pk_len(semantics unchanged).Phase 3b — StateDb address bridge cleanup
pq_hints→address_registryinShellStateDb; clearer semanticsregister_pq_address(),resolve_address(),clear_address_registry(),address_registry_snapshot()pq_addr_map: HashMapfromTxExecutionResult; eliminates clone duplication on every commitcommit_pqvm_stateto take&mut ShellStateDb<S>— uses registry for correct 32-byte PQ address resolutioncommit_pqvm_state_raw(result, world_state, chain_store, registry)for block_producer's dual-commit patterndo_commit_state()core logic shared by both commit variantsTests
All 236
shell-pqvmtests pass, including all 3 AA integration tests.cargo fmt --checkandcargo clippy --workspace -- -D warningsboth clean.Checklist
cargo fmt --checkcargo clippy --workspace -- -D warningscargo test -p shell-pqvm(236 pass, 0 fail)