diff --git a/2024/BIN-2024-0006.md b/2024/BIN-2024-0006.md new file mode 100644 index 0000000..7f5a514 --- /dev/null +++ b/2024/BIN-2024-0006.md @@ -0,0 +1,161 @@ +| BIN-2024-006 | `OP_PAIRCOMMIT` +| :------------ | :------- +| Revision | 006 (2024-11-08) +| Author | moonsettler `` +| | +| Layer | Consensus (soft fork) +| Status | Draft +| License | BSD-3-CLAUSE +| | +| Discussion | [https://delvingbitcoin.org/t/op-paircommit-as-a-candidate-for-addition-to-lnhance/1216/12] +| Aliases | [BIPs PR#????](https://github.com/bitcoin/bips/pull/?) + +## Abstract + +This BIP describes a new tapscript opcode `OP_PAIRCOMMIT` which +provide limited vector commitment functionality in tapscript. + +When evaluated, the `OP_PAIRCOMMIT` instruction: +* Pops the top two values off the stack, +* takes the "PairCommit" tagged SHA256 hash of the stack elements, +* pushes the resulting commitment on the top of the stack. + +## Motivation + +To do LN-Symmetry contracts that don't require the nodes to keep old states, +we need to solve the data availability problem presented by unilateral closes. +Channel peers must be able to reconstruct the script that spends an +intermediate state. + +Using in sequence `OP_CHECKTEMPLATEVERIFY`, `OP_PAIRCOMMIT`, `OP_INTERNALKEY` +and `OP_CHECKSIGFROMSTACK` we can construct a rebindable channel that is also +optimal. + +If `OP_CAT` was available, it could be used to combine multiple stack elements, +that get verified with `OP_CHECKSIGFROMSTACK` as a valid state update. + +`OP_PAIRCOMMIT` solves this specific problem without introducing a wide range +of potentially controversial new behaviors, such as novel 2-way peg mechanisms. + +The number of SHA256 iterations is minimized in the primary use case we +can optimize for, which is LN-Symmetry. Since the Tag can be pre-computed as +mid-state, it would only take 1 or 2 hash cycles in validation for the +unilateral close scenario. + +## Specification + +Repurpose opcode 205 (currently `OP_SUCCESS`) as follows: + +`OP_PAIRCOMMIT` pops two elements off the stack, then concatenates them along +with their size commitments and takes the tagged SHA256 hash of that +concatenated string, then pushes the resulting hash back on the stack. + +Given the stack `[x1, x2]`, where `x2` is at the top of the stack: + +`OP_PAIRCOMMIT` will push `SHA256(tagPC|cs(x1)|x1|cs(x2)|x2)` onto the stack. + +Where `|` denotes concatenation and `tagPC` is calculated according to BIP-340 +tagged hash as `SHA256("PairCommit")|SHA256("PairCommit")` and `cs(x)` means +`CompactSize(x)`. + +### Implementation + +```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); + + popstack(stack); + popstack(stack); + stack.emplace_back(hash.begin(), hash.end()); + break; +} +``` +```c++ +const HashWriter HASHER_PAIRCOMMIT{TaggedHash("PairCommit")}; + +uint256 PairCommitHash(const std::vector& x1, const std::vector& x2) +{ + return (HashWriter{HASHER_PAIRCOMMIT} << x1 << x2).GetSHA256(); +} +``` +### Use in script + +`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)) + + | PC PC OP_EQUALVERIFY +``` + +### Use in LN-Symmetry + +The following assembly-like pseudo-code shows a possible LN-Symmetry channel +construction, that provides data availability to spend to the latest state from +an earlier state pushed on-chain with a forced close by channel partner. + + +```text +# S = 500000000 +# IK -> A+B + | CTV PC IK CSFS CLTV DROP +``` +before funding sign first state template: +```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 } + +# contract for state n < m +IF + | CTV PC IK CSFS CLTV DROP +ELSE + CTV +ENDIF +``` + +## Reference Implementation + +A reference implementation is provided here: + +[https://github.com/lnhance/bitcoin/pull/6/files] + +## 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, Brandon Black, Salvatore Ingala, Anthony Towns + +## Copyright + +This document is licensed under the 3-clause BSD license. + +## References + +1. LNhance bitcoin repository ["LNhance"](https://github.com/lnhance/bitcoin) +2. LN-Symmetry ["eltoo"](https://github.com/instagibbs/bolts/blob/eltoo_draft/XX-eltoo-transactions.md) +3. OP_CAT, ["BIN-2024-0001"](https://github.com/bitcoin-inquisition/binana/blob/master/2024/BIN-2024-0001.md) +4. OP_CHECKTEMPLATEVERIFY, ["BIP 119"](https://github.com/bitcoin/bips/tree/master/bip-0119) +5. OP_CHECKSIGFROMSTACK, ["BIN-2024-0003"](https://github.com/bitcoin-inquisition/binana/blob/master/2024/BIN-2024-0003.md) +6. OP_INTERNALKEY, ["BIN-2024-0004"](https://github.com/bitcoin-inquisition/binana/blob/master/2024/BIN-2024-0004.md) +7. Tagged hash, ["BIP-340"](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki) \ No newline at end of file diff --git a/README.md b/README.md index 72682fe..1cc827b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ may be identified by appending ".RRR", the three digit revision number. | BIN-2024-0003 | Draft | [`CHECKSIGFROMSTACK`](2024/BIN-2024-0003.md) | BIN-2024-0004 | Draft | [`OP_INTERNALKEY`](2024/BIN-2024-0004.md) | BIN-2024-0005 | Info | [Bitcoin Related Specifications](2024/BIN-2024-0005.md) +| BIN-2024-0006 | Draft | [`OP_PAIRCOMMIT`](2024/BIN-2024-0006.md) ## Notes