Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BIP442: OP_PAIRCOMMIT #1699

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all 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
7 changes: 7 additions & 0 deletions README.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -1295,6 +1295,13 @@ Those proposing changes should consider that ultimately consent may rest with th
| Gloria Zhao
| Informational
| Draft
|-
| [[bip-0442.md|442]]
| Consensus (soft fork)
| OP_PAIRCOMMIT
| moonsettler, Brandon Black
| Standard
| Draft
|}

<!-- IMPORTANT! See the instructions at the top of this page, do NOT JUST add BIPs here! -->
320 changes: 320 additions & 0 deletions bip-0442.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
```
BIP: 442
Layer: Consensus (soft fork)
Title: OP_PAIRCOMMIT
Author: moonsettler <[email protected]>
Brandon Black <[email protected]>
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0442
Status: Draft
Type: Standards Track
Created: 2024-12-09
License: BSD-3-Clause
```

## Abstract

This BIP describes a new tapscript opcode `OP_PAIRCOMMIT`, which
provides limited vector commitment functionality in tapscript.

## Summary

When verifying taproot script spends having leaf version 0xc0 (as defined in
[BIP-342]), we propose `OP_PAIRCOMMIT` to replace `OP_SUCCESS205` (0xcd).

When evaluated, `OP_PAIRCOMMIT`:
* Pops the top two values off the stack,
* takes the "PairCommit" tagged SHA256 hash of the stack elements with size commitments,
* pushes the resulting 32-byte hash to the top of stack.

## Specification

The notation below follows that of [BIP-340]. This includes the
$$hash_{tag}(x)$$ notation to refer to
$$SHA256(SHA256(tag) \\| SHA256(tag) \\| x)$$.

* If fewer than 2 elements are on the stack, the script MUST fail and
terminate immediately.
* The top element ($$x2$$) and second to top element ($$x1$$) are read from the
stack.
* Let $$pc$$ be $$hash_{PairCommit}(
compact\\_size(size\\:of\\:x1) \\| x1 \\|
compact\\_size(size\\:of\\:x2) \\| x2)$$[^1]
* The top two elements are popped from the stack.
* $$pc$$ is pushed to the stack.

[^1]: The number of SHA256 blocks is minimized in typical use cases. Since the
Tag can be pre-computed as a SHA256 mid-state, it takes only 2 hash cycles
for a commitment to 2 32-byte items or 1 for 2 smaller items.

## Motivation

Currently, bitcoin lacks a way to commit to multiple data items together. It
is common practice to hash a single item as part of a bitcoin script. Either
in hash/time locked contracts, or in pay-to-pubkey-hash (P2PKH) scripts, but
there is no way to commit to multiple items with a single hash.
Comment on lines +52 to +54
Copy link
Contributor

Choose a reason for hiding this comment

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

The sentence starting with "Either" seems to be missing one or more words.


With the ability to commit to pairs of elements, `OP_PAIRCOMMIT` can be
generalized to Merklized commitments to a tree of elements with a single hash.
On its own, this could enable a hash lock contract where the holder of any
pre-image in a Merkle tree can unlock the spend, for example.

If `OP_CHECKSIGFROMSTACK` is combined with `OP_PAIRCOMMIT`, the ability to sign
commitments to multiple items enables complex delegation. For example,
delegating to $$key1$$ after time $$t1$$ and $$key2$$ after time $$t2$$.
Without `OP_PAIRCOMMIT` these complex delegations can be achieved using key
laddering[^2], at a much greater validation cost. If the same key is simply
used to sign multiple items, they can be combined arbitrarily, but
`OP_PAIRCOMMIT` or key laddering[^2] enforces any desired relationships between
(both sequence and combination) items.

[^2]: `OP_CHECKSIGFROMSTACK` can commit to a sequence of otherwise
undifferentiated items by requiring a key committed to by the output to
sign an initial laddering key (`key0`) and then having `key0` sign a tuple
of `(item1, key1)` and `key1` signing the tuple `(item2, key2)` etc. There
are some details around ensuring that the items cannot be used as keys
depending on the requirements of the protocol. This is costly both in
bytes and sigops and `OP_PAIRCOMMIT` eliminates the need for such
constructions when committing to any sequence of items. For details, see
the [key laddering post] by Jeremy Rubin and Brandon Black.

