Skip to content

bip-0360: added python reference example; test vector fixes#2202

Open
notmike-5 wants to merge 15 commits into
bitcoin:masterfrom
notmike-5:p2mr
Open

bip-0360: added python reference example; test vector fixes#2202
notmike-5 wants to merge 15 commits into
bitcoin:masterfrom
notmike-5:p2mr

Conversation

@notmike-5

Copy link
Copy Markdown

This PR adds a python reference example for construction of BIP-360 outputs and control blocks.
This PR updates the test vectors to remove "internalPubkey" key from vectors 7 and 8.
This PR also brings in fixes to #2102 and #2103 from @jbride and @notmike-5

jbride and others added 4 commits June 25, 2026 19:59
This commit adds a python reference example for construction of BIP-360 outputs and control blocks.
This commit also updates the test vectors.

@murchandamus murchandamus left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable at first glance.

cc: @cryptoquick, @EthanHeilman, @Isabelfoxenduke for owner review/sign-off.

@murchandamus murchandamus added Proposed BIP modification PR by non-owner to update BIP content Pending acceptance This BIP modification requires sign-off by the champion of the BIP being modified labels Jun 26, 2026
This refactors `compute_control_block` to improve performance, and make
the function simpler to read (to me at least).

The previous version walked the entire script tree searching for the
first matching instance of the leaf node.

The new version expects the caller to pass in an explicit `path`
parameter, which tells us exactly where the leaf node lives, with
left/right steps encoded as bits in an integer. We walk down the
tree straight to that leaf node, and build the control block as we go.

This might not be the best DX for a real-world API or library, but this
is just reference code, so we can accept poor usage ergonomics if it makes
the code clearer and more explicit.
Comment thread bip-0360/ref-impl/python/p2mr.py Outdated
Comment thread bip-0360/ref-impl/python/p2mr.py
Comment on lines +184 to +185
# Bech32 encoding code is taken from sipa (BIP-0350), and has been tested against the test vectors therein:
# https://github.com/sipa/bech32/blob/master/ref/python/tests.py

@conduition conduition Jun 26, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of this code already exists in the BIPs repository, under the reference code of BIP352 (silent payments).

https://github.com/bitcoin/bips/blob/master/bip-0352/bech32m.py

@murchandamus What are your thoughts on the bech32m code duplication here? is it better to duplicate for the sake of compartmentalization, or should we update the existing code and reference it here?

Comment thread bip-0360/ref-impl/python/p2mr.py Outdated
def compute_merkle_root(tree: ScriptTree) -> str:
"""Recursively compute script tree merkle root"""
if isinstance(tree, dict): # Leaf
version = f"{tree['leafVersion']:x}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems a bit redundant to convert the leaf version number to a hex string, only to convert it right back to bytes in the tapleaf_hash function. Maybe instead just pass the leaf version as an integer to tapleaf_hash?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 94b0f9d. Should be g2g now.

Comment thread bip-0360/ref-impl/python/p2mr.py Outdated
Comment thread bip-0360/ref-impl/python/p2mr.py Outdated
Comment thread bip-0360/ref-impl/python/p2mr.py Outdated
# `tapbranch_hash` returns bytes, not the hex str this loop expects.
assert len(tree) == 2, f"expected binary branch, got {len(tree)} children"
left, right = compute_merkle_root(tree[0]), compute_merkle_root(tree[1])
return tapbranch_hash(left, right).hex()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these functions accept or return hex-strings, while others use bytes for the same conceptual objects. Consistency is better: Either use hex strings for everything, or use bytes for everything. Input from test vectors (or output from the code) can be converted as needed in the tests.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took a stab at this in 94b0f9d. It also cleaned up the code quite a bit in places.

Comment thread bip-0360/ref-impl/python/p2mr.py Outdated
test_vectors
});

static P2TR_USING_V2_WITNESS_VERSION_ERROR: &str = "p2tr_using_v2_witness_version_error";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be renamed to "p2tr_using_v2_witness_version_error" to follow the test vector renaming.

Currently cargo test fails with:

  called `Option::unwrap()` on a `None` value

After renaming it passed.

@notmike-5 notmike-5 Jun 27, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test is checking p2mr misuse and specifically presence of an internal pubkey. That said, I don't have strong feelings one way or the other. We might need to update this file to also reflect the new test vector @jbride.

Standardizes all P2MR-specific functions to use bytes uniformly for
input/output. Hex conversions are now confined to two boundaries:
reading `script` field out of ScriptTree input, and comparing against
hex-encoded test vector data in `run_single_test`.

bech32 functions and s2w are left unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Pending acceptance This BIP modification requires sign-off by the champion of the BIP being modified Proposed BIP modification PR by non-owner to update BIP content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants