lnd icon indicating copy to clipboard operation
lnd copied to clipboard

[feature]: Make sure LND re-sends AnnouncementSignature after disconnect.

Open ziggie1984 opened this issue 7 months ago • 3 comments

Make sure LND always re-sends the AnnouncmentSignature in case the Peer disconnects before receiving it the first time.

@t-bast not sure if I understood the requirement correctly, when can we assume that the peer received the Signature ? Can we assume it at one point ?

came up in https://github.com/lightning/bolts/issues/1258

ziggie1984 avatar May 20 '25 17:05 ziggie1984

What we do right now is:

  • We'll write the ann sig to disk before we send it.
  • Each time the peer connections, we'll continue to always send it.
  • Once we receive theirs, and construct the final chan ann, we'll mark it as stale
  • If an announcement is stale when we reconnect to them, we'll delete it and no longer send it.
  • This relies on the remote party getting out chan ann either directly from us, or from the network (if they never got ours)

IIUC the suggested change here is:

  • Once per connection, if the remote party sends ann sig, then you should as well.

With our current logic, once we have constructed the chan ann and broadcasted it, we won't send it again. We still need some final trigger to stop sending it though (unless we don't care if we just continue to spam it to them until the channel is closed).

Roasbeef avatar May 20 '25 18:05 Roasbeef

Thanks for looking into it! Right now with your current implementation, there will be an issue in the following case:

  • eclair sends announcement_signatures to lnd
  • lnd receives that announcement_signatures
  • lnd sends announcement_signatures
  • a disconnection happens and eclair doesn't receive it
  • on reconnection, eclair will re-send its announcement_signatures to lnd, hoping to receive lnd's signatures in response
  • but lnd won't send it back

IMO the implementation logic should be:

  • if you receive the remote announcement_signatures before generating yours, just keep it in RAM. If a disconnection happens before you're ready to send your own announcement_signatures, you can dismiss it, your peer will retransmit it on reconnection, so no need to persist it to disk.
  • when you send announcement_signatures to your peer:
    • no need to persist it to disk, you can re-create it on-demand (and for taproot you will need to, because a previous announcement will use an old set of nonces that will be obsolete on reconnection)
    • if you have already received your peer's announcement_signatures, you can create the channel_announcement and store it to disk
  • when you reconnect:
    • if you don't have a channel_announcement on disk, that means you haven't exchanged announcement_signatures yet: you must thus re-send announcement_signatures after channel_reestablish (if the transaction has reached min depth, otherwise of course you keep waiting for confirmations)
    • if you have a channel_announcement on disk, that means you already sent and received announcement_signatures: no need to re-send announcement_signatures after channel_reestablish. But your peer may not have received your announcement_signatures: if you receive announcement_signatures, that means they hadn't received it, and you must respond by re-creating your announcement_signatures.
    • just be careful about not entering the infinite loop described here: you should only send announcement_signatures once per connection

You can only assume that your peer received your announcement_signatures when they don't re-send theirs on reconnection. So you should always be ready to re-create your announcement_signatures (once per connection) if your peer requests it. Does that make sense?

t-bast avatar May 21 '25 08:05 t-bast

In @t-bast scenario lnd has a full proof after the third step: lnd sends announcement_signatures

The way I interpret the current implementation in lnd is that in that specific case, upon receiving a remote announcement_signatures, we will always send a channel announcement.

https://github.com/lightningnetwork/lnd/blob/35102e7c35c7923e27d937d10ba51757edd9ec6e/discovery/gossiper.go#L3487-L3520

The staleness of the message doesn't come into play, [^1] because we only use the reliableSender for sending the announcement_signatures in response to a local signature announcement. In @t-bast 's scenario this happens at the third step and lnd is assumed to have successfully sent the local signature announcement but the eclair somehow didn't receive it. Then in step 5, eclair sends us a remote signature announcement to which we reply with a channel announcement.

Funnily enough that keeps us from falling into the infinite loop issue, but it isn't according to spec. The best approach is to send the signature announcement only once instead of always sending the channel announcement.

[^1]: Even if it did come into play, it wouldn't matter because we always send a message once regardless of it being stale. https://github.com/gijswijs/lnd/blob/9ceb6ec22725e7e226b3c403f6aa96411684e4d7/discovery/reliable_sender.go#L262-L267

gijswijs avatar Jun 12 '25 14:06 gijswijs