Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 4 additions & 0 deletions netsync/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,10 @@ func (sm *SyncManager) updateSyncPeer(dcSyncPeer bool) {
}

sm.syncPeer = nil
// IBD requires an active sync peer. Clear it with the peer so a lost
// sync peer cannot leave the manager in a state where announcements are
// ignored indefinitely.
sm.ibdMode = false

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This clears IBD mode unconditionally, including when the node is far from the tip and no higher-height peer is available to take over. In that window syncPeer is nil and ibdMode is false, so a headers message from any peer now falls through to fetchHeaderBlocks (~line 1014) with no check that the sender is the sync peer or even a sync candidate.

As I understand it, that can reserve up to 50k block hashes in requestedBlocks from a peer that never serves them, and nothing clears those entries while there's no sync peer. A later honest sync peer then skips every reserved hash and stalls out. Pre-PR the ibdMode guard in handleHeadersMsg blocked this. Can you confirm whether that's reachable, and if so gate the fall-through on the peer being the sync peer or a sync candidate?

sm.startSync()
}

Expand Down
Loading
Loading