## Examples

### Committing to more than 2 elements

`OP_PAIRCOMMIT` can be used to commit to a vector of stack elements in a way
that is not vulnerable to various forms of witness malleability. It is, however,
highly optimized for just 2 stack elements.

```text
# pc-hash = PC(a, PC(b, c))

<a> <b> <c> | PC PC <pc-hash> OP_EQUALVERIFY
```

### Use in Lightning Symmetry
Copy link
Contributor

Choose a reason for hiding this comment

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

I think "LN-Symmetry" is more commonly used to refer to the concept than "Lightning Symmetry". Is there a specific reason why you prefer the latter?


To create Lightning Symmetry contracts that neither require the nodes to keep
old states nor require additional signing round trips (and corresponding
signature validations), we need to solve a data availability problem presented
by contested closes. Specifically, the second to act channel partner must be
able to reconstruct the script that spends the first update transaction
published. This script includes the hash of the corresponding settlement
Comment on lines +99 to +101
Copy link
Contributor

@murchandamus murchandamus Feb 10, 2025

Choose a reason for hiding this comment

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

Maybe this is easier to parse:

Suggested change
by contested closes. Specifically, the second to act channel partner must be
able to reconstruct the script that spends the first update transaction
published. This script includes the hash of the corresponding settlement
by contested closes. Specifically, either channel partner must be
able to spend the output of any prior update transaction.
Those input scripts include the hash of the corresponding settlement

transaction which we do not wish to store for all prior states. By having the
channel and update state scripts force the parties to include the settlement
transaction's hash in the witness to in order to publish the corresponding
update transaction, then a later update can use the settlement hash from the
Copy link
Contributor

Choose a reason for hiding this comment

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

I’m stumbling over this "in the witness to in order". Could you please revisit this sentence?

first update transaction's witness to recreate the corresponding spend script.

The following assembly-like pseudo-code shows a possible Lightning Symmetry
channel construction that ensures sufficient data is available on chain in a
force close to reconstruct the corresponding script and update it with a later
state while only knowing the later state.[^3] The opcodes `OP_CHECKTEMPLATEVERIFY`,
`OP_PAIRCOMMIT`, `OP_INTERNALKEY`, and `OP_CHECKSIGFROMSTACK` are abbreviated
as `CTV`, `PC`, `IK`, and `CSFS` respectively.

[^3]: Concretely 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.

```text
# S = 500000000
# internal key = [BIP-327] aggregate key of channel participants
# channel script:
<sig> <state-n-recovery-data> <state-n-hash> | CTV PC IK CSFS <S+1> CLTV DROP
```

Before funding, sign the first state.

```text
# 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 }
# update script:
IF
<sig> <state-m-recovery-data> <state-m-hash> | CTV PC IK CSFS <S+n+1> CLTV DROP
ELSE
<settlement-n-hash> CTV
ENDIF
```

These scripts ensure the necessary data availability as follows: `CTV` commits
to the update transaction's hash, `PC` combines this hash with the next stack
item, and `CSFS` checks a MuSig 2-party signature against the resulting pair
hash. Both parties must sign the same pair hash to produce a channel update,
and they can therefore require each other to include both the update hash and
settlement hash in the witness stack when initiating a force close. This
Lightning Symmetry channel construction is close to [optimal].

### In MATT

The Merklize All The Things ([MATT]) framework proposes to use `OP_CAT` to
combine multiple items into a single commitment for use with
`OP_CHECKCONTRACTVERIFY`. `OP_PAIRCOMMIT` provides a more ergonomic way to
accomplish this[^4].

[^4]: `OP_CAT` can be used to commit to multiple items, but it is subject to
byte shifting attacks if used naively.
E.g. `0x0102 || 0x03` equals `0x01 || 0x0203`. Mitigating this correctly
requires either length checking, hashing, or both.

