bip360: use correct leafVersion in control block byte for non-default version leaves #2103

pull jasonandjay wants to merge 1 commits into bitcoin:master from jasonandjay:fix/control-block-leaf-version-byte changing 1 files +1 −1
  1. jasonandjay commented at 2:03 am on February 15, 2026: none

    Summary

    Fix the first byte of scriptPathControlBlocks[1] in the p2mr_different_version_leaves test vector. The control block incorrectly uses 0xC1 (leafVersion 192) instead of 0xFB (leafVersion 250) for a leaf explicitly declared with "leafVersion": 250.

    Problem

    The P2MR control block’s first byte encodes both the leaf version and parity bit:

    0controlBlock[0] = (leafVersion & 0xfe) | parityBit
    

    For P2MR, the parity bit is always 1. So:

    • leafVersion 192 (0xC0) → 0xC1
    • leafVersion 250 (0xFA) → 0xFB

    The test vector defines two leaves:

    0{ "id": 0, "leafVersion": 192, "script": "...OP_CHECKSIG" }
    1{ "id": 1, "leafVersion": 250, "script": "06424950333431" }
    

    But the current control block for leaf1 starts with 0xC1:

    0scriptPathControlBlocks[1] = "c1 8ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7"
    1                               ^^
    2                               0xC1 → leafVersion = 0xC0 = 192  ✗ (should be 250)
    

    This is incorrect because a verifier would extract leafVersion = 0xC1 & 0xFE = 0xC0 = 192 from this byte, then compute tapleafHash(script, version=192) which produces a completely different hash than the correct tapleafHash(script, version=250), making it impossible to reconstruct the correct Merkle root.

    Fix

    Change the first byte from 0xC1 to 0xFB:

    0scriptPathControlBlocks[1] = "fb 8ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7"
    1                               ^^
    2                               0xFB → leafVersion = 0xFA = 250  ✓
    

    Verification:

    0tapleafHash(script="06424950333431", version=250) = f224a923cd0021ab202ab139cc56802ddb92dcfc172b9212261a539df79a112a
    1sibling = leafHash[0] = 8ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7
    2
    3tapBranchHash(f224a923..., 8ad69ec7...) → hashes are sorted internally
    4→ 6c2dc106ab816b73f9d07e3cd1ef2c8c1256f519748e0813e4edd2405d277bef = merkleRoot ✓
    

    Changes

    • p2mr_different_version_leaves: change scriptPathControlBlocks[1] first byte from c1 to fb
  2. fix: use correct leafVersion in control block byte for non-default version leaves
    The P2MR control block's first byte encodes both the leaf version and
    parity bit: controlBlock[0] = (leafVersion & 0xfe) | parityBit.
    For the leaf with leafVersion 250 (0xFA), the correct first byte is
    0xFB (with parity bit 1), not 0xC1 (which corresponds to leafVersion
    192).
    
    Fix p2mr_different_version_leaves scriptPathControlBlocks[1] first
    byte from c1 to fb.
    c4648bae6b
  3. murchandamus commented at 10:08 pm on February 17, 2026: member
  4. murchandamus added the label Proposed BIP modification on Feb 17, 2026
  5. murchandamus added the label Bug fix on Feb 17, 2026
  6. murchandamus renamed this:
    fix: use correct leafVersion in control block byte for non-default version leaves
    bip360: use correct leafVersion in control block byte for non-default version leaves
    on Feb 17, 2026
  7. EthanHeilman commented at 2:17 pm on February 18, 2026: contributor
    @murchandamus Looking into it
  8. murchandamus added the label Pending acceptance on Feb 27, 2026
  9. murchandamus commented at 5:34 pm on March 16, 2026: member
    Given from the look of this, that a new PR by this author was authored by Openclaw, and from the general activity on this author’s profile, I assume that this PR is AI slop. It may be useful AI slop, which is why I asked for your opinion, but I tend to close this. Will close this in a couple weeks (on or after 2026-03-30), if I don’t hear more from @cryptoquick, or @EthanHeilman.
  10. notmike-5 commented at 6:44 pm on March 16, 2026: none

    Given from the look of this, that a new PR by this author was authored by Openclaw, and from the general activity on this author’s profile, I assume that this PR is AI slop. It may be useful AI slop, which is why I asked for your opinion, but I tend to close this. Will close this in a couple weeks (on or after 2026-03-30), if I don’t hear more from @cryptoquick, or @EthanHeilman.

    This PR is obviously correct.

  11. EthanHeilman commented at 9:12 pm on March 16, 2026: contributor

    @murchandamus @notmike-5 I’m confused about what this PR is trying to say. Let me try to work through it out loud tell me where I’m wrong.

    The only supported leaf version is 0xc0 or 192. P2MR uses this leaf version.

    The PR says:

    0xC1 → leafVersion = 0xC0 = 192 ✗ (should be 250)

    Why should the leaf version be 250? 192 seems correct.

  12. in bip-0360/ref-impl/common/tests/data/p2mr_construction.json:90 in c4648bae6b
    86@@ -87,7 +87,7 @@
    87                 "bip350Address": "bc1zdskuzp4ts94h87ws0c7drmev3sf9dagewj8qsylyahfyqhf800hsam4d6e",
    88                 "scriptPathControlBlocks": [
    89                     "c1f224a923cd0021ab202ab139cc56802ddb92dcfc172b9212261a539df79a112a",
    90-                    "c18ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7"
    91+                    "fb8ad69ec7cf41c2a4001fd1f738bf1e505ce2277acdcaa63fe4765192497f47a7"
    


    murchandamus commented at 9:30 pm on March 16, 2026:

    @EthanHeilman: The description of the test states that the two leaves have different leaf versions and the second leaf uses a hypothetical leaf version of 250 (see line 74).

    One of the reasons I surface this is to ask whether you want to take the proposed action or whether you want to do something else, or additional actions if this is indicative of other issues in your reference implementation. E.g., what was this test with different leaf versions supposed to test? Is it an issue that it didn’t test that and still passed?


    EthanHeilman commented at 10:35 pm on March 16, 2026:

    Ahh, this test case is about different leaf versions, that makes sense. I probably should have noticed the name of the test case was p2mr_different_version_leaves I retract my comment.

    I don’t maintain the reference implementation. @cryptoquick is taking care of it.


    murchandamus commented at 10:38 pm on March 16, 2026:
    Sorry, I should have distinguished. The first line was in response to you, but the rest was generally directed at the authors.
  13. jbride commented at 10:19 pm on March 16, 2026: none

    I believe the correct behavior when encountering a non-standard leaf version in a P2MR merkle tree should be to throw an error.

    My pull request here implements this approach.

  14. cryptoquick commented at 10:24 pm on March 16, 2026: contributor

    Glad this was pointed out, thank you @jasonandjay. That said, we’re going to discuss the proper approach together as a team and address concerns in the PR that @jbride linked: https://github.com/cryptoquick/bips/pull/44

    We are also going to need more time to investigate #2102.

    Any other thoughts or improvements should be directed there to better tie up loose ends and polish things even further.

  15. murchandamus commented at 10:40 pm on March 16, 2026: member
    Thanks for taking a look. I’m going to wait to hear what you want to do about this topic.
  16. notmike-5 commented at 0:22 am on March 17, 2026: none

    According to the section “Script Validation” of BIP-360, which was adapted from BIP-341, it is implied that “for the future leaf versions (non-0xC0) the execution must succeed”.

    As others have pointed to previously, there is a further issue of what to do for leaf version 0xC0 in the context of P2MR. Tapscript validation rules, as defined, explicitly do not apply in this context.

    So, might want to consider lumping these two issues together.


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-03-29 21:10 UTC

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