Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion bip-0110.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Blocks during a temporary, one-year deployment are checked with these additional

# New output scriptPubKeys exceeding 34 bytes are invalid, unless the first opcode is OP_RETURN, in which case up to 83 bytes are valid.
# OP_PUSHDATA* payloads and [[#script-argument-witness-items|script argument witness items]] exceeding 256 bytes are invalid, except for the redeemScript push in BIP16 scriptSigs.
# Spending undefined witness (or Tapleaf) versions (ie, not Witness v0/BIP 141, Taproot/BIP 341, or P2A) is invalid. (Creating outputs with undefined witness versions is still valid.)
# Spending undefined witness (or Tapleaf) versions (ie, anything not listed under [[#defined-witness-versions|Defined witness versions]] below) is invalid. (Creating outputs with undefined witness versions is still valid.)
# Witness stacks with a Taproot annex are invalid.
# Taproot control blocks larger than 257 bytes (a merkle tree with 128 script leaves) are invalid.
# Tapscripts including OP_SUCCESS* opcodes anywhere (even unexecuted) are invalid.
Expand All @@ -37,6 +37,15 @@ This grandfathering ensures that no existing coins can be frozen or rendered uns
The new rules apply only to UTXOs created at or after the activation height.
Once the softfork expires, UTXOs of all heights are once again unrestricted.

<span id="defined-witness-versions"></span>
===Defined witness versions===

For the purposes of rule 3, these are the witness versions (and the one Tapleaf version) that are defined as of this BIP:

