Hi Bastien, Thanks for the update on the state of splicing.
> 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. I think halting 0-conf splicing is pretty easy for a counterparty by abusing Bitcoin Core mempool replacement rule #5 on the maximum number of original transactions replaced. Let's say you have Alice with 10% of the channel capacity as a balance in the "inactive" commitment and the 90% remaining in favor of Bob. Bob has initiated a splice out of 70% of the channel capacity. On the interactive transaction, Alice adds 4 unrelated confirmed inputs and then broadcasts 4 chains of 25 unconfirmed transactions from those inputs. When Bob broadcasts the splice-out, it should be rejected by the network mempools on the grounds of RBF rule #5, whatever the absolute fee and feerate. So the "0-conf" splicing might be maintained under risk of double-spend by your counterparty for a while. It sounds like Bob's splice out funds should be segregated until the corresponding "active commitment" is confirmed, i.e no use to fund another channel, with inbound/outbound HTLC flows. Best, Antoine Le lun. 3 avr. 2023 à 00:25, Bastien TEINTURIER <bast...@acinq.fr> a écrit : > 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 | > |<-----------------------------| > | | > | <interactive-tx> | > |<---------------------------->| > | | > | 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 > _______________________________________________ > Lightning-dev mailing list > Lightning-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev >
_______________________________________________ Lightning-dev mailing list Lightning-dev@lists.linuxfoundation.org https://lists.linuxfoundation.org/mailman/listinfo/lightning-dev