mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-11 01:11:37 +00:00
core/rawdb, eth/downloader: persist partial-sync completion across restarts
d.partialSyncComplete is consulted by beaconBackfiller.resume() to skip redundant downloader cycles after the initial partial-state sync has finished. It was an in-memory atomic.Bool, so every process restart reset it to false, and the next forkchoiceUpdated from the CL would re-enter the sync loop. Persist the flag in leveldb via a new PartialSyncComplete marker: - Add ReadPartialSyncComplete / WritePartialSyncComplete / DeletePartialSyncComplete accessors in core/rawdb/accessors_chain.go backed by a single-byte value under the PartialSyncComplete key. - Write the marker in the downloader right after AdvancePartialHead succeeds (same spot we flip the in-memory flag). - Rehydrate the in-memory flag from leveldb in Downloader.New() so a freshly-started process with a completed partial-state sync keeps the resume short-circuit active from the first beacon forkchoice. Without this, the restart invariant relied on HasState(header.Root) accidentally returning false to reroute the downloader back to SnapSync; with this the resume guard is the primary protection regardless of how header-root convergence evolves.
This commit is contained in:
parent
e131e7708b
commit
e0c5cff4df
3 changed files with 42 additions and 0 deletions
|
|
@ -200,6 +200,32 @@ func WriteLastPivotNumber(db ethdb.KeyValueWriter, pivot uint64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadPartialSyncComplete reports whether the partial-state initial sync
|
||||||
|
// completed successfully on this datadir. Returns false if the flag is
|
||||||
|
// unset or absent (fresh database, non-partial-state node, or sync in
|
||||||
|
// progress).
|
||||||
|
func ReadPartialSyncComplete(db ethdb.KeyValueReader) bool {
|
||||||
|
data, _ := db.Get(partialSyncCompleteKey)
|
||||||
|
return len(data) > 0 && data[0] == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// WritePartialSyncComplete marks the partial-state initial sync as finished.
|
||||||
|
// The downloader uses this on restart to skip redundant sync cycles.
|
||||||
|
func WritePartialSyncComplete(db ethdb.KeyValueWriter) {
|
||||||
|
if err := db.Put(partialSyncCompleteKey, []byte{1}); err != nil {
|
||||||
|
log.Crit("Failed to store partial-sync-complete flag", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeletePartialSyncComplete clears the partial-state sync completion flag.
|
||||||
|
// Used when the node is reset to genesis or rewound behind the pivot so a
|
||||||
|
// fresh partial sync can run.
|
||||||
|
func DeletePartialSyncComplete(db ethdb.KeyValueWriter) {
|
||||||
|
if err := db.Delete(partialSyncCompleteKey); err != nil {
|
||||||
|
log.Crit("Failed to delete partial-sync-complete flag", "err", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ReadTxIndexTail retrieves the number of oldest indexed block
|
// ReadTxIndexTail retrieves the number of oldest indexed block
|
||||||
// whose transaction indices has been indexed.
|
// whose transaction indices has been indexed.
|
||||||
func ReadTxIndexTail(db ethdb.KeyValueReader) *uint64 {
|
func ReadTxIndexTail(db ethdb.KeyValueReader) *uint64 {
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,12 @@ var (
|
||||||
// snapSyncStatusFlagKey flags that status of snap sync.
|
// snapSyncStatusFlagKey flags that status of snap sync.
|
||||||
snapSyncStatusFlagKey = []byte("SnapSyncStatus")
|
snapSyncStatusFlagKey = []byte("SnapSyncStatus")
|
||||||
|
|
||||||
|
// partialSyncCompleteKey flags that the partial-state initial sync
|
||||||
|
// (snap sync + second state sync to HEAD + AdvancePartialHead) has
|
||||||
|
// finished successfully on this datadir. Consumed by the downloader
|
||||||
|
// so beaconBackfiller.resume() keeps short-circuiting across restarts.
|
||||||
|
partialSyncCompleteKey = []byte("PartialSyncComplete")
|
||||||
|
|
||||||
// Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes).
|
// Data item prefixes (use single byte to avoid mixing data types, avoid `i`, used for indexes).
|
||||||
headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header
|
headerPrefix = []byte("h") // headerPrefix + num (uint64 big endian) + hash -> header
|
||||||
headerTDSuffix = []byte("t") // headerPrefix + num (uint64 big endian) + hash + headerTDSuffix -> td (deprecated)
|
headerTDSuffix = []byte("t") // headerPrefix + num (uint64 big endian) + hash + headerTDSuffix -> td (deprecated)
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,13 @@ func New(stateDb ethdb.Database, mode ethconfig.SyncMode, mux *event.TypeMux, ch
|
||||||
stateSyncStart: make(chan *stateSync),
|
stateSyncStart: make(chan *stateSync),
|
||||||
syncStartBlock: chain.CurrentSnapBlock().Number.Uint64(),
|
syncStartBlock: chain.CurrentSnapBlock().Number.Uint64(),
|
||||||
}
|
}
|
||||||
|
// Rehydrate the partial-state completion flag across restarts. Without
|
||||||
|
// this, a freshly-started process would re-enter the downloader loop for
|
||||||
|
// every beacon forkchoice update, defeating beaconBackfiller.resume()'s
|
||||||
|
// short-circuit.
|
||||||
|
if partialFilter != nil && rawdb.ReadPartialSyncComplete(stateDb) {
|
||||||
|
dl.partialSyncComplete.Store(true)
|
||||||
|
}
|
||||||
// Create the post-merge skeleton syncer and start the process
|
// Create the post-merge skeleton syncer and start the process
|
||||||
dl.skeleton = newSkeleton(stateDb, dl.peers, dropPeer, newBeaconBackfiller(dl, success), chain)
|
dl.skeleton = newSkeleton(stateDb, dl.peers, dropPeer, newBeaconBackfiller(dl, success), chain)
|
||||||
|
|
||||||
|
|
@ -1027,6 +1034,9 @@ func (d *Downloader) processSnapSyncContent() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
d.partialSyncComplete.Store(true)
|
d.partialSyncComplete.Store(true)
|
||||||
|
// Persist the completion flag so a restart does not
|
||||||
|
// re-run the sync cycle on every beacon forkchoice.
|
||||||
|
rawdb.WritePartialSyncComplete(d.stateDB)
|
||||||
log.Info("Partial state initial sync complete")
|
log.Info("Partial state initial sync complete")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue