Merged
Conversation
Fix three security issues with Dilithium opcode integration: 1. Dilithium opcodes (OP_CHECKSIGDILITHIUM, OP_CHECKSIGDILITHIUMVERIFY, OP_CHECKMULTISIGDILITHIUM, OP_CHECKMULTISIGDILITHIUMVERIFY) were not counted by GetSigOpCount, allowing blocks with unbounded Dilithium signature verifications that bypass the 80k sigop limit (DoS vector). 2. Dilithium opcodes (0xbb-0xbf) fell within the OP_SUCCESSx range (0xbb-0xfe) in tapscript, causing any tapscript containing a Dilithium opcode to unconditionally succeed without validation, making affected outputs anyone-can-spend. 3. Even with the OP_SUCCESSx fix, Dilithium opcodes in tapscript provide a false sense of security because P2TR outputs expose the internal public key on-chain, leaving them vulnerable to quantum key recovery via the key path (see BIP360). Dilithium opcodes are now explicitly disabled in tapscript with SCRIPT_ERR_TAPSCRIPT_DILITHIUM, following the same pattern as OP_CHECKMULTISIG in tapscript. Changes: - script: count Dilithium opcodes in CScript::GetSigOpCount() - script: narrow IsOpSuccess() range from 0xbb-0xfe to 0xc0-0xfe - script: reject Dilithium opcodes in tapscript execution context - script: add SCRIPT_ERR_TAPSCRIPT_DILITHIUM error code - test: add Dilithium opcode definitions to Python test framework - test: fix is_op_success() in Python test framework to match C++ - test: add feature_dilithium_sigops.py integration test suite~
Implement SegWit version 2 P2MR outputs as specified in BIP360. P2MR provides a quantum-resistant script tree output type by removing the Taproot key path spend, which exposes a public key vulnerable to quantum key recovery via Shor's algorithm. P2MR commits directly to the script tree Merkle root (no internal key, no tweak), enabling Dilithium post-quantum signature opcodes to provide real protection inside the script tree. Consensus changes: - Add SigVersion::P2MR_TAPSCRIPT and SCRIPT_VERIFY_P2MR flag - Add VerifyP2MRCommitment (Merkle root verification without tweak) - Add witversion==2 branch in VerifyWitnessProgram - No key path (reject witness stack with fewer than 2 elements) - Control block format 1+32*m bytes (no internal key) - Parity bit enforcement (must be 1 per BIP360) - Validation weight for Dilithium signature checks - Route P2MR_TAPSCRIPT through EvalChecksigTapscript, SignatureHashSchnorr, CheckSchnorrSignature, and ExecuteWitnessScript - Re-enable Dilithium opcodes in P2MR tapscript context (blocked in P2TR) - Block OP_CHECKMULTISIG in P2MR (inherited from BIP342 tapscript rules) Address and type system: - Add WitnessV2P2MR destination type and TxoutType::WITNESS_V2_P2MR - Add bc1z address encoding/decoding (SegWit v2, bech32m) - Add P2MRBuilder for constructing P2MR outputs from script trees - Add P2MRSpendData for script path spending Policy and activation: - Add P2MR witness standardness checks - Activate SCRIPT_VERIFY_P2MR on all networks Tests: - Add feature_p2mr.py with 15 test groups covering output format, script path spending with mining verification, no key path, all 5 Dilithium opcodes (P2MR vs P2TR comparative), error messages, OP_CHECKMULTISIG blocking, multi-leaf trees (2 and 4 leaves), invalid Merkle proofs, invalid control block sizes, parity bit enforcement, address encoding, and multi-input transactions - Add p2mr_construct() and P2MRInfo to Python test framework
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.
Consensus Changes
SigVersion::P2MR_TAPSCRIPTandSCRIPT_VERIFY_P2MRflagVerifyP2MRCommitment— Merkle root verification without the Taproot tweak stepwitversion == 2branch inVerifyWitnessProgram:1 + 32*mbytes (no internal key, 32 bytes smaller than P2TR)1per BIP360 specificationP2MR_TAPSCRIPTthroughEvalChecksigTapscript,SignatureHashSchnorr,CheckSchnorrSignature, andExecuteWitnessScriptOP_CHECKMULTISIGblocked in P2MR tapscript (inherited from BIP342 rules)Address and Type System
WitnessV2P2MR(32-byte Merkle root)TxoutType::WITNESS_V2_P2MRbc1z...on mainnet,qcrt1z...on regtest (SegWit v2, bech32m)P2MRBuilder— constructs P2MR outputs from script trees (no internal key)P2MRSpendData— control blocks in1 + 32*mformatPolicy and Activation
SCRIPT_VERIFY_P2MRactivated on all networksTest Coverage
test/functional/feature_p2mr.py— 15 test groups with BIP-level rigor:OP_2 <32 bytes>, same size as P2TR1 + 32*mrejectedEvery successful spend is mined in a block and verified at the consensus level, not just mempool acceptance. Every rejection asserts the specific error message to prevent false passes.
Why P2MR Matters
Taproot (P2TR) outputs expose the internal public key on-chain, making them vulnerable to long-exposure quantum attacks. Even if you use Dilithium signatures in a P2TR script leaf, an attacker with a CRQC can bypass it entirely via the key path.
P2MR removes the key path, so there is no exposed public key to attack. Combined with Dilithium opcodes in the script tree, P2MR provides end-to-end quantum resistance for BTQ outputs.
Files Modified