From bastien at acinq.fr Fri Mar 31 09:04:24 2023 From: bastien at acinq.fr (Bastien TEINTURIER) Date: Fri, 31 Mar 2023 11:04:24 +0200 Subject: [Lightning-dev] Proposed changes to the splicing specification Message-ID: Good morning list, As some of you may know, we've been hard at work experimenting with splicing [1]. Splicing is a complex feature with a large design space. It was interesting to iterate on two separate implementations (eclair and cln) and discover the pain points, edge cases and things that could be improved in the protocol specification. After a few months trying out different approaches, we'd like to share changes that we believe make the splicing protocol simpler and more robust. We call "active commitments" the set of valid commitment transactions to which updates must be applied. While one (or more) splices are ongoing, there is more than one active commitment. When signing updates, we send one `commitment_signed` message per active commitment. We send those messages in the order in which the corresponding funding transactions have been created, which lets the receiver implicitly match every `commitment_signed` to their respective funding transaction. Once we've negotiated a new splice and reached the signing steps of the interactive-tx protocol, we send a single `commitment_signed` for that new commitment. We don't revoke the previous commitment(s), as this adds an unnecessary step. Conceptually, we're simply adding a new commitment to our active commitments set. A sample flow will look like this: Alice Bob | stfu | |----------------------------->| | stfu | |<-----------------------------| | splice_init | |----------------------------->| | splice_ack | |<-----------------------------| | | | | |<---------------------------->| | | | tx_complete | |----------------------------->| | tx_complete | |<-----------------------------| | commit_sig | Sign the new commitment. |----------------------------->| | commit_sig | Sign the new commitment. |<-----------------------------| | tx_signatures | |----------------------------->| | tx_signatures | |<-----------------------------| | | | update_add_htlc | Alice and Bob use the channel while the splice transaction is unconfirmed. |----------------------------->| | update_add_htlc | |----------------------------->| | commit_sig | Sign the old commitment. |----------------------------->| | commit_sig | Sign the new commitment. |----------------------------->| | revoke_and_ack | |<-----------------------------| | commit_sig | Sign the old commitment. |<-----------------------------| | commit_sig | Sign the new commitment. |<-----------------------------| | revoke_and_ack | |----------------------------->| | | | splice_locked | The splice transaction confirms. |----------------------------->| | splice_locked | |<-----------------------------| | | | update_add_htlc | Alice and Bob can use the channel and forget the old commitment. |----------------------------->| | commit_sig | Sign the new commitment. |----------------------------->| | revoke_and_ack | |<-----------------------------| | commit_sig | Sign the new commitment. |<-----------------------------| | revoke_and_ack | |----------------------------->| | | You can find many more details and sample flows in [2]. We require nodes to store data about the funding transaction as soon as they send their `commitment_signed` message. This lets us handle every disconnection scenario safely, allowing us to either resume the signing steps on reconnection or forget the funding attempt. This is important because if peers disagree on the set of active commitments, this will lead to a force-close. In order to achieve that, we only need to add the `next_funding_txid` to the `channel_reestablish` message, and fill it when we're missing signatures from our peer. Again, you can find more details and sample flows in [2]. Finally, after trying various approaches, we believe that the funding amounts that peer exchange in `splice_init` and `splice_ack` should be relative amounts based on each peer's current channel balance. If Alice sends `funding_amount = 200_000 sats`, it means she will be adding 200 000 sats to the channel's capacity (splice-in). If she sends `funding_amount = -50_000 sats`, it means she will be removing 50 000 sats from the channel's capacity (splice-out). This makes it easier to compute the new channel balances (otherwise we have to deal with millisatoshi to satoshi truncation) and better matches the UX that node operators are expecting, which means there is less need to glue code between the RPC exposed to the node operator and the actual underlying protocol. We've also discovered that implementing 0-conf splicing is tricky: you need to be very careful about scenarios where your peer force-closes using an *inactive* commitment that ends up double-spending what you think is the only *active* commitment but is unconfirmed. We'd be happy to discuss that in more details with other implementers to reduce the risk of introducing new vulnerabilities when shipping that feature. Cheers, Bastien [1] https://github.com/lightning/bolts/pull/863 [2] https://gist.github.com/t-bast/1ac31f4e27734a10c5b9847d06db8d86 -------------- next part -------------- An HTML attachment was scrubbed... URL: