bip360: add spend-path test vectors #2232

pull jeanpablojp wants to merge 1 commits into bitcoin:master from jeanpablojp:bip360-spend-vectors changing 1 files +1285 −0
  1. jeanpablojp commented at 9:55 PM on August 1, 2026: contributor

    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/expected with the sighash midstates at group level. invalidSpending holds nine 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_tree at depth 0, no signature: the v0.12.0 anyone-can-spend rule
    • p2mr_different_version_leaves through 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

    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, 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.

  2. jonatack added the label Proposed BIP modification on Aug 2, 2026
  3. jonatack added the label Pending acceptance on Aug 3, 2026
  4. murchandamus commented at 11:04 PM on August 13, 2026: member
  5. bip360: add spend-path test vectors
    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.
    adbc31fe33
  6. jeanpablojp force-pushed on Aug 15, 2026

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bips. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-09-13 01:10 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me