eth/downloader: implement beacon sync (#23982)
* eth/downloader: implement beacon sync * eth/downloader: fix a crash if the beacon chain is reduced in length * eth/downloader: fix beacon sync start/stop thrashing data race * eth/downloader: use a non-nil pivot even in degenerate sync requests * eth/downloader: don't touch internal state on beacon Head retrieval * eth/downloader: fix spelling mistakes * eth/downloader: fix some typos * eth: integrate legacy/beacon sync switchover and UX * eth: handle UX wise being stuck on post-merge TTD * core, eth: integrate the beacon client with the beacon sync * eth/catalyst: make some warning messages nicer * eth/downloader: remove Ethereum 1&2 notions in favor of merge * core/beacon, eth: clean up engine API returns a bit * eth/downloader: add skeleton extension tests * eth/catalyst: keep non-kiln spec, handle mining on ttd * eth/downloader: add beacon header retrieval tests * eth: fixed spelling, commented failing tests out * eth/downloader: review fixes * eth/downloader: drop peers failing to deliver beacon headers * core/rawdb: track beacon sync data in db inspect * eth: fix review concerns * internal/web3ext: nit Co-authored-by: Marius van der Wijden <m.vanderwijden@live.de>
This commit is contained in:
39
eth/sync.go
39
eth/sync.go
@ -17,6 +17,7 @@
|
||||
package eth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@ -65,6 +66,7 @@ type chainSyncer struct {
|
||||
handler *handler
|
||||
force *time.Timer
|
||||
forced bool // true when force timer fired
|
||||
warned time.Time
|
||||
peerEventCh chan struct{}
|
||||
doneCh chan error // non-nil when sync is running
|
||||
}
|
||||
@ -119,10 +121,18 @@ func (cs *chainSyncer) loop() {
|
||||
select {
|
||||
case <-cs.peerEventCh:
|
||||
// Peer information changed, recheck.
|
||||
case <-cs.doneCh:
|
||||
case err := <-cs.doneCh:
|
||||
cs.doneCh = nil
|
||||
cs.force.Reset(forceSyncCycle)
|
||||
cs.forced = false
|
||||
|
||||
// If we've reached the merge transition but no beacon client is available, or
|
||||
// it has not yet switched us over, keep warning the user that their infra is
|
||||
// potentially flaky.
|
||||
if errors.Is(err, downloader.ErrMergeTransition) && time.Since(cs.warned) > 10*time.Second {
|
||||
log.Warn("Local chain is post-merge, waiting for beacon client sync switch-over...")
|
||||
cs.warned = time.Now()
|
||||
}
|
||||
case <-cs.force.C:
|
||||
cs.forced = true
|
||||
|
||||
@ -143,9 +153,16 @@ func (cs *chainSyncer) loop() {
|
||||
// nextSyncOp determines whether sync is required at this time.
|
||||
func (cs *chainSyncer) nextSyncOp() *chainSyncOp {
|
||||
if cs.doneCh != nil {
|
||||
return nil // Sync already running.
|
||||
return nil // Sync already running
|
||||
}
|
||||
// Disable the td based sync trigger after the transition
|
||||
// If a beacon client once took over control, disable the entire legacy sync
|
||||
// path from here on end. Note, there is a slight "race" between reaching TTD
|
||||
// and the beacon client taking over. The downloader will enforce that nothing
|
||||
// above the first TTD will be delivered to the chain for import.
|
||||
//
|
||||
// An alternative would be to check the local chain for exceeding the TTD and
|
||||
// avoid triggering a sync in that case, but that could also miss sibling or
|
||||
// other family TTD block being accepted.
|
||||
if cs.handler.merger.TDDReached() {
|
||||
return nil
|
||||
}
|
||||
@ -159,16 +176,24 @@ func (cs *chainSyncer) nextSyncOp() *chainSyncOp {
|
||||
if cs.handler.peers.len() < minPeers {
|
||||
return nil
|
||||
}
|
||||
// We have enough peers, check TD
|
||||
// We have enough peers, pick the one with the highest TD, but avoid going
|
||||
// over the terminal total difficulty. Above that we expect the consensus
|
||||
// clients to direct the chain head to sync to.
|
||||
peer := cs.handler.peers.peerWithHighestTD()
|
||||
if peer == nil {
|
||||
return nil
|
||||
}
|
||||
mode, ourTD := cs.modeAndLocalHead()
|
||||
|
||||
op := peerToSyncOp(mode, peer)
|
||||
if op.td.Cmp(ourTD) <= 0 {
|
||||
return nil // We're in sync.
|
||||
// We seem to be in sync according to the legacy rules. In the merge
|
||||
// world, it can also mean we're stuck on the merge block, waiting for
|
||||
// a beacon client. In the latter case, notify the user.
|
||||
if cs.handler.chain.Config().TerminalTotalDifficulty != nil && time.Since(cs.warned) > 10*time.Second {
|
||||
log.Warn("Local chain is post-merge, waiting for beacon client sync switch-over...")
|
||||
cs.warned = time.Now()
|
||||
}
|
||||
return nil // We're in sync
|
||||
}
|
||||
return op
|
||||
}
|
||||
@ -227,7 +252,7 @@ func (h *handler) doSync(op *chainSyncOp) error {
|
||||
}
|
||||
}
|
||||
// Run the sync cycle, and disable snap sync if we're past the pivot block
|
||||
err := h.downloader.Synchronise(op.peer.ID(), op.head, op.td, op.mode)
|
||||
err := h.downloader.LegacySync(op.peer.ID(), op.head, op.td, h.chain.Config().TerminalTotalDifficulty, op.mode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Reference in New Issue
Block a user