[Lightning-dev] Reconciling the off-chain and on-chain models with eltoo

With the recently published proof-of-concept of eltoo on signet by Richard, I thought it might a good time to share some thoughts on ho I think we can build this system. I think there are a few properties of eltoo that allow us to build a nicely layered protocol stack, which improves flexibility and simplifies the reasoning about their relative security. Since I don't like huge e-mails myself and I'm about to write one, here's a quick TL;DR: > Using the clean separation of protocol layers provided by eltoo we can > reconcile many on-chain and off-chain concepts, and simplify the > reasoning to build more complex functionality beyond simple > HTLCs. Bitcoin transactions are a natural fit to represent proposed > off-chain state-changes while they are being negotiated. ### Clean separation of protocol layers One of te big advantages of eltoo over other off-chain update mechanisms is that it provides strong guarantees regarding the state that will eventually end up confirmed on-chain. If parties in an eltoo off-chain contract agree on an update, we can be certain (within eltoo's security assumptions) that this is the state that will eventually confirm on-chain, if no newer states are agreed. In particular it means that we are guaranteed no earlier state can leak onto the chain, keeping anything we build on top of the update layer unencumbered since it doesn't have to deal with this case. This is in stark contrast to the penalty update mechanism, where old/revoked states can leak on-chain, resulting in anything built on top of the penalty mechanism having to deal with that eventuality. For example if we look at HTLCs as specified [1] we see that it needs an additional revokation path for the case the commitment transaction that created this HTLC output is confirmed: ```btcscript # To remote node with revocation key OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL OP_IF OP_CHECKSIG OP_ELSE <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL OP_IF # To local node via HTLC-success transaction. OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG OP_ELSE # To remote node after timeout. OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_CHECKSIG OP_ENDIF OP_ENDIF ``` The update mechanism bleeding into the other layers is rather cumbersome if you ask me, and complicates the reasoning about security. Having to thread the penalty through outputs created by the off-chain contract may also not work if we deal with more than 2 parties, since penalties always steal all the funds, regardless of whether the output belonged to the cheater or not (see asymmetry vs symmetry argument from the paper [2]). With the clean separation we get from eltoo we can concentrate on building the output scripts we'd like to have without having to thread penalties through them. This reduces the complexity and our on-chain footprint. The update layer now exposes only two very simple operations: `add_output` and `remove_output` (this should sound very familiar :-p). ### Ownership and atomic update model Now that we have a solid update layer, which ensures that agreed upon states will eventually be reflected on-chain, we can turn our attention to the next layer up: the negotiation layer. Each output in our agreed-upon state needs to be assigned one or more owners. The owners are the participants that need to sign off on removal of an output and the creation of new outputs which redistribute the funds contained in the removed outputs to newly created outputs. In addition we need to ensure that multiple `remove_output` and `add_output` are guaranteed to be applied atomically. By creating a datastructure that lists a number of operations that are to either be applied to the current state or discarded, we can have arbitrary complex changes of ownership, and the newly created outputs can have arbitrary scripts. If all of this sounds familiar that's because this is exactly the UTXO model and the transaction structure we have in Bitcoin. We collaboratively manage funds bound to some outputs (UTXO) and can change their ownership and allocation over time (transactions). This means that a subset of the participants in an off-chain contract can negotiate among themselves how to redistribute funds, join and split them in an arbitrary fashion, without the rest of the contract being involved. The end result is a valid Bitcoin transaction that spends some outputs of the current state, and is signed by the owners. The transaction can then be presented to the entire group, and applied to the state. Applying the transaction flattens multiple transactions built on top of the current state into a new state (similar to transaction cut-through in mimblewimble). Using transactions as a means to represent off-chain negotiations, and then applying them to the off-chain state via cut-through has a number of advantages over similar schemes: - Even if we failed to update the off-chain state, the transactions building on top of it are valid transactions, so once we tear down the channel, our negotiated new state can still be reached by broadcasting the transaction after settlement (this is basically what the channel factory paper [3] was using). - We can reuse a lot of tools that we have already built for on-chain transactions, including things like miniscript and hardware wallets, without explicitly requiring them in our own specification. The Bitcoin object model is our interface here. - It allows for experimentation even inside a running eltoo instance. If you can find another participant that supports a fancy new protocol, you can use that protocol even though some of the other participants may not know anything about it. As long as you can understand the Bitcoin transaction model you can participate in a multi-party channel. I think this reconciliation between the off-chain model and the on-chain model, with many concepts cleanly mapping from one context to another (state outputs = UTXO, off-chain update = on-chain transactions, cut-through = confirmation, operation batching = block creation) is rather nice :-) That should be enough rambling on my side. I'm interested in what others think about this. Is it completely off, does it make no sense at all, or is this something we should be looking into going forward? Cheers, Christian [1] https://github.com/lightningnetwork/lightning-rfc/blob/master/03-transactions.md#received-htlc-outputs [2] https://blockstream.com/eltoo.pdf [3] https://tik-old.ee.ethz.ch/file/a20a865ce40d40c8f942cf206a7cba96/Scalable%5FFunding%5FOf%5FBlockchain%5FMicropayment%5FNetworks.pdf