diff --git a/netsync/manager.go b/netsync/manager.go index 523437a0c55..a3928a20cc9 100644 --- a/netsync/manager.go +++ b/netsync/manager.go @@ -406,9 +406,30 @@ func (sm *SyncManager) isSyncCandidate(peer *peerpkg.Peer) bool { log.Errorf("Unable to query for segwit "+ "soft-fork state: %v", err) } + if segwitActive && !peer.IsWitnessEnabled() { + return false + } + nodeServices := peer.Services() - if nodeServices&wire.SFNodeNetwork != wire.SFNodeNetwork || - (segwitActive && !peer.IsWitnessEnabled()) { + + switch { + case nodeServices&wire.SFNodeNetwork == wire.SFNodeNetwork: + // Node is a sync candidate if it has all the blocks. + case nodeServices&wire.SFNodeNetworkLimited == wire.SFNodeNetworkLimited: + // Even if the peer is pruned, if they have the node network limited + // flag, they are able to serve 2 days worth of blocks from the + // current tip. Therefore, check if our chaintip is within that range. + bestHeight := sm.chain.BestSnapshot().Height + peerLastBlock := peer.LastBlock() + + // bestHeight+1 as we need the peer to serve us the next block, + // not the one we already have. + if bestHeight+1 < peerLastBlock-wire.NodeNetworkLimitedBlockThreshold { + return false + } + default: + // If the peer isn't an archival node and it's not signaling + // NODE_NETWORK_LIMITED, we can't sync off of this node. return false } } @@ -428,7 +449,7 @@ func (sm *SyncManager) handleNewPeerMsg(peer *peerpkg.Peer) { log.Infof("New valid peer %s (%s)", peer, peer.UserAgent()) - // Initialize the peer state + // Initialize the peer state. isSyncCandidate := sm.isSyncCandidate(peer) sm.peerStates[peer] = &peerSyncState{ syncCandidate: isSyncCandidate,