## Alternative approaches

The following list of alternative approaches were discussed and rejected for
various reasons, either for expanding the scope or for unnecessary complexity:

* `OP_CAT`[^4][^7]
* SHA256 streaming opcodes[^7]
* Merkle operation opcodes
* 'Kitty' CAT: `OP_CAT` with result or inputs arbitrarily limited in size
* `OP_CHECKTEMPLATEVERIFY` committing to the taproot annex in tapscript[^5]
* `OP_CHECKSIGFROMSTACK` on n elements as message
* `OP_VECTORCOMMIT`: generalized form for n > 2 elements
* ReKey/Laddering[^2]
* `OP_RETURN`[^6]

[^5]: As seen in Greg Sanders' [Lightning Symmetry write-up], one additional
item can be committed to by a transaction signature by placing that item
in the Taproot annex. This mechanism is limited to a single additional
item and that item is not made accessible to script making it less useful.
[^6]: `OP_RETURN` can also be used to cause a transaction signature or CTV
hash to commit to additional data items. This is both costly for the user,
as this inexpensive to validate data is pushed into transaction data
instead of witness data and not accessible to script making it less useful
like the annex.
[^7]: `OP_PAIRCOMMIT` is intended to enable more useful bitcoin scripts, in
some cases similar to those enabled by `OP_CAT` but without also enabling
unexpected script behaviors such as those described by Andrew Poelstra in
[CAT-tricks-I] and [CAT-tricks-II] or larger numeric operations.

## 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();
}
```

### PR

https://github.com/lnhance/bitcoin/pull/6/files

## Rationale

### Cost comparison of Lightning Symmetry constructions

The following table briefly summarizes the costs associated with force closing
Lightning Symmetry channels enabled by various combinations of proposed script
upgrades.

| Method | ChannelSc | UpdateSc | UpdateW | ForceC | Contest | Settle |
| :--------------- | --------: | -------: | ------: | ------: | ------: | :----: |
| 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 | CTV |
| CTV+CSFS+IKEY | 10 WU | 48 WU | 98 WU | 1328 WU | 732 WU | CTV |
| CTV+CSFS+IKEY+PC | 11 WU | 49 WU | 131 WU | 1191 WU | 594 WU | CTV |

*ChannelSc: channel script, UpdateSc: update script, UpdateW: witness is the
same size for both Force Close and Contest in Lightning Symmetry, ForceC: total
cost of unilateral close transactions, Contest: The additional cost to contest
a force closure, Settle: Whether a signature operation or CTV operation is
required to validate the settlement transaction*
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for expanding on the column titles. As I wrote above, it would be good to provide more context for this table. It would especially help if the compared schemata were at least briefly described and/or sources for details were provided.


### Proving general computation using trees

One potential risk of PAIRCOMMIT is that it may enable verification of general
computations on bitcoin.

Any script change which enables commitment to pairs of items necessarily
enables commitments to Merkle trees.

Merkle trees can be used to prove computation where the root of the tree
represents the *function* and the leaves represent the *inputs* and *output*.
There are practical limits to the total number of discrete output values that
can be reached by all possible input values (i.e. the input entropy space) as
they must be enumerated and hashed into a Merkle root.

Taproot trees can be 128 levels deep, therefore including up to 2^128 possible
output values. This is over the practical limits to enumerate and merklize.
Therefore, we conclude that enabling Merkle commitments in script does not
materially extend what computations are possible to validate in bitcoin
script. While `OP_PAIRCOMMIT` is not explicitly limited to a height of 128, greater
heights are not practical to Merklize.

## Backward Compatibility

By constraining the behavior of `OP_SUCCESS` opcodes, deployment of the BIP
can be done in a backwards-compatible, soft-fork manner. If anyone were to
rely on the `OP_SUCCESS` behavior of `OP_SUCCESS205`, `OP_PAIRCOMMIT` would
invalidate their spend.

## 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_INTERNALKEY: [BIP-349], [BIN-2024-0004]
7. Tagged hash: [BIP-340]

[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-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
[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