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. Two transactions carry the valid cases, per-input given/intermediary/expected with the sighash midstates at group level. invalidSpending holds ten standalone transactions that must fail; error is 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:
- depth-1 leaf, SIGHASH_DEFAULT
- depth-2 leaf of a three-leaf tree, SIGHASH_ALL (65-byte signature)
- annex, covered by the signature
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 unencumbered- depth-128 leaf, control block at its 4097-byte maximum: the accepting side of the depth limit
- a second transaction with one input for each of the other five hash types (SIGHASH_NONE, SIGHASH_SINGLE and the three ANYONECANPAY forms), with SINGLE|ANYONECANPAY at input 1 so it signs output 1 and not output 0
Invalid: 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, a signature with the undefined hash type 0x80, 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 at m = 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_zero expects failure when the last bit of c[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.