eth/catalyst: fetch header on forkchoiceUpdated (#31928)

closes https://github.com/ethereum/go-ethereum/issues/31254

---------

Co-authored-by: Gary Rong <garyrong0905@gmail.com>
This commit is contained in:
Marius van der Wijden 2025-06-18 09:06:49 +02:00 committed by GitHub
parent fa8f391db3
commit 4ea9eea75f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 30 additions and 18 deletions

View file

@ -283,8 +283,14 @@ 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)
return engine.STATUS_SYNCING, nil
log.Warn("Fetching the unknown forkchoice head from network", "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.

View file

@ -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,34 +49,39 @@ func (d *Downloader) BeaconDevSync(mode SyncMode, hash common.Hash, stop chan st
return errors.New("stop requested")
default:
}
// Pick a random peer to sync from and keep retrying if none are yet
// available due to fresh startup
d.peers.lock.RLock()
var peer *peerConnection
for _, peer = range d.peers.peers {
break
}
d.peers.lock.RUnlock()
if peer == nil {
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()
defer d.peers.lock.RUnlock()
for _, peer := range d.peers.peers {
if peer == nil {
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
log.Info("Attempting to retrieve sync target", "peer", peer.id)
log.Debug("Attempting to retrieve sync target", "peer", peer.id, "hash", hash)
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
}
// 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)
log.Warn("Received invalid sync target", "peer", peer.id, "want", hash, "have", metas[0])
continue
}
return d.BeaconSync(mode, headers[0], headers[0])
return headers[0], nil
}
return nil, errors.New("failed to fetch sync target")
}