From f3f7f91d261433c315ee153a09b4388160ef13e1 Mon Sep 17 00:00:00 2001 From: moonsettler Date: Wed, 13 Nov 2024 22:34:58 +0100 Subject: [PATCH] Add: PAIRCOMMIT --- bip-PC.md | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 bip-PC.md diff --git a/bip-PC.md b/bip-PC.md new file mode 100644 index 0000000000..c0182afe70 --- /dev/null +++ b/bip-PC.md @@ -0,0 +1,162 @@ +``` +BIP: ? +Layer: Consensus (soft fork) +Title: OP_PAIRCOMMIT +Author: moonsettler +Comments-Summary: No comments yet. +Comments-URI: +Status: Draft +Type: Standards Track +Created: 2024-11-08 +License: BSD-3-CLAUSE +``` + +## 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