peer: always send channel update on reconnect
We have existing logic to attempt to reliably send a channel update to the remote peer. In the wild, we've seen this fail, as it's possible right when we send the update the peer disconnects. In this commit, we implement a simple fix which is just to send the chan update each time we connect to the remote party. Fixes https://github.com/lightningnetwork/lnd/issues/6870.
This commit is contained in:
4 files changed
+131
-2
No files matched your search
@@ -787,7 +787,9 @@ func (p *Brontide) Start() error {
|
||||
//
|
||||
// TODO(wilmer): Remove this once we're able to query for node
|
||||
// announcements through their timestamps.
|
||||
p.wg.Add(2)
|
||||
go p.maybeSendNodeAnn(activeChans)
|
||||
go p.maybeSendChannelUpdates()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1218,6 +1220,8 @@ func (p *Brontide) addLink(chanPoint *wire.OutPoint,
|
||||
// maybeSendNodeAnn sends our node announcement to the remote peer if at least
|
||||
// one confirmed public channel exists with them.
|
||||
func (p *Brontide) maybeSendNodeAnn(channels []*channeldb.OpenChannel) {
|
||||
defer p.wg.Done()
|
||||
|
||||
hasConfirmedPublicChan := false
|
||||
for _, channel := range channels {
|
||||
if channel.IsPending {
|
||||
@@ -1245,6 +1249,72 @@ func (p *Brontide) maybeSendNodeAnn(channels []*channeldb.OpenChannel) {
|
||||
}
|
||||
}
|
||||
|
||||
// maybeSendChannelUpdates sends our channel updates to the remote peer if we
|
||||
// have any active channels with them.
|
||||
func (p *Brontide) maybeSendChannelUpdates() {
|
||||
defer p.wg.Done()
|
||||
|
||||
// If we don't have any active channels, then we can exit early.
|
||||
if p.activeChannels.Len() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
maybeSendUpd := func(cid lnwire.ChannelID,
|
||||
lnChan *lnwallet.LightningChannel) error {
|
||||
|
||||
// Nil channels are pending, so we'll skip them.
|
||||
if lnChan == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
dbChan := lnChan.State()
|
||||
scid := func() lnwire.ShortChannelID {
|
||||
switch {
|
||||
// Otherwise if it's a zero conf channel and confirmed,
|
||||
// then we need to use the "real" scid.
|
||||
case dbChan.IsZeroConf() && dbChan.ZeroConfConfirmed():
|
||||
return dbChan.ZeroConfRealScid()
|
||||
|
||||
// Otherwise, we can use the normal scid.
|
||||
default:
|
||||
return dbChan.ShortChanID()
|
||||
}
|
||||
}()
|
||||
|
||||
// Now that we know the channel is in a good state, we'll try
|
||||
// to fetch the update to send to the remote peer. If the
|
||||
// channel is pending, and not a zero conf channel, we'll get
|
||||
// an error here which we'll ignore.
|
||||
chanUpd, err := p.cfg.FetchLastChanUpdate(scid)
|
||||
if err != nil {
|
||||
p.log.Debugf("Unable to fetch channel update for "+
|
||||
"ChannelPoint(%v), scid=%v: %v",
|
||||
dbChan.FundingOutpoint, dbChan.ShortChanID, err)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
p.log.Debugf("Sending channel update for ChannelPoint(%v), "+
|
||||
"scid=%v", dbChan.FundingOutpoint, dbChan.ShortChanID)
|
||||
|
||||
// We'll send it as a normal message instead of using the lazy
|
||||
// queue to prioritize transmission of the fresh update.
|
||||
if err := p.SendMessage(false, chanUpd); err != nil {
|
||||
err := fmt.Errorf("unable to send channel update for "+
|
||||
"ChannelPoint(%v), scid=%v: %w",
|
||||
dbChan.FundingOutpoint, dbChan.ShortChanID(),
|
||||
err)
|
||||
p.log.Errorf(err.Error())
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
p.activeChannels.ForEach(maybeSendUpd)
|
||||
}
|
||||
|
||||
// WaitForDisconnect waits until the peer has disconnected. A peer may be
|
||||
// disconnected if the local or remote side terminates the connection, or an
|
||||
// irrecoverable protocol error has been encountered. This method will only
|
||||
|
||||
Reference in new issue
Block a user