From rusty at rustcorp.com.au Mon Jul 6 06:41:34 2015 From: rusty at rustcorp.com.au (Rusty Russell) Date: Mon, 06 Jul 2015 16:11:34 +0930 Subject: [Lightning-dev] HTLCs using OP_CHECKSEQUENCEVERIFY/OP_LOCKTIMEVERIFY and revocation hashes. Message-ID: <87fv51eqjl.fsf@rustcorp.com.au> Hi all, To recap: each side maintains a commitment transaction with two outputs: one paying to self (with some delay), and the second paying to the other side. To generate hash time-locked contracts (required for lightning to be a network), both commitment transactions get an additional output. This output is spendable under four conditions: 1) Recipient knows the R value (funds go to recipient), OR 2) The HTLC has timed out (funds return to initiator), OR 3) The HTLC has been revoked (funds to go "non-cheating" side), OR 4) The Commit transaction has been revoked (funds to go "non-cheating" side) The last two failure modes are separate from each other, because HTLCs have different lifetimes from commit transactions. Since we use "revocation preimages" to revoke transactions (rather than sending pubkeys as the original draft paper), the result of this for A's commitment transaction look like this: HTLC from A to B: 1) R value and B's signature, OR 2) HTLC timeout and A's signature[*], OR 3) HTLC revocation preimage and B's signature, OR 4) Commitment transaction revocation preimage and B's signature. HTLC from B to A: 1) R value and A's signature[*], OR 2) HTLC timeout and B's signature, OR 3) HTLC revocation preimate and B's signature, OR 4) Commitment transaction revocation preimage and B's signature. We need to ensure delays in the cases where payment can go to A (marked with [*]) so that B has a chance to steal the funds if the HTLC or commitment tx has been revoked. The result is one of the following scriptPubKey from the commitment tx for the HTLC like so (note: unchecked and unoptimized!): HTLC from US to THEM: --------------------- # They present HTLC's R value, or either revocation hash: OP_DUP OP_HASH160 OP_EQUAL OP_SWAP OP_EQUAL OP_ADD OP_SWAP OP_EQUAL OP_ADD OP_IF # One hash matched, pay to them. OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG OP_ELSE # Must be us, with HTLC timed out. OP_CHECKLOCKTIMEVERIFY OP_DROP OP_CHECKSEQUENCEVERIFY OP_DROP OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG OP_ENDIF HTLC from THEM to US: --------------------- # Revocation cases: OP_DUP OP_HASH160 OP_EQUAL OP_SWAP OP_EQUAL OP_ADD OP_IF # One hash matched, pay to them. OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG OP_ELSE # Us with R value? 3 OP_DEPTH OP_EQUAL OP_IF OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSEQUENCEVERIFY OP_DROP OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG OP_ELSE # Them with timeout. OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG OP_ENDIF OP_ENDIF If you've read this far, congratulations! AFAICT we don't need new SIGOPS here; the logic has all been moved to the commitment transaction output (thanks to OP_CLV and OP_CSV), so each side can generate the HTLC spending transaction with needing a signature from the other. Feedback, fixed and optimizations welcome... Rusty.