bip360: add spend-path test vectors - #2232
Open
jeanpablojp wants to merge 1 commit into
Open
Conversation
Member
|
cc: @cryptoquick |
The existing vectors are construction-only, so implementations have to
invent their own spend coverage. This adds a spending file in the shape
of bip-0341/wallet-test-vectors.json, adapted to an output type whose
only spend path is the script path.
One transaction with six inputs covers the valid cases, with the five
shared BIP 341 sighash hashes at the group level and per-input given,
intermediary and expected fields. A separate invalidSpending array has
nine self-contained transactions that must fail validation, with the
reason in a short spec-level error string.
Private keys are sha256("p2mr_spending/key/<n>"), prevout txids are
sha256("p2mr_spending/prevout/<n>") in internal byte order, and signing
is BIP 340 with an all-zero aux, so the signatures can be re-derived
rather than trusted. Two of the inputs reuse trees from
p2mr_construction.json, which makes the two files cross-check each
other.
jeanpablojp
force-pushed
the
bip360-spend-vectors
branch
from
August 15, 2026 18:36
92cb0b1 to
adbc31f
Compare
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.
BIP 360's vectors stop at construction: a script tree goes in, leaf hashes, Merkle root, scriptPubKey, address and control blocks come out. There is nothing to spend, unlike BIP 341's wallet-test-vectors.json, so every implementation ends up writing its own spend coverage. This adds the spend-path vectors offered in the Delving write-up (https://delvingbitcoin.org/t/bip-360-p2mr-implemented-in-bitcoin-core-on-regtest-vector-results-measurements-spec-feedback/2751).
The schema mirrors bip-0341/wallet-test-vectors.json, adapted to an output type whose only spend path is the script path. One transaction with six inputs carries the valid cases, per-input
given/intermediary/expectedwith the sighash midstates at group level.invalidSpendingholds nine standalone transactions that must fail;erroris a spec-level description for implementations to map onto their own codes, and several deliberately collapse onto one code in ours. Inputs spent without a signature have privkey/hashType/annex/sigMsg/sigHash null rather than absent.Valid:
p2mr_single_leaf_script_treeat depth 0, no signature: the v0.12.0 anyone-can-spend rulep2mr_different_version_leavesthrough its 0xfa leaf: unknown leaf versions are unencumberedInvalid: flipped signature, tampered Merkle path, control byte with the last bit 0, single-element witness, two-element witness ending in an annex, no witness at all, and control blocks of 0, 34 and 4129 bytes, which is one too short for the control byte, one that is not
1 + 32*m, and one atm = 129.Both named trees come from p2mr_construction.json and are asserted against it when the file is generated, so the two files cross-check each other. Keys and prevout txids are derived deterministically and signing is BIP 340 with an all-zero aux, so the file regenerates from scratch.
One case takes a position the spec leaves open:
p2mr_spend_control_byte_low_bit_zeroexpects failure when the last bit ofc[0]is 0. Script Validation says that bit "is unused and must be 1" and the footnote says a faulty deserialization "will cause an immediate error", but that bullet states no failure condition, while the length rule above it does. If non-enforcement is the intended reading I am happy to drop the vector and the footnote could be reworded; either way it would help to have it explicit.Verified against a Bitcoin Core implementation of the BIP: every valid input passes VerifyScript and every invalid case fails with the expected script error (https://github.com/jeanpablojp/bitcoin/tree/p2mr-regtest, src/test/p2mr_vector_tests.cpp). The generator is test/functional/tool_p2mr_spend_vectors.py on the same branch.