Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wire, netsync: change isSyncCandidate behavior #2035

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
netsync: change isSyncCandidate behavior to include pruned nodes
isSyncCandidate is now changed to return true even if the peer is a
pruned node if and only if our chaintip is within 288 blocks of the
peer.

Rationale:
Pruned nodes that signal NODE_NETWORK_LIMITED MUST serve 288 blocks from
their chaintip.  If our chaintip is within that range, this peer can be
a sync candidate even if they aren't an archival node.
  • Loading branch information
kcalvinalvin committed Nov 7, 2023
commit b4992febff11fefc1940c67edfbcac97b627efd1
61 changes: 48 additions & 13 deletions netsync/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,20 +397,55 @@ func (sm *SyncManager) isSyncCandidate(peer *peerpkg.Peer) bool {
if host != "127.0.0.1" && host != "localhost" {
return false
}
} else {
// The peer is not a candidate for sync if it's not a full
// node. Additionally, if the segwit soft-fork package has
// activated, then the peer must also be upgraded.
segwitActive, err := sm.chain.IsDeploymentActive(chaincfg.DeploymentSegwit)
if err != nil {
log.Errorf("Unable to query for segwit "+
"soft-fork state: %v", err)
}
nodeServices := peer.Services()
if nodeServices&wire.SFNodeNetwork != wire.SFNodeNetwork ||
(segwitActive && !peer.IsWitnessEnabled()) {

// Candidate if all checks passed.
return true
}

// If the segwit soft-fork package has activated, then the peer must
// also be upgraded.
segwitActive, err := sm.chain.IsDeploymentActive(
chaincfg.DeploymentSegwit,
)
if err != nil {
log.Errorf("Unable to query for segwit soft-fork state: %v",
err)
}

if segwitActive && !peer.IsWitnessEnabled() {
return false
}

var (
nodeServices = peer.Services()
fullNode = nodeServices.HasFlag(wire.SFNodeNetwork)
prunedNode = nodeServices.HasFlag(wire.SFNodeNetworkLimited)
)

switch {
case fullNode:
// Node is a sync candidate if it has all the blocks.

case prunedNode:
// 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
}

// Candidate if all checks passed.
Expand All @@ -428,7 +463,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,
Expand Down
12 changes: 6 additions & 6 deletions wire/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ const (
AddrV2Version uint32 = 70016
)

const (
// NodeNetworkLimitedBlockThreshold is the number of blocks that a node
// broadcasting SFNodeNetworkLimited MUST be able to serve from the tip.
NodeNetworkLimitedBlockThreshold = 288
)

// ServiceFlag identifies services supported by a bitcoin peer.
type ServiceFlag uint64

Expand Down Expand Up @@ -156,12 +162,6 @@ func (f ServiceFlag) String() string {
return s
}

const (
// NodeNetworkLimitedBlockThreshold is the number of blocks that a node
// broadcasting SFNodeNetworkLimited MUST be able to serve from the tip.
NodeNetworkLimitedBlockThreshold = 288
)

// BitcoinNet represents which bitcoin network a message belongs to.
type BitcoinNet uint32

Expand Down
Loading