bip360: depth-zero script trees should be anyone-can-spend (#2198)
Some checks are pending
GitHub Actions Check / Link-Format-Checks (push) Waiting to run
GitHub Actions Check / Build-Table-Checks (push) Waiting to run
GitHub Actions Check / Diff Checks (fails until number assignment) (push) Waiting to run
GitHub Actions Check / Typo Checks (push) Waiting to run
Some checks are pending
GitHub Actions Check / Link-Format-Checks (push) Waiting to run
GitHub Actions Check / Build-Table-Checks (push) Waiting to run
GitHub Actions Check / Diff Checks (fails until number assignment) (push) Waiting to run
GitHub Actions Check / Typo Checks (push) Waiting to run
* bip360: depth zero trees should be anyone-can-spend * bip360: update changelog and bump version to 0.12.0
This commit is contained in:
parent
40cd7b4dd6
commit
6740c533e8
@ -9,7 +9,7 @@
|
|||||||
Type: Specification
|
Type: Specification
|
||||||
Assigned: 2024-12-18
|
Assigned: 2024-12-18
|
||||||
License: BSD-3-Clause
|
License: BSD-3-Clause
|
||||||
Version: 0.11.0
|
Version: 0.12.0
|
||||||
Requires: 340, 341, 342
|
Requires: 340, 341, 342
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -152,11 +152,13 @@ That is, they place elements on the stack to be evaluated by the leaf script.
|
|||||||
|
|
||||||
The control block is a ''1 + 32 * m'' byte array, where the first byte is the control byte and the next ''32 * m'' bytes are the Merkle path to the leaf script. The control byte is the same as the control byte in a P2TR control block, including the 7 bits which are used to specify the leaf version. The parity bit of the control byte is always 1, since P2MR does not have a key path spend. Unlike P2TR, we omit the public key from the control block as it is not needed in P2MR. We maintain support for the optional annex in the witness (see Specification section below for more details).
|
The control block is a ''1 + 32 * m'' byte array, where the first byte is the control byte and the next ''32 * m'' bytes are the Merkle path to the leaf script. The control byte is the same as the control byte in a P2TR control block, including the 7 bits which are used to specify the leaf version. The parity bit of the control byte is always 1, since P2MR does not have a key path spend. Unlike P2TR, we omit the public key from the control block as it is not needed in P2MR. We maintain support for the optional annex in the witness (see Specification section below for more details).
|
||||||
|
|
||||||
|
Unlike P2TR, script trees of depth 0 - those with a single leaf script - are considered anyone-can-spend in P2MR, which discourages the use of depth-zero script trees today while still allowing them to be repurposed in a future soft-fork.
|
||||||
|
|
||||||
==Rationale==
|
==Rationale==
|
||||||
|
|
||||||
Design of the P2MR output type is guided by the following intentions:
|
Design of the P2MR output type is guided by the following intentions:
|
||||||
|
|
||||||
1. Minimize changes to the network. We should reuse existing Bitcoin code and preserve existing software behavior, workflows, user expectations and compatibility whenever possible.
|
1. Minimize changes to the network. We should reuse existing Bitcoin code and preserve existing software behavior, workflows, user expectations, incentives, and compatibility whenever possible.
|
||||||
|
|
||||||
P2MR leverages the battle tested P2TR, tapleaf and tapscript code already in Bitcoin, reducing the implementation burden on wallets, exchanges, and libraries that can reuse code they already have. This approach reduces complexity and minimizes implementation risks.
|
P2MR leverages the battle tested P2TR, tapleaf and tapscript code already in Bitcoin, reducing the implementation burden on wallets, exchanges, and libraries that can reuse code they already have. This approach reduces complexity and minimizes implementation risks.
|
||||||
|
|
||||||
@ -166,6 +168,8 @@ Importantly, we are proposing a script tree output, i.e. an output type that sup
|
|||||||
|
|
||||||
P2WSH, for instance, does not support tapscript and as such does not support the OP_SUCCESSx opcode update path that will be critical for the integration of post-quantum OP_CHECKSIG opcodes into Bitcoin.<ref><code>OP_SUCCESSx</code> is a mechanism to upgrade tapscript</ref>
|
P2WSH, for instance, does not support tapscript and as such does not support the OP_SUCCESSx opcode update path that will be critical for the integration of post-quantum OP_CHECKSIG opcodes into Bitcoin.<ref><code>OP_SUCCESSx</code> is a mechanism to upgrade tapscript</ref>
|
||||||
|
|
||||||
|
P2MR encourages script trees of depth 1 or more, so that P2MR addresses contain at least two spending paths, even if one is not used. This is intended to incentivize the use of a post-quantum-secure leaf script once available, and to better align P2MR's privacy profile with P2TR.
|
||||||
|
|
||||||
3. Facilitate gradual integration of quantum resistant features that can be carried out iteratively as quantum computers evolve. This approach encourages responsiveness to the current threat-level, while avoiding heavy-handedness in our reactions to a potential threat.
|
3. Facilitate gradual integration of quantum resistant features that can be carried out iteratively as quantum computers evolve. This approach encourages responsiveness to the current threat-level, while avoiding heavy-handedness in our reactions to a potential threat.
|
||||||
|
|
||||||
We designed P2MR with an eye towards integrating post-quantum signatures in the future, without proposing more complex changes while CRQCs are still in their infancy.
|
We designed P2MR with an eye towards integrating post-quantum signatures in the future, without proposing more complex changes while CRQCs are still in their infancy.
|
||||||
@ -174,11 +178,22 @@ We designed P2MR with an eye towards integrating post-quantum signatures in the
|
|||||||
|
|
||||||
While P2TR outputs (and the use of key path spend) will remain an option for folks wishing to use them, we aim to be clear about the tradeoffs of using P2MR outputs, which disable the key path spend for the benefit of quantum resistance.
|
While P2TR outputs (and the use of key path spend) will remain an option for folks wishing to use them, we aim to be clear about the tradeoffs of using P2MR outputs, which disable the key path spend for the benefit of quantum resistance.
|
||||||
|
|
||||||
The witness to a P2MR spend is always larger than the witness to a P2TR key path spend. This is because a P2TR key path spend requires only a Schnorr signature in the witness. For P2MR, the witness must include the chosen leaf script, the initial stack, and a control block consisting of the control byte and Merkle path (if any).
|
The witness to a P2MR spend is always larger than the witness to a P2TR key path spend. This is because a P2TR key path spend requires only a Schnorr signature in the witness. For P2MR, the witness must include the chosen leaf script, the initial stack, and a control block consisting of the control byte and Merkle path.
|
||||||
|
|
||||||
That said, the witness to a P2MR spend will always be smaller than the witness to an equivalent P2TR script path spend, because there is no longer any internal key in P2MR that must be revealed in the control block. For a more complete comparison of output type transaction sizes, the "Transaction Size and Fees" section may be reviewed later in this proposal.
|
That said, the witness to a P2MR spend will always be smaller than the witness to an equivalent P2TR script path spend, because there is no longer any internal key in P2MR that must be revealed in the control block. For a more complete comparison of output type transaction sizes, the "Transaction Size and Fees" section may be reviewed later in this proposal.
|
||||||
|
|
||||||
Additionally, there is a privacy tradeoff when comparing P2MR and P2TR, which is that users reveal they are spending to a script tree whenever they are using P2MR outputs, since P2MR outputs can only be spent via script path spend. In P2TR when you spend an output as a key path spend, you don't reveal if you have any script path spends. This trade-off only exists when comparing P2TR key path spends to P2MR script path spends; P2TR and P2MR provide the same level of privacy when both are script path spends.
|
P2MR and P2TR share a nearly equivalent privacy profile with respect to the information leaked by spending.
|
||||||
|
|
||||||
|
* A P2MR address has at least two spending paths, defined by script leaves.
|
||||||
|
** Spending any leaf script reveals a lower bound on the total number of valid leaf scripts available. E.g. spending a depth-1 leaf reveals there is at least one valid spending path: the sibling node may be disabled or it may contain thousands of child script leaves.
|
||||||
|
** Leaf scripts below depth-1 are unlikely to be disabled, so revealing a depth ''d > 0'' leaf script implies there are likely at least ''d+1'' leaf scripts available in total.
|
||||||
|
* A P2TR address has at least two spending paths: one defined by key-spending and the rest defined by script leaves.
|
||||||
|
** Spending the key path reveals P2TR's key path is usable. The script path may be disabled.
|
||||||
|
** Spending the script path reveals P2TR's script path is usable. The key path spend may be disabled. Spending any leaf script reveals a lower bound on the total number of leaf scripts available. E.g. spending a depth-1 leaf reveals there are likely at least two leaf scripts. In general, revealing a depth ''d'' leaf script implies there are likely at least ''d+1'' leaf scripts available in total.
|
||||||
|
|
||||||
|
In both P2MR and P2TR, the only way for an observer to put a reasonable upper bound on the potential number of spending paths is to learn every leaf script, or in P2TR if the observer learns the script path is disabled through external means.
|
||||||
|
|
||||||
|
The only major difference is that in P2TR, a sender can reveal and enforce a script at depth zero to spend, while in P2MR depth-zero trees are discouraged because they are anyone-can-spend.
|
||||||
|
|
||||||
'''Note:''' P2MR and P2TR both provide greater script privacy than P2SH [[bip-0016.mediawiki|BIP 16]] because unused script paths are not revealed.
|
'''Note:''' P2MR and P2TR both provide greater script privacy than P2SH [[bip-0016.mediawiki|BIP 16]] because unused script paths are not revealed.
|
||||||
|
|
||||||
@ -234,6 +249,7 @@ A P2MR output is a native SegWit output (see [[bip-0141.mediawiki|BIP 141]]) wit
|
|||||||
**** If ''k<sub>j</sub> ≥ e<sub>j</sub>'': ''k<sub>j+1</sub> = hash<sub>TapBranch</sub>(e<sub>j</sub> || k<sub>j</sub>)''.
|
**** If ''k<sub>j</sub> ≥ e<sub>j</sub>'': ''k<sub>j+1</sub> = hash<sub>TapBranch</sub>(e<sub>j</sub> || k<sub>j</sub>)''.
|
||||||
** Let ''r = k<sub>m</sub>''.
|
** Let ''r = k<sub>m</sub>''.
|
||||||
** If ''q ≠ r'', fail.
|
** If ''q ≠ r'', fail.
|
||||||
|
** If ''m = 0'', succeed immediately.
|
||||||
** Execute the script, according to the script rules specified in BIP 342, using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. This implies that for the future leaf versions (non-''0xC0'') the execution must succeed.
|
** Execute the script, according to the script rules specified in BIP 342, using the witness stack elements excluding the script ''s'', the control block ''c'', and the annex ''a'' if present, as initial stack. This implies that for the future leaf versions (non-''0xC0'') the execution must succeed.
|
||||||
|
|
||||||
The steps above follow the script path spend logic from [[bip-0341.mediawiki|BIP 341]] with the following changes:
|
The steps above follow the script path spend logic from [[bip-0341.mediawiki|BIP 341]] with the following changes:
|
||||||
@ -241,6 +257,7 @@ The steps above follow the script path spend logic from [[bip-0341.mediawiki|BIP
|
|||||||
* The witness program is the the Merkle root of the script tree and not a tweaked public key. This means that we skip directly to the BIP 341 script path validation.
|
* The witness program is the the Merkle root of the script tree and not a tweaked public key. This means that we skip directly to the BIP 341 script path validation.
|
||||||
* We compute the script tree Merkle root ''r'' and compare it directly to the witness program ''q''.
|
* We compute the script tree Merkle root ''r'' and compare it directly to the witness program ''q''.
|
||||||
* The control block is ''1 + 32*m'' bytes, instead of ''33 + 32*m'' bytes.
|
* The control block is ''1 + 32*m'' bytes, instead of ''33 + 32*m'' bytes.
|
||||||
|
* If the leaf script is at depth zero, script execution is skipped and validation automatically succeeds.
|
||||||
|
|
||||||
===Common Signature Message Construction===
|
===Common Signature Message Construction===
|
||||||
|
|
||||||
@ -256,15 +273,15 @@ All P2MR and P2TR outputs are always the same size. P2MR inputs can be slightly
|
|||||||
|
|
||||||
====Comparison with P2TR key path spend====
|
====Comparison with P2TR key path spend====
|
||||||
|
|
||||||
A P2MR witness will be larger than a P2TR witness when the P2TR output is spent via the key path spend. A witness to a P2TR key path spend is simply a signature. P2MR quantum resistance comes from removing the P2TR key path spend. Every P2MR spend is a P2TR script path spend and so requires a script, its input stack and a control block. Consequently, P2MR loses this size advantage of P2TR key path spends in order to gain quantum resistance. If the script tree only has a single leaf script, no Merkle path is needed in the control block, giving us a minimal size control block of 1 byte.
|
A P2MR witness will be larger than a P2TR witness when the P2TR output is spent via the key path spend. A witness to a P2TR key path spend is simply a signature. P2MR quantum resistance comes from removing the P2TR key path spend. Every P2MR spend is a P2TR script path spend and so requires a script, its input stack and a control block. Consequently, P2MR loses this size advantage of P2TR key path spends in order to gain quantum resistance.
|
||||||
|
|
||||||
P2MR witness for depth-0 tree (103 bytes):
|
P2MR witness for a depth-1 tree (135 bytes):
|
||||||
|
|
||||||
<source>
|
<source>
|
||||||
[count] (1 byte), # Number of elements in the witness
|
[count] (1 byte), # Number of elements in the witness
|
||||||
[size] signature (1 + 64 bytes = 65 bytes),
|
[size] signature (1 + 64 bytes = 65 bytes),
|
||||||
leaf script = [size] [OP_PUSHBYTES_32, 32-byte public key, OP_CHECKSIG] (1 + 1 + 32 + 1 bytes = 35 bytes),
|
leaf script = [size] [OP_PUSHBYTES_32, 32-byte public key, OP_CHECKSIG] (1 + 1 + 32 + 1 bytes = 35 bytes),
|
||||||
control block = [size] [control byte] [merkle path (empty)] (1 + 1 + 0 bytes = 2 bytes)
|
control block = [size] [control byte] [merkle path (empty)] (1 + 1 + 32 bytes = 34 bytes)
|
||||||
</source>
|
</source>
|
||||||
|
|
||||||
P2TR key path spend witness (66 bytes):
|
P2TR key path spend witness (66 bytes):
|
||||||
@ -274,13 +291,12 @@ P2TR key path spend witness (66 bytes):
|
|||||||
[size] signature (1 + 64 bytes = 65 bytes)
|
[size] signature (1 + 64 bytes = 65 bytes)
|
||||||
</source>
|
</source>
|
||||||
|
|
||||||
Thus, the P2MR witness would be 103 - 66 = 37 bytes larger than a P2TR key path spend witness.
|
Thus, the P2MR witness would be 135 - 66 = 69 bytes larger than a P2TR key path spend witness.
|
||||||
|
|
||||||
If the Merkle tree has more than a single leaf, then the Merkle path must be included in the control block, increasing the size by ''32 * m'' bytes, where m is the depth of the Merkle tree.
|
The P2MR Merkle path must be included in the control block, increasing the size by ''32 * m'' bytes, where m is the depth of the leaf script.
|
||||||
While script trees do support leaf scripts of different depths, here we assume the Merkle tree has been constructed such that each leaf is at the same depth.
|
|
||||||
This would make such witness 37 + 32 * m bytes larger than a P2TR key path spend witness.<ref>If ''m >= 8'', then the compact size will use 3 bytes rather than 1 byte</ref>
|
This would make such witness 37 + 32 * m bytes larger than a P2TR key path spend witness.<ref>If ''m >= 8'', then the compact size will use 3 bytes rather than 1 byte</ref>
|
||||||
|
|
||||||
P2MR witness ''(103 + 32*m bytes)'':
|
P2MR witness, general case ''(103 + 32*m bytes)'':
|
||||||
|
|
||||||
<source>
|
<source>
|
||||||
[count] (1 byte), # Number of elements in the witness
|
[count] (1 byte), # Number of elements in the witness
|
||||||
@ -299,7 +315,7 @@ P2MR is slightly more computationally performant than P2TR script path spends, a
|
|||||||
|
|
||||||
==Backward Compatibility==
|
==Backward Compatibility==
|
||||||
|
|
||||||
Older wallets and nodes that have not been made compatible with SegWit version 2 and P2MR will not understand these outputs. Per [[bip-0350.mediawiki|BIP 350]] older wallets should be able to spend funds to SegWit version 2 outputs. Users should ensure they are using updated wallets and nodes to receive P2MR outputs and validate transactions using P2MR outputs. P2MR is fully compatible with tapscript and existing tapscript programs can be used in P2MR outputs without modification. P2MR can also support future scripts with new leaf versions.
|
Older wallets and nodes that have not been made compatible with SegWit version 2 and P2MR will not understand these outputs. Per [[bip-0350.mediawiki|BIP 350]] older wallets should be able to spend funds to SegWit version 2 outputs. Users should ensure they are using updated wallets and nodes to receive P2MR outputs and validate transactions using P2MR outputs. P2MR is fully compatible with tapscript and existing tapscript programs can be used in P2MR outputs mostly without modification (but depth-zero script trees will be anyone-can-spend in P2MR!). P2MR can also support future script upgrades with new leaf versions.
|
||||||
|
|
||||||
==Security==
|
==Security==
|
||||||
|
|
||||||
@ -399,6 +415,7 @@ A script tree output type, similar to to Pay-to-Taproot (P2TR), but with the qua
|
|||||||
|
|
||||||
To help implementers understand updates to this BIP, we keep a list of substantial changes.
|
To help implementers understand updates to this BIP, we keep a list of substantial changes.
|
||||||
|
|
||||||
|
* __0.12.0__ (2026-06-18) - Make depth-zero script trees anyone-can-spend.
|
||||||
* __0.11.0__ (2026-02-10) - Rename BIP from Pay-to-Tapscript-Hash (P2TSH) to Pay-to-Merkle-Root (P2MR)
|
* __0.11.0__ (2026-02-10) - Rename BIP from Pay-to-Tapscript-Hash (P2TSH) to Pay-to-Merkle-Root (P2MR)
|
||||||
* __0.10.3__ (2026-02-06) - Rename tapscript-native output type to script tree output type.
|
* __0.10.3__ (2026-02-06) - Rename tapscript-native output type to script tree output type.
|
||||||
* __0.10.2__ (2026-01-23) - Fix bug in verification, minor review comments and adopt [[bip-0003.md|BIP 3]] conventions.
|
* __0.10.2__ (2026-01-23) - Fix bug in verification, minor review comments and adopt [[bip-0003.md|BIP 3]] conventions.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user