1
0
mirror of https://github.com/bitcoin/bips.git synced 2026-03-09 15:53:54 +00:00

BIP442: OP_PAIRCOMMIT (#1699)

* Add: PAIRCOMMIT

* New revision with Brandon Black

* Fix: Authors and spelling merklize

* Fix: header

* Rework based on feedback from PR 1699

commit ae69991b77830021c34e31d1a65ac6987e2ca1ba
Author: moonsettler <moonsettler@protonmail.com>
Date:   Tue Sep 23 02:23:43 2025 +0200

    Update references

commit 6adcb4e559cd2b67553fa57d193474906c138721
Author: moonsettler <moonsettler@protonmail.com>
Date:   Tue Sep 23 02:15:14 2025 +0200

    General computation simplify wording

commit 2f911cb4ab4b938697e39cb34974fa6fc12bf3b2
Author: moonsettler <moonsettler@protonmail.com>
Date:   Tue Sep 23 01:36:41 2025 +0200

    Rework based on feedback from PR 1699

* More readeable scripts & fix footnotes

* Format and readability improvements

* Update general computation section

* THIKCS cost compare

* Reference BIP-446

* Standard -> Specification

Co-authored-by: Mark "Murch" Erhardt <murch@murch.one>

* Update header to BIP-3 compatible

Co-authored-by: Mark "Murch" Erhardt <murch@murch.one>

* Add: Post-History

* Update Cost comparison table

* Post-History -> Discussion

Co-authored-by: Mark "Murch" Erhardt <murch@murch.one>
This commit is contained in:
moonsettler
2026-03-03 20:38:26 +01:00
committed by GitHub
parent 6eb7cb38fb
commit f61d4b8ba3
2 changed files with 258 additions and 0 deletions

View File

@@ -1402,6 +1402,13 @@ users (see also: [https://en.bitcoin.it/wiki/Economic_majority economic majority
| Specification
| Draft
|-
| [[bip-0442.md|442]]
| Consensus (soft fork)
| OP_PAIRCOMMIT
| moonsettler, Brandon Black
| Specification
| Draft
|-
| [[bip-0443.mediawiki|443]]
| Consensus (soft fork)
| OP_CHECKCONTRACTVERIFY

251
bip-0442.md Normal file
View File

@@ -0,0 +1,251 @@
```
BIP: 442
Layer: Consensus (soft fork)
Title: OP_PAIRCOMMIT
Authors: moonsettler <moonsettler@protonmail.com>
Brandon Black <freedom@reardencode.com>
Status: Draft
Type: Specification
Assigned: 2024-12-09
License: BSD-3-Clause
Discussion: https://delvingbitcoin.org/t/op-paircommit-as-a-candidate-for-addition-to-lnhance/1216
https://groups.google.com/g/bitcoindev/c/si6ZNIkVfOw/m/29VY_YRrCgAJ
```
## Abstract
This BIP proposes a new tapscript opcode, `OP_PAIRCOMMIT`, which enables efficient and secure commitment to pairs of stack elements using a tagged hash construction. This opcode provides limited vector commitment functionality, facilitating more expressive contracts and improved data availability in Bitcoin scripts.
## Summary
For taproot script spends with leaf version *0xc0* (see [BIP-342]), `OP_PAIRCOMMIT` replaces `OP_SUCCESS205` (*0xcd*). When executed, `OP_PAIRCOMMIT` pops the top two stack elements, computes a *PairCommit* tagged SHA256 hash over their compact size and data, and pushes the resulting 32-byte hash onto the stack.
## Specification
Notation follows [BIP-340], including the tagged hash notation:
*hash<sub>tag</sub>(x) = SHA256(SHA256(tag) || SHA256(tag) || x)*
Stack operation:
- If fewer than 2 elements are present, script execution fails.
- Let the stack be *[..., x1, x2]* (top is rightmost).
- Compute: `pc` = *hash<sub>PairCommit</sub>(compact_size(len(x1)) || x1 || compact_size(len(x2)) || x2)*[^1]
- Pop `x2` and `x1` from the stack.
- Push `pc` onto the stack.
[^1]: The number of SHA256 blocks is minimized in typical use cases. The tag can be precomputed as a SHA256 mid-state, requiring only two hash cycles for two 32-byte items, or one for two smaller items.
## Motivation
Bitcoin scripts often commit to single data items (e.g., hash/time locks, P2PKH), but lack native support for committing to multiple items together. `OP_PAIRCOMMIT` enables Merklized commitments, allowing contracts to commit to trees of elements with a single hash. This supports use cases such as hash lock contracts where any pre-image in a Merkle tree can unlock a spend.
Combined with `OP_CHECKSIGFROMSTACK`, signing commitments to multiple items enables complex delegation (e.g., delegating to `key1` after time `t1` and `key2` after time `t2`). Previously, such delegation required key laddering[^2], which is more costly in validation. `OP_PAIRCOMMIT` enforces relationships between items efficiently.
[^2]: Key laddering involves a sequence of keys signing tuples of items and keys, which is costly in bytes and sigops. See [key laddering post] for details.
## Examples
### Committing to more than 2 elements
`OP_PAIRCOMMIT` can commit to a vector of stack elements securely and efficiently.
```perl
# Commit to three elements: a, b, c
# pc-hash = PC(a, PC(b, c))
# Witness: <a> <b> <c>
OP_PAIRCOMMIT # <a>, PC(b, c)
OP_PAIRCOMMIT # PC(a, PC(b, c))
<pc-hash> # PC(a, PC(b, c)), <pc-hash>
OP_EQUALVERIFY #
# ...
```
### Use in Lightning Symmetry
Lightning Symmetry contracts require data availability for contested closes. [^3] By forcing parties to include settlement transaction hashes in the witness, later updates can reconstruct scripts of intermediate states while only keeping the latest state.
[^3]: The required data is a full CTV hash of the settlement transaction when there are open HTLCs, or merely the difference in balance between the channel partners in other cases. Whether the latter optimization would be used is an implementation detail not further discussed here.
```perl
# S: 500000000
# internal-key: BIP-327 aggregate key of channel participants
# state-n-hash: { nLockTime(S+n), out(contract, amount(A)+amount(B)) }
# settlement-n-hash: { nSequence(2w), out(A, amount(A)), out(B, amount(B)) }
# state-n-recovery-data: { settlement-n-hash or state-n-balance }
```
#### Example channel script (pseudo-code)
```perl
# Witness: <sig> <state-n-recovery-data> <state-n-hash>
OP_CHECKTEMPLATEVERIFY # <sig>, <state-n-recovery-data>, <state-n-hash>
OP_PAIRCOMMIT # <sig>, PC(state-n-recovery-data, state-n-hash)
OP_INTERNALKEY # <sig>, PC(state-n-recovery-data, state-n-hash), <internal-key>
OP_CHECKSIGFROMSTACK # <1>
<S+1> # <1>, <S+1>
OP_CHECKLOCKTIMEVERIFY # <1>, <S+1>
OP_DROP # <1>
```
#### Channel update script (pseudo-code) for m > n
```perl
OP_IF
# Witness: <sig> <state-m-recovery-data> <state-m-hash>
OP_CHECKTEMPLATEVERIFY # <sig>, <state-m-recovery-data>, <state-m-hash>
OP_PAIRCOMMIT # <sig>, PC(state-m-recovery-data, state-m-hash)
OP_INTERNALKEY # <sig>, PC(state-m-recovery-data, state-m-hash), <internal-key>
OP_CHECKSIGFROMSTACK # <1>
<S+n+1> # <1>, <S+n+1>
OP_CHECKLOCKTIMEVERIFY # <1>, <S+n+1>
OP_DROP # <1>
OP_ELSE
# Empty witness stack
<settlement-n-hash> # <settlement-n-hash>
OP_CHECKTEMPLATEVERIFY # <settlement-n-hash>
OP_0NOTEQUAL # <1>
OP_ENDIF
```
These constructions ensure both parties sign the same pair hash, requiring inclusion of both update and settlement hashes in the witness. [^4] [^5]
[^4]: `state-n-hash` commits to a specific `nLockTime` value for the transaction through `OP_CHECKTEMPLATEVERIFY`; `OP_CHECKLOCKTIMEVERIFY` ensures that the state progression can only go forward (the transaction needs to have greater `nLockTime` value than the intermediate state
[^5]: `OP_0NOTEQUAL` can be omitted (any non-zero value left on the stack would be accepted by the script interpreter).
### In MATT
The Merklize All The Things ([MATT]) framework uses `OP_CAT` to combine items for commitments. `OP_PAIRCOMMIT` provides a more ergonomic and secure alternative[^6].
[^6]: Naive use of `OP_CAT` is vulnerable to byte shifting attacks. E.g. *0x0102 || 0x03* equals *0x01 || 0x0203*. Mitigation requires length checking or hashing.
## Alternative approaches
Alternative approaches considered and rejected:
- `OP_CAT`[^6][^9]
- SHA256 streaming opcodes[^9]
- Merkle operation opcodes
- 'Kitty' CAT: `OP_CAT` with size limits
- `OP_CHECKTEMPLATEVERIFY` committing to the taproot annex[^7]
- `OP_CHECKSIGFROMSTACK` on n elements
- `OP_VECTORCOMMIT`: generalized for n > 2 elements
- ReKey/Laddering[^2]
- `OP_RETURN`[^8]
[^7]: Committing to the taproot annex allows one additional item, but it is not accessible to script.
[^8]: `OP_RETURN` can commit to additional data, but is costly and not accessible to script.
[^9]: `OP_PAIRCOMMIT` enables useful scripts without the risks of `OP_CAT` (see [CAT-tricks-I], [CAT-tricks-II]).
## Reference Implementation
### Code
```c++
case OP_PAIRCOMMIT: {
// OP_PAIRCOMMIT is only available in Tapscript
// ...
// x1 x2 -- hash
if (stack.size() < 2) {
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
}
const valtype& vch1 = stacktop(-2);
const valtype& vch2 = stacktop(-1);
uint256 hash = PairCommitHash(vch1, vch2);
stack.pop_back();
stack.pop_back();
stack.emplace_back(hash.begin(), hash.end());
break;
}
```
```c++
const HashWriter HASHER_PAIRCOMMIT{TaggedHash("PairCommit")};
uint256 PairCommitHash(const std::vector<unsigned char>& x1, const std::vector<unsigned char>& x2)
{
return (HashWriter{HASHER_PAIRCOMMIT} << x1 << x2).GetSHA256();
}
```
### Pull Request
https://github.com/lnhance/bitcoin/pull/6/files
## Rationale
### Cost comparison of Lightning Symmetry constructions
| Method | Channel Script | Update Script | Update Witness<sup>1</sup> | Force Close<sup>2</sup> | Contest | Settlement Mechanism |
|:----------------------|---------------:|--------------:|---------------------------:|------------------------:|--------:|:--------------------:|
| APO-Annex | 8 WU | 113 WU | 100 WU | 1221 WU | 627 WU| SigOp |
| APO-Return | 8 WU | 113 WU | 66 WU | 1359 WU | 765 WU| SigOp |
| CTV+CSFS | 43 WU | 81 WU | 98 WU | 1394 WU | 765 WU| HashEq |
| CTV+CSFS+IKEY | 10 WU | 48 WU | 98 WU | 1328 WU | 732 WU| HashEq |
| CTV+CSFS+IKEY+PC | 11 WU | 49 WU | 131 WU | 1191 WU | 594 WU| HashEq |
| THIKCS-Annex | 10 WU | 49 WU | 98 WU | 1160 WU | 563 WU| HashEq |
| THIKCS-Return | 10 WU | 49 WU | 66 WU | 1329 WU | 733 WU| HashEq |
<sup>1</sup> *Witness is the same weight for both Force Close and Contest in LN-Symmetry* \
<sup>2</sup> *Total cost of unilateral close transactions* \
<sup>3</sup> *THIKCS is short for TEMPLATEHASH+IKEY+CSFS*
### Proving general computation using trees
`OP_PAIRCOMMIT` enables Merkle tree commitments, which can represent functions where inputs and corresponding outputs are the leaves. Taproot trees can be 128 levels deep, therefore including up to 2<sup>128</sup> possible leaf scripts that can represent complex functions. This is already over the practical computational limits to enumerate and Merklize.
## Backward Compatibility
Constraining `OP_SUCCESS` opcodes allows deployment as a backwards-compatible soft fork. Reliance on `OP_SUCCESS205` behavior will be invalidated by `OP_PAIRCOMMIT`.
## Deployment
TBD
## Credits
Jeremy Rubin, Salvatore Ingala, Anthony Towns, Ademan555, Psifour
## Copyright
This document is licensed under the 3-clause BSD license.
## References
1. LNhance bitcoin repository: [lnhance]
2. Lightning Symmetry: [eltoo]
3. OP_CAT: [BIP-347], [BIN-2024-0001]
4. OP_CHECKTEMPLATEVERIFY: [BIP-119]
5. OP_CHECKSIGFROMSTACK: [BIP-348], [BIN-2024-0003]
6. OP_CHECKCONTRACTVERIFY: [BIP-443]
7. OP_INTERNALKEY: [BIP-349], [BIN-2024-0004]
8. OP_TEMPLATEHASH: [BIP-446]
9. Tagged hash: [BIP-340]
10. MuSig2: [BIP-327]
[lnhance]: https://github.com/lnhance/bitcoin
[eltoo]: https://github.com/instagibbs/bolts/blob/eltoo_draft/XX-eltoo-transactions.md
[CAT-tricks-I]: https://medium.com/blockstream/cat-and-schnorr-tricks-i-faf1b59bd298
[CAT-tricks-II]: https://medium.com/blockstream/cat-and-schnorr-tricks-ii-2f6ede3d7bb5
[MATT]: https://merkle.fun
[Lightning Symmetry write-up]: https://delvingbitcoin.org/t/ln-symmetry-project-recap/359
[key laddering post]: https://rubin.io/bitcoin/2024/12/02/csfs-ctv-rekey-symmetry/
[//]: # (BIPs referenced)
[BIP-119]: https://github.com/bitcoin/bips/tree/master/bip-0119.mediawiki
[BIP-327]: https://github.com/bitcoin/bips/blob/master/bip-0327.mediawiki
[BIP-340]: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
[BIP-341]: https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki
[BIP-342]: https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki
[BIP-347]: https://github.com/bitcoin/bips/blob/master/bip-0347.mediawiki
[BIP-348]: https://github.com/bitcoin/bips/blob/master/bip-0348.md
[BIP-349]: https://github.com/bitcoin/bips/blob/master/bip-0349.md
[BIP-443]: https://github.com/bitcoin/bips/blob/master/bip-0443.mediawiki
[BIP-446]: https://github.com/instagibbs/bips/blob/bip_op_templatehash/bip-0446.md
[BIN-2024-0001]: https://github.com/bitcoin-inquisition/binana/blob/master/2024/BIN-2024-0001.md
[BIN-2024-0003]: https://github.com/bitcoin-inquisition/binana/blob/master/2024/BIN-2024-0003.md
[BIN-2024-0004]: https://github.com/bitcoin-inquisition/binana/blob/master/2024/BIN-2024-0004.md
[//]: # (Internal links)
[optimal]: #cost-comparison-of-ln-symmetry-constructions