fix: 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


jasonandjay


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-02-17 00:10 UTC

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