diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 845bce46..5d3d9968 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -343,16 +343,18 @@ func New(cfg Config, selfKey *btcec.PublicKey) *AuthenticatedGossiper { channelMtx: multimutex.NewMutex(), recentRejects: make(map[uint64]struct{}), heightForLastChanUpdate: make(map[uint64][2]uint32), - syncMgr: newSyncManager(&SyncManagerCfg{ - ChainHash: cfg.ChainHash, - ChanSeries: cfg.ChanSeries, - RotateTicker: cfg.RotateTicker, - HistoricalSyncTicker: cfg.HistoricalSyncTicker, - NumActiveSyncers: cfg.NumActiveSyncers, - IgnoreHistoricalFilters: cfg.IgnoreHistoricalFilters, - }), } + gossiper.syncMgr = newSyncManager(&SyncManagerCfg{ + ChainHash: cfg.ChainHash, + ChanSeries: cfg.ChanSeries, + RotateTicker: cfg.RotateTicker, + HistoricalSyncTicker: cfg.HistoricalSyncTicker, + NumActiveSyncers: cfg.NumActiveSyncers, + IgnoreHistoricalFilters: cfg.IgnoreHistoricalFilters, + BestHeight: gossiper.latestHeight, + }) + gossiper.reliableSender = newReliableSender(&reliableSenderCfg{ NotifyWhenOnline: cfg.NotifyWhenOnline, NotifyWhenOffline: cfg.NotifyWhenOffline, @@ -2644,3 +2646,10 @@ func IsKeepAliveUpdate(update *lnwire.ChannelUpdate, } return true } + +// latestHeight returns the gossiper's latest height known of the chain. +func (d *AuthenticatedGossiper) latestHeight() uint32 { + d.Lock() + defer d.Unlock() + return d.bestHeight +} diff --git a/discovery/sync_manager.go b/discovery/sync_manager.go index daebcc35..d81a905e 100644 --- a/discovery/sync_manager.go +++ b/discovery/sync_manager.go @@ -89,6 +89,9 @@ type SyncManagerCfg struct { // This prevents ranges with old start times from causing us to dump the // graph on connect. IgnoreHistoricalFilters bool + + // BestHeight returns the latest height known of the chain. + BestHeight func() uint32 } // SyncManager is a subsystem of the gossiper that manages the gossip syncers @@ -419,7 +422,10 @@ func (m *SyncManager) createGossipSyncer(peer lnpeer.Peer) *GossipSyncer { sendToPeerSync: func(msgs ...lnwire.Message) error { return peer.SendMessageLazy(true, msgs...) }, - ignoreHistoricalFilters: m.cfg.IgnoreHistoricalFilters, + ignoreHistoricalFilters: m.cfg.IgnoreHistoricalFilters, + maxUndelayedQueryReplies: DefaultMaxUndelayedQueryReplies, + delayedQueryReplyInterval: DefaultDelayedQueryReplyInterval, + bestHeight: m.cfg.BestHeight, }) // Gossip syncers are initialized by default in a PassiveSync type diff --git a/discovery/sync_manager_test.go b/discovery/sync_manager_test.go index c7a228f8..d3c0ba46 100644 --- a/discovery/sync_manager_test.go +++ b/discovery/sync_manager_test.go @@ -2,7 +2,6 @@ package discovery import ( "fmt" - "math" "reflect" "sync/atomic" "testing" @@ -34,6 +33,9 @@ func newTestSyncManager(numActiveSyncers int) *SyncManager { RotateTicker: ticker.NewForce(DefaultSyncerRotationInterval), HistoricalSyncTicker: ticker.NewForce(DefaultHistoricalSyncInterval), NumActiveSyncers: numActiveSyncers, + BestHeight: func() uint32 { + return latestKnownHeight + }, }) } @@ -202,7 +204,7 @@ func TestSyncManagerInitialHistoricalSync(t *testing.T) { syncMgr.InitSyncState(peer) assertMsgSent(t, peer, &lnwire.QueryChannelRange{ FirstBlockHeight: 0, - NumBlocks: math.MaxUint32, + NumBlocks: latestKnownHeight, }) // The graph should not be considered as synced since the initial @@ -290,7 +292,7 @@ func TestSyncManagerForceHistoricalSync(t *testing.T) { syncMgr.InitSyncState(peer) assertMsgSent(t, peer, &lnwire.QueryChannelRange{ FirstBlockHeight: 0, - NumBlocks: math.MaxUint32, + NumBlocks: latestKnownHeight, }) // If an additional peer connects, then a historical sync should not be @@ -305,7 +307,7 @@ func TestSyncManagerForceHistoricalSync(t *testing.T) { syncMgr.cfg.HistoricalSyncTicker.(*ticker.Force).Force <- time.Time{} assertMsgSent(t, extraPeer, &lnwire.QueryChannelRange{ FirstBlockHeight: 0, - NumBlocks: math.MaxUint32, + NumBlocks: latestKnownHeight, }) } @@ -326,7 +328,7 @@ func TestSyncManagerGraphSyncedAfterHistoricalSyncReplacement(t *testing.T) { syncMgr.InitSyncState(peer) assertMsgSent(t, peer, &lnwire.QueryChannelRange{ FirstBlockHeight: 0, - NumBlocks: math.MaxUint32, + NumBlocks: latestKnownHeight, }) // The graph should not be considered as synced since the initial @@ -531,7 +533,7 @@ func assertTransitionToChansSynced(t *testing.T, s *GossipSyncer, peer *mockPeer query := &lnwire.QueryChannelRange{ FirstBlockHeight: 0, - NumBlocks: math.MaxUint32, + NumBlocks: latestKnownHeight, } assertMsgSent(t, peer, query) diff --git a/discovery/syncer.go b/discovery/syncer.go index 10b6d420..4f6c4256 100644 --- a/discovery/syncer.go +++ b/discovery/syncer.go @@ -237,6 +237,9 @@ type gossipSyncerCfg struct { // This prevents ranges with old start times from causing us to dump the // graph on connect. ignoreHistoricalFilters bool + + // bestHeight returns the latest height known of the chain. + bestHeight func() uint32 } // GossipSyncer is a struct that handles synchronizing the channel graph state @@ -834,9 +837,17 @@ func (g *GossipSyncer) genChanRangeQuery( startHeight = uint32(newestChan.BlockHeight - chanRangeQueryBuffer) } + // Determine the number of blocks to request based on our best height. + // We'll take into account any potential underflows and explicitly set + // numBlocks to its minimum value of 1 if so. + bestHeight := g.cfg.bestHeight() + numBlocks := bestHeight - startHeight + if int64(numBlocks) < 1 { + numBlocks = 1 + } + log.Infof("GossipSyncer(%x): requesting new chans from height=%v "+ - "and %v blocks after", g.cfg.peerPub[:], startHeight, - math.MaxUint32-startHeight) + "and %v blocks after", g.cfg.peerPub[:], startHeight, numBlocks) // Finally, we'll craft the channel range query, using our starting // height, then asking for all known channels to the foreseeable end of @@ -844,7 +855,7 @@ func (g *GossipSyncer) genChanRangeQuery( query := &lnwire.QueryChannelRange{ ChainHash: g.cfg.chainHash, FirstBlockHeight: startHeight, - NumBlocks: math.MaxUint32 - startHeight, + NumBlocks: numBlocks, } g.curQueryRangeMsg = query diff --git a/discovery/syncer_test.go b/discovery/syncer_test.go index 8e99fa49..6d687bf9 100644 --- a/discovery/syncer_test.go +++ b/discovery/syncer_test.go @@ -158,6 +158,9 @@ func newTestSyncer(hID lnwire.ShortChannelID, return nil }, delayedQueryReplyInterval: 2 * time.Second, + bestHeight: func() uint32 { + return latestKnownHeight + }, } syncer := newGossipSyncer(cfg) @@ -1134,9 +1137,9 @@ func TestGossipSyncerGenChanRangeQuery(t *testing.T) { rangeQuery.FirstBlockHeight, startingHeight-chanRangeQueryBuffer) } - if rangeQuery.NumBlocks != math.MaxUint32-firstHeight { + if rangeQuery.NumBlocks != latestKnownHeight-firstHeight { t.Fatalf("wrong num blocks: expected %v, got %v", - math.MaxUint32-firstHeight, rangeQuery.NumBlocks) + latestKnownHeight-firstHeight, rangeQuery.NumBlocks) } // Generating a historical range query should result in a start height @@ -1149,9 +1152,9 @@ func TestGossipSyncerGenChanRangeQuery(t *testing.T) { t.Fatalf("incorrect chan range query: expected %v, %v", 0, rangeQuery.FirstBlockHeight) } - if rangeQuery.NumBlocks != math.MaxUint32 { + if rangeQuery.NumBlocks != latestKnownHeight { t.Fatalf("wrong num blocks: expected %v, got %v", - math.MaxUint32, rangeQuery.NumBlocks) + latestKnownHeight, rangeQuery.NumBlocks) } } @@ -2234,7 +2237,7 @@ func TestGossipSyncerHistoricalSync(t *testing.T) { // sent to the remote peer with a FirstBlockHeight of 0. expectedMsg := &lnwire.QueryChannelRange{ FirstBlockHeight: 0, - NumBlocks: math.MaxUint32, + NumBlocks: latestKnownHeight, } select {