* '''Witness v0''' with a 20-byte program (P2WPKH) or a 32-byte program (P2WSH), as defined in [[bip-0141.mediawiki|BIP 141]]. Other v0 program lengths are already invalid under BIP 141 itself.
* '''Witness v1''' with a 32-byte program (Taproot/P2TR), as defined in [[bip-0341.mediawiki|BIP 341]]. In a script path spend, the only defined Tapleaf version is 0xc0 (Tapscript), as defined in [[bip-0342.mediawiki|BIP 342]].
* '''Witness v1''' with the 2-byte program 0x4e73 (P2A), and only when spent with an empty witness stack, as defined in [[bip-0433.mediawiki#specification|BIP 433]].
Comment thread
murchandamus marked this conversation as resolved.
Outdated
Comment thread
dathonohm marked this conversation as resolved.
Outdated

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.

I'm all for appeasing the author, as long as it's a clear win for documentations spec, integrity, and a win for implementers of this bip.

But the author is stating here, as written, that bip433 states a p2a must be spent with an empty witness, which is incorrect.

All attempts around the 8th rule, point to this being a clear isolatable consensus rule imposed by bip110

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

But the author is stating here, as written, that bip433 states a p2a must be spent with an empty witness

That is indeed what it says:

"P2A inputs are considered standard by Bitcoin Core for spending if no witness data is attached."
Screenshot 2026-07-29 at 15 25 06

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.

"Consensus meaning is unchanged"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We've been over this; "Consensus meaning is unchanged" just means that P2A has no consensus meaning at all. That isn't relevant to BIP-110.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2A output type specifically states that no witness data is attached.
If witness data is attached to the above specification, can it still be considered P2A? @jarolrod

@john-moffett john-moffett Jul 30, 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.

@delcin-raj

P2A output type specifically states that no witness data is attached.

The output type is defined independently of the spend. It's a template, just like P2MS or P2PKH. Spending a P2A with witness data is currently consensus valid. The current relay policy, however, restricts it to an empty witness.

If witness data is attached to the above specification, can it still be considered P2A?

Undoubtedly, as BIP 433 is unequivocal in its definition of P2A: it's the output type, not the separate policy restricting its spend. In Bitcoin Core, IsPayToAnchor only looks at the scriptPubKey. It's like asking whether a 6-of-12 P2MS is still considered a P2MS despite it not relaying in Bitcoin Core due to policy. The answer is yes.

Edit: to address @dathonohm 's objection about "P2A has no consensus meaning at all". That's not true. The script pattern had existing consensus meaning before P2A (anyone can spend even with a non-empty witness), just like P2MS's script pattern had existing consensus meaning before BIP11 made it a standard template (and also didn't change any consensus rules).

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.

@delcin-raj Moreover, this PR itself also characterizes P2A by the output type, not the spending witness status.

"description": "Spend a PRE-activation P2A output with a non-empty witness stack (grandfathered, exempt)",

@jonatack jonatack Aug 5, 2026

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.

But the author (dathonohm) is stating here, as written, that bip433 states a p2a must be spent with an empty witness

That is indeed what it says:

"P2A inputs are considered standard by Bitcoin Core for spending if no witness data is attached."

@dathonohm Your statement is not equivalent to the text you've quoted in BIP 433. @john-moffett is correct and proposes a minimum viable clarification on this.


===GetBlockTemplate===

This deployment uses the GBT deployment name "reduced_data" as defined in [[bip-0009.mediawiki#getblocktemplate_changes|BIP 9]]. During mandatory signaling, the deployment's bit is included in "vbrequired".
Expand Down
88 changes: 84 additions & 4 deletions bip-0110/test-vectors.json
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,66 @@
"expected": "valid",
"reject_reason": null
},
{
"rule": 3,
"name": "p2a_empty_witness_valid",
"description": "Spend a P2A output with an empty witness stack",
"reduced_data_active": true,
"spent_utxo": "post-activation",
"spent_outputs": [
{
"prevout": {
"txid": "110000000000000000000000000000000000000000000000000000000000000f",
"vout": 0
},
"scriptPubKey": "51024e73",
"amount": 100000
}
],
"tx": "02000000010f0000000000000000000000000000000000000000000000000000000000001100000000000000000001b882010000000000015100000000",
"expected": "valid",
"reject_reason": null
},
{
"rule": 3,
"name": "p2a_empty_item_invalid",
"description": "Spend a P2A output with one empty witness item (non-empty stack)",
"reduced_data_active": true,
"spent_utxo": "post-activation",
"spent_outputs": [
{
"prevout": {
"txid": "1100000000000000000000000000000000000000000000000000000000000010",
"vout": 0
},
"scriptPubKey": "51024e73",
"amount": 100000
}
],
"tx": "02000000000101100000000000000000000000000000000000000000000000000000000000001100000000000000000001b8820100000000000151010000000000",
"expected": "invalid",
"reject_reason": "script-verify-flag-failed (Witness version reserved for soft-fork upgrades)"
},
{
"rule": 3,
"name": "p2a_one_byte_item_invalid",
"description": "Spend a P2A output with one one-byte witness item",
"reduced_data_active": true,
"spent_utxo": "post-activation",
"spent_outputs": [
{
"prevout": {
"txid": "1100000000000000000000000000000000000000000000000000000000000011",
"vout": 0
},
"scriptPubKey": "51024e73",
"amount": 100000
}
],
"tx": "02000000000101110000000000000000000000000000000000000000000000000000000000001100000000000000000001b882010000000000015101010100000000",
"expected": "invalid",
"reject_reason": "script-verify-flag-failed (Witness version reserved for soft-fork upgrades)"
},
{
"rule": 2,
"name": "grandfathered_witness_item_257_valid",
Expand All @@ -290,14 +350,34 @@
"spent_outputs": [
{
"prevout": {
"txid": "110000000000000000000000000000000000000000000000000000000000000f",
"txid": "1100000000000000000000000000000000000000000000000000000000000012",
"vout": 0
},
"scriptPubKey": "002033198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349",
"amount": 100000
}
],
"tx": "020000000001010f0000000000000000000000000000000000000000000000000000000000001100000000000000000001b882010000000000015102fd0101424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424202755100000000",
"tx": "02000000000101120000000000000000000000000000000000000000000000000000000000001100000000000000000001b882010000000000015102fd0101424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424202755100000000",
"expected": "valid",
"reject_reason": null
},
{
"rule": 3,
"name": "grandfathered_p2a_nonempty_witness_valid",
"description": "Spend a PRE-activation P2A output with a non-empty witness stack (grandfathered, exempt)",
"reduced_data_active": true,
"spent_utxo": "pre-activation",
"spent_outputs": [
{
"prevout": {
"txid": "1100000000000000000000000000000000000000000000000000000000000013",
"vout": 0
},
"scriptPubKey": "51024e73",
"amount": 100000
}
],
"tx": "02000000000101130000000000000000000000000000000000000000000000000000000000001100000000000000000001b882010000000000015101010100000000",
"expected": "valid",
"reject_reason": null
},
Expand All @@ -310,14 +390,14 @@
"spent_outputs": [
{
"prevout": {
"txid": "1100000000000000000000000000000000000000000000000000000000000010",
"txid": "1100000000000000000000000000000000000000000000000000000000000014",
"vout": 0
},
"scriptPubKey": "00204ae81572f06e1b88fd5ced7a1a000945432e83e1551e6f721ee9c00b8cc33260",
"amount": 100000
}
],
"tx": "02000000000101100000000000000000000000000000000000000000000000000000000000001100000000000000000001b88201000000000023510000000000000000000000000000000000000000000000000000000000000000000001015100000000",
"tx": "02000000000101140000000000000000000000000000000000000000000000000000000000001100000000000000000001b88201000000000023510000000000000000000000000000000000000000000000000000000000000000000001015100000000",
"expected": "invalid",
"reject_reason": "bad-txns-vout-script-toolarge"
}
Expand Down
26 changes: 25 additions & 1 deletion bip-0110/test-vectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
Coverage:
Rule 1: output scriptPubKey size (<=34, or OP_RETURN <=83) [per-output]
Rule 2: push / script-argument witness item size (<=256)
Rule 3: spending undefined witness / Tapleaf versions
Rule 3: spending undefined witness / Tapleaf versions (the P2A exemption
covers only spends with an empty witness stack)
Rule 4: Taproot annex
Rule 5: Taproot control block size (<=257)
Rule 6: OP_SUCCESS* in tapscript
Expand Down Expand Up @@ -255,17 +256,20 @@ def run_test(self):
# P2WSH(OP_DROP OP_TRUE) lets us inject an arbitrary witness data element (rule 2)
wsh_drop = CScript([OP_DROP, OP_TRUE])
wsh_drop_spk = script_to_p2wsh_script(wsh_drop)
p2a_spk = CScript([OP_1, bytes.fromhex("4e73")])

# Fund "old" UTXOs BEFORE activation so they are grandfathered (exempt
# from the per-input script rules). Done first, at a low height.
self.log.info("Funding pre-activation (grandfathered) UTXOs...")
old_drop_o, old_drop_a, old_drop_h = self.fund(wsh_drop_spk)
old_true_o, old_true_a, old_true_h = self.fund(wsh_true_spk)
old_p2a_o, old_p2a_a, old_p2a_h = self.fund(p2a_spk)

self.log.info("Activating REDUCED_DATA...")
self.activate()
assert old_drop_h < self.activation_height
assert old_true_h < self.activation_height
assert old_p2a_h < self.activation_height
self.generate(self.wallet, 20) # spendable coins for funding "new" UTXOs

self.log.info("=== Rule 1: output scriptPubKey size (per-output) ===")
Expand Down Expand Up @@ -365,6 +369,21 @@ def run_test(self):
self.check(7, "witness_v0_op_if_valid", "OP_IF in a witness v0 script is valid (rule is tapscript-only)",
[(wsh_if_spk, a)], self.spend(o, a, [bytes(wsh_if)]), True, "post-activation")

# The rule 3 exemption for P2A covers only spends with an empty witness
# stack; any witness item makes the spend invalid (cf. BIP 433).
self.log.info("=== Rule 3: P2A witness stack must be empty ===")
o, a = self.fund(p2a_spk)[0:2]
self.check(3, "p2a_empty_witness_valid", "Spend a P2A output with an empty witness stack",
[(p2a_spk, a)], self.spend(o, a, []), True, "post-activation")
o, a = self.fund(p2a_spk)[0:2]
self.check(3, "p2a_empty_item_invalid",
"Spend a P2A output with one empty witness item (non-empty stack)",
[(p2a_spk, a)], self.spend(o, a, [b'']), False, "post-activation")
o, a = self.fund(p2a_spk)[0:2]
self.check(3, "p2a_one_byte_item_invalid",
"Spend a P2A output with one one-byte witness item",
[(p2a_spk, a)], self.spend(o, a, [b'\x01']), False, "post-activation")

self.log.info("=== Grandfathering: pre-activation UTXOs ===")
# An input spending a pre-activation UTXO is exempt from the per-input
# script rules: a 257-byte witness item is accepted here (cf. rule 2).
Expand All @@ -373,6 +392,11 @@ def run_test(self):
[(wsh_drop_spk, old_drop_a)],
self.spend(old_drop_o, old_drop_a, [b'\x42' * 257, bytes(wsh_drop)]),
True, "pre-activation")
self.check(3, "grandfathered_p2a_nonempty_witness_valid",
"Spend a PRE-activation P2A output with a non-empty witness stack (grandfathered, exempt)",
[(p2a_spk, old_p2a_a)],
self.spend(old_p2a_o, old_p2a_a, [b'\x01']),
True, "pre-activation")
# But the per-output rule 1 still applies even when spending an old UTXO:
# creating an oversized output is rejected regardless of input age.
self.check(1, "grandfathered_input_oversized_output_invalid",
Expand Down