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

Reply via email to