From 994d9cf7e4d26dbe2f398e9bd6f68047fad21b5e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Fri, 27 Apr 2018 16:31:15 -0700 Subject: [PATCH] discovery: attempt to request the full chan ann for stray chan updates In this commit, we extend the AuthenticatedGossiper to take advantage of the new query features in the case that it gets a channel update w/o first receiving the full channel announcement. If this happens, we'll attempt to find a syncer that's fully synced, and request the channel announcement from it. --- discovery/gossiper.go | 51 ++++++++++++++++++++++++++++++++++++++++++- discovery/syncer.go | 3 ++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 8db315906..f2ccd1991 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -1873,12 +1873,28 @@ func (d *AuthenticatedGossiper) processNetworkAnnouncement(nMsg *networkMsg) []n d.pChanUpdMtx.Lock() d.prematureChannelUpdates[shortChanID] = append( d.prematureChannelUpdates[shortChanID], - nMsg) + nMsg, + ) d.pChanUpdMtx.Unlock() + log.Debugf("Got ChannelUpdate for edge not "+ "found in graph(shortChanID=%v), "+ "saving for reprocessing later", shortChanID) + + // If the node supports it, we may try to + // request the chan ann from it. + go func() { + reqErr := d.maybeRequestChanAnn( + msg.ShortChannelID, + ) + if reqErr != nil { + log.Errorf("unable to request ann "+ + "for chan_id=%v: %v", shortChanID, + reqErr) + } + }() + nMsg.err <- nil return nil default: @@ -2445,3 +2461,36 @@ func (d *AuthenticatedGossiper) updateChannel(info *channeldb.ChannelEdgeInfo, return chanAnn, chanUpdate, err } + +// maybeRequestChanAnn will attempt to request the full channel announcement +// for a particular short chan ID. We do this in the case that we get a channel +// update, yet don't already have a channel announcement for it. +func (d *AuthenticatedGossiper) maybeRequestChanAnn(cid lnwire.ShortChannelID) error { + d.syncerMtx.Lock() + defer d.syncerMtx.Unlock() + + for nodeID, syncer := range d.peerSyncers { + // If this syncer is already at the terminal state, then we'll + // chose it to request the fully channel update. + if syncer.SyncState() == chansSynced { + pub, err := btcec.ParsePubKey(nodeID[:], btcec.S256()) + if err != nil { + return err + } + + log.Debugf("attempting to request chan ann for "+ + "chan_id=%v from node=%x", cid, nodeID[:]) + + return d.cfg.SendToPeer(pub, &lnwire.QueryShortChanIDs{ + ChainHash: d.cfg.ChainHash, + EncodingType: lnwire.EncodingSortedPlain, + ShortChanIDs: []lnwire.ShortChannelID{cid}, + }) + } + } + + log.Debugf("unable to find peer to request chan ann for chan_id=%v "+ + "from", cid) + + return nil +} diff --git a/discovery/syncer.go b/discovery/syncer.go index 1b441786b..85e356bca 100644 --- a/discovery/syncer.go +++ b/discovery/syncer.go @@ -256,7 +256,8 @@ func (g *gossipSyncer) channelGraphSyncer() { for { state := atomic.LoadUint32(&g.state) - log.Debugf("gossipSyncer(%x): state=%v", g.peerPub[:], state) + log.Debugf("gossipSyncer(%x): state=%v", g.peerPub[:], + syncerState(state)) switch syncerState(state) { // When we're in this state, we're trying to synchronize our