mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +00:00
eth/catalyst: try to fetch header from network
This commit is contained in:
parent
d6a91b9da8
commit
fc09e939ef
4 changed files with 70 additions and 47 deletions
|
|
@ -35,6 +35,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/txpool"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/eth/gasprice"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
|
|
@ -456,3 +457,7 @@ func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, re
|
|||
func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (*types.Transaction, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) {
|
||||
return b.eth.stateAtTransaction(ctx, block, txIndex, reexec)
|
||||
}
|
||||
|
||||
func (b *EthAPIBackend) Downloader() *downloader.Downloader {
|
||||
return b.eth.Downloader()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -337,9 +337,15 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
|||
// that should be fixed, not papered over.
|
||||
header := api.remoteBlocks.get(update.HeadBlockHash)
|
||||
if header == nil {
|
||||
log.Warn("Forkchoice requested unknown head", "hash", update.HeadBlockHash)
|
||||
log.Warn("Forkchoice requested unknown head, trying to retrive it from a random peer", "hash", update.HeadBlockHash)
|
||||
retrievedHead, err := api.eth.Downloader().GetHeader(update.HeadBlockHash)
|
||||
if err != nil {
|
||||
log.Warn("Could not retrieve unknown head from peers")
|
||||
return engine.STATUS_SYNCING, nil
|
||||
}
|
||||
api.remoteBlocks.put(retrievedHead.Hash(), retrievedHead)
|
||||
header = retrievedHead
|
||||
}
|
||||
// If the finalized hash is known, we can direct the downloader to move
|
||||
// potentially more data to the freezer from the get go.
|
||||
finalized := api.remoteBlocks.get(update.FinalizedBlockHash)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
|
|
@ -48,6 +49,18 @@ func (d *Downloader) BeaconDevSync(mode SyncMode, hash common.Hash, stop chan st
|
|||
return errors.New("stop requested")
|
||||
default:
|
||||
}
|
||||
header, err := d.GetHeader(hash)
|
||||
if err != nil {
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
||||
|
||||
return d.BeaconSync(mode, header, header)
|
||||
}
|
||||
}
|
||||
|
||||
// GetHeader tries to retrieve the header with a given hash from a random peer.
|
||||
func (d *Downloader) GetHeader(hash common.Hash) (*types.Header, error) {
|
||||
// Pick a random peer to sync from and keep retrying if none are yet
|
||||
// available due to fresh startup
|
||||
d.peers.lock.RLock()
|
||||
|
|
@ -58,8 +71,7 @@ func (d *Downloader) BeaconDevSync(mode SyncMode, hash common.Hash, stop chan st
|
|||
d.peers.lock.RUnlock()
|
||||
|
||||
if peer == nil {
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
return nil, errors.New("could not find peer")
|
||||
}
|
||||
// Found a peer, attempt to retrieve the header whilst blocking and
|
||||
// retry if it fails for whatever reason
|
||||
|
|
@ -67,15 +79,12 @@ func (d *Downloader) BeaconDevSync(mode SyncMode, hash common.Hash, stop chan st
|
|||
headers, metas, err := d.fetchHeadersByHash(peer, hash, 1, 0, false)
|
||||
if err != nil || len(headers) != 1 {
|
||||
log.Warn("Failed to fetch sync target", "headers", len(headers), "err", err)
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
return nil, errors.New("failed to fetch sync target")
|
||||
}
|
||||
// Head header retrieved, if the hash matches, start the actual sync
|
||||
if metas[0] != hash {
|
||||
log.Error("Received invalid sync target", "want", hash, "have", metas[0])
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
||||
return d.BeaconSync(mode, headers[0], headers[0])
|
||||
return nil, errors.New("received invalid sync target")
|
||||
}
|
||||
return headers[0], nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||
"github.com/ethereum/go-ethereum/eth/gasestimator"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers/logger"
|
||||
|
|
@ -1700,21 +1701,11 @@ func (api *TransactionAPI) Resend(ctx context.Context, sendArgs TransactionArgs,
|
|||
// namespace.
|
||||
type DebugAPI struct {
|
||||
b Backend
|
||||
// contains filtered or unexported fields
|
||||
}
|
||||
|
||||
// NewDebugAPI creates a new DebugAPI instance.
|
||||
func NewDebugAPI(b Backend) *DebugAPI {
|
||||
// Fill defaults based on the chain config
|
||||
var gasLimit uint64
|
||||
if head := b.CurrentBlock(); head != nil {
|
||||
gasLimit = head.GasLimit
|
||||
}
|
||||
// The geth console doesn't allow flags, so we depend on the configured backend.
|
||||
return &DebugAPI{
|
||||
b: b,
|
||||
defaultCallGas: gasLimit,
|
||||
}
|
||||
return &DebugAPI{b: b}
|
||||
}
|
||||
|
||||
// SetSyncTarget manually sets the target hash for full sync.
|
||||
|
|
@ -1723,15 +1714,27 @@ func NewDebugAPI(b Backend) *DebugAPI {
|
|||
func (api *DebugAPI) SetSyncTarget(ctx context.Context, target common.Hash) error {
|
||||
// Note: BeaconDevSync might block; running in a goroutine to avoid blocking RPC/console.
|
||||
// Also, passing nil for the cancel channel as we don't provide a way to cancel via API.
|
||||
go func() {
|
||||
err := api.b.Downloader().BeaconDevSync(ethconfig.FullSync, target, nil)
|
||||
if err != nil {
|
||||
log.Warn("debug_setSyncTarget: BeaconDevSync failed", "target", target, "err", err)
|
||||
} else {
|
||||
log.Info("debug_setSyncTarget: BeaconDevSync initiated", "target", target)
|
||||
type Downloader interface {
|
||||
Downloader() *downloader.Downloader
|
||||
}
|
||||
}()
|
||||
return nil // API call returns immediately
|
||||
backend, ok := api.b.(Downloader)
|
||||
if !ok {
|
||||
log.Error("Could not get downloader")
|
||||
}
|
||||
// retry 20 times to retrieve the header from random peers
|
||||
for range 20 {
|
||||
header, err := backend.Downloader().GetHeader(target)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if err := backend.Downloader().BeaconSync(ethconfig.FullSync, header, header); err != nil {
|
||||
return err
|
||||
} else {
|
||||
// Sync target set successfully, return
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("could not set sync target")
|
||||
}
|
||||
|
||||
// ChainConfig returns the active chain configuration.
|
||||
|
|
|
|||
Loading…
Reference in a new issue