Skip to content

Instantly share code, notes, and snippets.

@t-bast
Created March 13, 2023 16:07
Show Gist options
  • Save t-bast/2594ecf0314f0b91293a3f5e3bf10540 to your computer and use it in GitHub Desktop.
Save t-bast/2594ecf0314f0b91293a3f5e3bf10540 to your computer and use it in GitHub Desktop.
When should we store an `interactive-tx`?

When should we store an interactive-tx?

When using the interactive-tx protocol, we currently store the channel state only after we've sent tx_signatures. This makes sense from a funds safety point of view: the commitment transactions can only be broadcast once we've given our peer the signatures they needed to broadcast the funding transaction first.

But in some cases, this creates an issue where one side has stored the channel state but not the other side. See the following scenario for example (where -->X indicates a message that wasn't received):

  Alice                          Bob
    |                             |
    |        tx_complete          |
    |---------------------------->|
    |        tx_complete          |
    |<----------------------------|
    |        commit_sig           |
    |<----------------------------|
    |        commit_sig           |
    |------------->X              |
    |       tx_signatures         |
    |------------->X              |

Alice has sent tx_signatures and stored the channel state, but Bob didn't receive commit_sig / tx_signatures so Bob threw away the channel when disconnecting.

If this is a dual funding attempt, this is annoying but acceptable:

  • Alice must wait for the funding transaction to be double-spent (or actively double-spend it)
  • Bob can go on without caring about this channel

But if this was a splice attempt, the result isn't acceptable: Alice thinks that there is an ongoing splice while Bob thinks there is none. This will lead to a force-close whenever one side signs an update to the channel (e.g. adds a new HTLC).

This shows that when using interactive-tx for splicing, we must make sure that both sides always agree on whether there is an active splice or not after reconnection, regardless of when the disconnection happened. This will most likely require a reconciliation step when exchanging channel_reestablish.

Since we absolutely need to fix it for splicing, we should take this opportunity to use that fix for dual funding as well and improve the scenario described above.

My suggestion to fix this is:

  1. Store the channel state when sending commit_sig
  2. Re-transmit commit_sig (and tx_signatures) on reconnection
  3. Introduce some additional data to channel_reestablish to figure out when commit_sig needs to be retransmitted (and to what this commit_sig applies)

In most cases, it means that if peers manage to exchange tx_complete without disconnecting, they will be able to complete the channel opening flow even if they disconnect while exchanging signatures. The only case where this isn't true is in the following scenario:

  Alice                          Bob
    |                             |
    |        tx_complete          |
    |<----------------------------|
    |        tx_complete          |
    |------------->X              |
    |        commit_sig           |
    |------------->X              |

In that case Alice stores the channel state (because she sent commit_sig) but Bob doesn't. When reconnecting, Bob will tell Alice he doesn't know this channel (or this splice attempt). Alice can safely forget it as well then, because she hasn't sent tx_signatures (since she hasn't received Bob's commit_sig).

I'd like your feedback on how to design the channel reestablish logic and retransmission of commit_sig (if you agree on the proposed solution to store channel state after sending commit_sig).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment