Skip to content

Commit 5adea82

Browse files
committed
fix(eth): log sync status each cycle while node is behind network
The sync status logger only fired while the downloader was inside a bulk historical sync. Once the node is caught up, new blocks are followed through the block fetcher / BFT announcements, so Synchronising() stays false and the warn log appeared only once or never over hours of normal operation instead of every 10 minutes. The logger now reports whenever the node is behind the best peer's head, covering both the downloader and the announcement-driven catch-up paths.
1 parent 436a229 commit 5adea82

2 files changed

Lines changed: 91 additions & 11 deletions

File tree

eth/sync.go

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -205,24 +205,40 @@ func (pm *ProtocolManager) syncStatusLogger() {
205205
for {
206206
select {
207207
case <-ticker.C:
208-
if pm.downloader.Synchronising() {
209-
progress := pm.downloader.Progress()
210-
log.Warn("Block synchronisation in progress",
211-
"starting", progress.StartingBlock,
212-
"current", progress.CurrentBlock,
213-
"highest", progress.HighestBlock,
214-
"pulledStates", progress.PulledStates,
215-
"knownStates", progress.KnownStates,
216-
"peers", pm.peers.Len(),
217-
)
218-
}
208+
pm.reportSyncStatus()
219209

220210
case <-pm.quitSync:
221211
return
222212
}
223213
}
224214
}
225215

216+
// reportSyncStatus emits a warn-level log whenever the node is behind the best
217+
// peer's head. Gating on the downloader alone is not enough: once the bulk
218+
// historical sync finishes, new blocks are fetched through the block fetcher /
219+
// BFT announcements, so `downloader.Synchronising()` stays false even while the
220+
// node is still catching up.
221+
func (pm *ProtocolManager) reportSyncStatus() {
222+
peer := pm.peers.BestPeer()
223+
if peer == nil {
224+
return
225+
}
226+
current := pm.blockchain.CurrentBlock()
227+
_, pTd := peer.Head()
228+
if pTd.Cmp(pm.blockchain.GetTd(current.Hash(), current.Number.Uint64())) <= 0 {
229+
return // We are at or ahead of the best peer, nothing left to sync
230+
}
231+
progress := pm.downloader.Progress()
232+
log.Warn("Block synchronisation in progress",
233+
"starting", progress.StartingBlock,
234+
"current", progress.CurrentBlock,
235+
"highest", progress.HighestBlock,
236+
"pulledStates", progress.PulledStates,
237+
"knownStates", progress.KnownStates,
238+
"peers", pm.peers.Len(),
239+
)
240+
}
241+
226242
// synchronise tries to sync up our local block chain with a remote peer.
227243
func (pm *ProtocolManager) synchronise(peer *peer) {
228244
// Short circuit if no peers are available

eth/sync_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,15 @@
1717
package eth
1818

1919
import (
20+
"bytes"
21+
"math/big"
22+
"strings"
2023
"sync/atomic"
2124
"testing"
2225
"time"
2326

2427
"github.com/XinFinOrg/XDPoSChain/eth/downloader"
28+
"github.com/XinFinOrg/XDPoSChain/log"
2529
"github.com/XinFinOrg/XDPoSChain/p2p"
2630
"github.com/XinFinOrg/XDPoSChain/p2p/enode"
2731
)
@@ -31,6 +35,66 @@ func TestFastSyncDisabling100(t *testing.T) { testFastSyncDisabling(t, xdc100) }
3135
func TestFastSyncDisabling164(t *testing.T) { testFastSyncDisabling(t, xdc164) }
3236
func TestFastSyncDisabling165(t *testing.T) { testFastSyncDisabling(t, xdc165) }
3337

38+
// Tests that the periodic sync status logger reports progress whenever the node
39+
// is behind the best peer's head, even when the downloader is idle (i.e. the
40+
// node is following new blocks through the block fetcher / BFT announcements).
41+
func TestSyncStatusLogger(t *testing.T) {
42+
pm, _ := newTestProtocolManagerMust(t, downloader.FullSync, 0, nil, nil)
43+
defer pm.Stop()
44+
45+
// Capture the warn-level logs emitted by the sync status logger.
46+
var logBuf bytes.Buffer
47+
prevLog := log.Root()
48+
glog := log.NewGlogHandler(log.NewTerminalHandlerWithLevel(&logBuf, log.LevelTrace, false))
49+
glog.Verbosity(log.LevelTrace)
50+
log.SetDefault(log.NewLogger(glog))
51+
defer log.SetDefault(prevLog)
52+
53+
// Register a peer that we can move ahead of / behind our own chain head.
54+
app, net := p2p.MsgPipe()
55+
defer app.Close()
56+
peer := pm.newPeer(xdc100, p2p.NewPeer(enode.ID{1}, "sync-status-peer", nil), net, pm.txpool.Get)
57+
if err := pm.peers.Register(peer); err != nil {
58+
t.Fatalf("failed to register peer: %v", err)
59+
}
60+
defer pm.peers.Unregister(peer.id)
61+
62+
current := pm.blockchain.CurrentBlock()
63+
localTD := pm.blockchain.GetTd(current.Hash(), current.Number.Uint64())
64+
65+
// setHead moves the peer's advertised head to the given total difficulty.
66+
// The handshake (which normally initialises these fields) is skipped here,
67+
// so set the peer's head state directly.
68+
setHead := func(td *big.Int) {
69+
peer.lock.Lock()
70+
defer peer.lock.Unlock()
71+
peer.head = current.Hash()
72+
peer.td = new(big.Int).Set(td)
73+
}
74+
75+
// A peer ahead of us must trigger a sync status report...
76+
setHead(new(big.Int).Add(localTD, big.NewInt(1)))
77+
pm.reportSyncStatus()
78+
if got := strings.Count(logBuf.String(), "Block synchronisation in progress"); got != 1 {
79+
t.Fatalf("expected a sync status log when behind the best peer, got %d, log: %q", got, logBuf.String())
80+
}
81+
// ...while a peer at or behind us must not.
82+
logBuf.Reset()
83+
setHead(localTD)
84+
pm.reportSyncStatus()
85+
if got := strings.Count(logBuf.String(), "Block synchronisation in progress"); got != 0 {
86+
t.Fatalf("expected no sync status log when at the best peer's head, got %d, log: %q", got, logBuf.String())
87+
}
88+
// The progress fields must be populated with the local chain state.
89+
logBuf.Reset()
90+
setHead(new(big.Int).Add(localTD, big.NewInt(1)))
91+
pm.reportSyncStatus()
92+
logLine := logBuf.String()
93+
if !strings.Contains(logLine, "current=") || !strings.Contains(logLine, "peers=1") {
94+
t.Fatalf("expected populated progress fields, got %q", logLine)
95+
}
96+
}
97+
3498
// Tests that fast sync gets disabled as soon as a real block is successfully
3599
// imported into the blockchain.
36100
func testFastSyncDisabling(t *testing.T, protocol int) {

0 commit comments

Comments
 (0)