Skip to content

Commit 059fde0

Browse files
committed
Select new sync peer if median of sync peer candidates are ahead of us
1 parent 013d095 commit 059fde0

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

netsync/manager.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"container/list"
99
"math/rand"
1010
"net"
11+
"sort"
1112
"sync"
1213
"sync/atomic"
1314
"time"
@@ -525,6 +526,13 @@ func (sm *SyncManager) handleCheckSyncPeer() {
525526
return
526527
}
527528

529+
// Check if a majority of our sync peer candidates are at a greater height than our current sync peer.
530+
// If they are, it is time to select a new peer, as ours is obviously behind.
531+
if sm.topBlock() < sm.medianSyncPeerCandidateBlockHeight() {
532+
sm.updateSyncPeer()
533+
return
534+
}
535+
528536
// Update network stats at the end of this tick.
529537
defer sm.syncPeerState.updateNetwork(sm.syncPeer)
530538

@@ -537,7 +545,6 @@ func (sm *SyncManager) handleCheckSyncPeer() {
537545

538546
// Don't update sync peers if you have all the available
539547
// blocks.
540-
541548
best := sm.chain.BestSnapshot()
542549

543550
if sm.topBlock() == best.Height || sm.chain.UtxoCacheFlushInProgress() || (sm.fastSyncMode && best.Height == sm.lastCheckpoint().Height) {
@@ -550,6 +557,40 @@ func (sm *SyncManager) handleCheckSyncPeer() {
550557
sm.updateSyncPeer()
551558
}
552559

560+
// medianSyncPeerCandidateBlockHeight returns the median block height of sync peer candidates.
561+
func (sm *SyncManager) medianSyncPeerCandidateBlockHeight() int32 {
562+
heights := []int32{}
563+
564+
for peer, state := range sm.peerStates {
565+
if !state.syncCandidate {
566+
continue
567+
}
568+
569+
// Peer isn't connected, skip.
570+
if !peer.Connected() {
571+
continue
572+
}
573+
574+
heights = append(heights, peer.LastBlock())
575+
}
576+
577+
// If we don't have any sync peer candidate heights, return 0.
578+
// This is just to protect from a panic below.
579+
if len(heights) < 1 {
580+
return 0
581+
}
582+
583+
sort.Slice(heights, func(i, j int) bool { return heights[i] < heights[j] })
584+
585+
mNumber := len(heights) / 2
586+
587+
if len(heights)%2 != 0 {
588+
return heights[mNumber]
589+
}
590+
591+
return (heights[mNumber-1] + heights[mNumber]) / 2
592+
}
593+
553594
// topBlock returns the best chains top block height
554595
func (sm *SyncManager) topBlock() int32 {
555596
if sm.syncPeer.LastBlock() > sm.syncPeer.StartingHeight() {

0 commit comments

Comments
 (0)