mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-10 01:56:37 +00:00
eth/catalyst: allow reorging the head block to a parent (#34767)
Implements https://github.com/ethereum/execution-apis/pull/786/changes as discussed on standup today --------- Co-authored-by: Gary Rong <garyrong0905@gmail.com>
This commit is contained in:
parent
84949107ce
commit
4d2af275e1
3 changed files with 29 additions and 6 deletions
|
|
@ -81,6 +81,7 @@ var (
|
|||
TooLargeRequest = &EngineAPIError{code: -38004, msg: "Too large request"}
|
||||
InvalidParams = &EngineAPIError{code: -32602, msg: "Invalid parameters"}
|
||||
UnsupportedFork = &EngineAPIError{code: -38005, msg: "Unsupported fork"}
|
||||
TooDeepReorg = &EngineAPIError{code: -38006, msg: "Too deep reorg"}
|
||||
|
||||
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
|
||||
STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}
|
||||
|
|
|
|||
|
|
@ -2596,8 +2596,13 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error
|
|||
blockReorgAddMeter.Mark(int64(len(newChain)))
|
||||
} else {
|
||||
// len(newChain) == 0 && len(oldChain) > 0
|
||||
// rewind the canonical chain to a lower point.
|
||||
log.Error("Impossible reorg, please file an issue", "oldnum", oldHead.Number, "oldhash", oldHead.Hash(), "oldblocks", len(oldChain), "newnum", newHead.Number, "newhash", newHead.Hash(), "newblocks", len(newChain))
|
||||
// Rewind the canonical chain to a lower point. In EPBs we can reorg to
|
||||
// a parent of the head within 32 blocks.
|
||||
if len(oldChain) > 32 {
|
||||
log.Error("Impossible reorg, please file an issue", "oldnum", oldHead.Number, "oldhash", oldHead.Hash(), "oldblocks", len(oldChain))
|
||||
} else {
|
||||
log.Info("Shorten chain", "del", len(oldChain), "number", oldHead.Number, "hash", oldHead.Hash())
|
||||
}
|
||||
}
|
||||
// Acquire the tx-lookup lock before mutation. This step is essential
|
||||
// as the txlookups should be changed atomically, and all subsequent
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ const (
|
|||
// beaconUpdateWarnFrequency is the frequency at which to warn the user that
|
||||
// the beacon client is offline.
|
||||
beaconUpdateWarnFrequency = 5 * time.Minute
|
||||
|
||||
// maxReorgDepth is the maximum reorg depth accepted via forkchoiceUpdated.
|
||||
maxReorgDepth = 32
|
||||
)
|
||||
|
||||
type ConsensusAPI struct {
|
||||
|
|
@ -237,6 +240,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV4(ctx context.Context, update engine.
|
|||
func (api *ConsensusAPI) forkchoiceUpdated(ctx context.Context, update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, payloadWitness bool) (result engine.ForkChoiceResponse, err error) {
|
||||
ctx, _, spanEnd := telemetry.StartSpan(ctx, "engine.forkchoiceUpdated")
|
||||
defer spanEnd(&err)
|
||||
|
||||
api.forkchoiceLock.Lock()
|
||||
defer api.forkchoiceLock.Unlock()
|
||||
|
||||
|
|
@ -321,10 +325,23 @@ func (api *ConsensusAPI) forkchoiceUpdated(ctx context.Context, update engine.Fo
|
|||
// generating the payload. It's a special corner case that a few slots are
|
||||
// missing and we are requested to generate the payload in slot.
|
||||
} else {
|
||||
// If the head block is already in our canonical chain, the beacon client is
|
||||
// probably resyncing. Ignore the update.
|
||||
log.Info("Ignoring beacon update to old head", "number", block.NumberU64(), "hash", update.HeadBlockHash, "age", common.PrettyAge(time.Unix(int64(block.Time()), 0)), "have", api.eth.BlockChain().CurrentBlock().Number)
|
||||
return valid(nil), nil
|
||||
if finalized := api.eth.BlockChain().CurrentFinalBlock(); finalized != nil && block.NumberU64() <= finalized.Number.Uint64() {
|
||||
log.Info("Skipping beacon update to finalized ancestor", "number", block.NumberU64(), "hash", update.HeadBlockHash)
|
||||
return valid(nil), nil
|
||||
}
|
||||
depth := api.eth.BlockChain().CurrentBlock().Number.Uint64() - block.NumberU64()
|
||||
if depth >= maxReorgDepth {
|
||||
log.Warn("Refusing too deep reorg", "depth", depth, "head", update.HeadBlockHash)
|
||||
return engine.STATUS_INVALID, engine.TooDeepReorg.With(fmt.Errorf("reorg depth %d exceeds limit %d", depth, maxReorgDepth))
|
||||
}
|
||||
if !api.eth.Synced() {
|
||||
log.Info("Ignoring beacon update to old head while syncing", "number", block.NumberU64(), "hash", update.HeadBlockHash)
|
||||
return valid(nil), nil
|
||||
}
|
||||
if latestValid, err := api.eth.BlockChain().SetCanonical(block); err != nil {
|
||||
log.Error("Error setting canonical", "number", block.NumberU64(), "hash", update.HeadBlockHash, "error", err)
|
||||
return engine.ForkChoiceResponse{PayloadStatus: engine.PayloadStatusV1{Status: engine.INVALID, LatestValidHash: &latestValid}}, err
|
||||
}
|
||||
}
|
||||
api.eth.SetSynced()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue