Skip to content

Commit

Permalink
fix pbss recover(geth)
Browse files Browse the repository at this point in the history
  • Loading branch information
krish-nr committed Jun 14, 2024
1 parent d0fbab5 commit 7c537b7
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 17 deletions.
2 changes: 2 additions & 0 deletions beacon/engine/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ var (
// - newPayloadV1: if the payload was accepted, but not processed (side chain)
ACCEPTED = "ACCEPTED"

UNCONSISTENT = "UNCONSISTENT"

GenericServerError = &EngineAPIError{code: -32000, msg: "Server error"}
UnknownPayload = &EngineAPIError{code: -38001, msg: "Unknown payload"}
InvalidForkChoiceState = &EngineAPIError{code: -38002, msg: "Invalid forkchoice state"}
Expand Down
53 changes: 44 additions & 9 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
if bc.triedb.Scheme() == rawdb.PathScheme {
recoverable, _ := bc.triedb.Recoverable(diskRoot)
if !bc.HasState(diskRoot) && !recoverable {
log.Info("ZXL: diskRoot reset")
diskRoot = bc.triedb.Head()
}
}
Expand Down Expand Up @@ -761,13 +762,14 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
newHeadBlock = bc.GetBlock(newHeadBlock.ParentHash(), newHeadBlock.NumberU64()-1) // Keep rewinding
}
}
rawdb.WriteHeadBlockHash(db, newHeadBlock.Hash())
rawdb.WriteHeadBlockHash(db, newHeadBlock.Hash()) //这里已经写入的是带MPT的高度

// Degrade the chain markers if they are explicitly reverted.
// In theory we should update all in-memory markers in the
// last step, however the direction of SetHead is from high
// to low, so it's safe to update in-memory markers directly.
bc.currentBlock.Store(newHeadBlock.Header())
log.Info("ZXL: rewind header now is", "header", newHeadBlock.Header().Number.Uint64())
headBlockGauge.Update(int64(newHeadBlock.NumberU64()))

// The head state is missing, which is only possible in the path-based
Expand Down Expand Up @@ -833,6 +835,7 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
// touching the header chain altogether, unless the freezer is broken
if repair {
if target, force := updateFn(bc.db, bc.CurrentBlock()); force {
log.Info("ZXL: force set head", "head", target.Number.Uint64())
bc.hc.SetHead(target.Number.Uint64(), updateFn, delFn)
}
} else {
Expand All @@ -857,15 +860,47 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha
bc.miningStateCache.Purge()
bc.futureBlocks.Purge()

// Clear safe block, finalized block if needed
if safe := bc.CurrentSafeBlock(); safe != nil && head < safe.Number.Uint64() {
log.Warn("SetHead invalidated safe block")
bc.SetSafe(nil)
}
if finalized := bc.CurrentFinalBlock(); finalized != nil && head < finalized.Number.Uint64() {
log.Error("SetHead invalidated finalized block")
bc.SetFinalized(nil)
log.Info("ZXL: after setHeadBeyondRoot", "currenthead", bc.CurrentBlock().Number.Uint64())

//修改

if bc.triedb.Scheme() == rawdb.PathScheme {
headHeaderUpdated := bc.CurrentBlock()
var safe *types.Header
if safe = bc.CurrentSafeBlock(); safe != nil && headHeaderUpdated.Number.Uint64() < safe.Number.Uint64() {
log.Warn("SetHead invalidated safe block", "before", safe.Number.Uint64(), "after", headHeaderUpdated.Number.Uint64())
bc.SetSafe(headHeaderUpdated)
}
log.Info("ZXL", "safe before set", safe.Number.Uint64(), "after", bc.CurrentSafeBlock().Number.Uint64())

var finalized *types.Header

if finalized = bc.CurrentFinalBlock(); finalized != nil && headHeaderUpdated.Number.Uint64() < finalized.Number.Uint64() {
log.Error("SetHead invalidated finalized block", "before", finalized.Number.Uint64(), "after", headHeaderUpdated.Number.Uint64())
bc.SetFinalized(headHeaderUpdated)
}
log.Info("ZXL", "finalized before set", finalized.Number.Uint64(), "after", bc.CurrentFinalBlock().Number.Uint64())
} else {
// Clear safe block, finalized block if needed
var safe *types.Header
if safe = bc.CurrentSafeBlock(); safe != nil && head < safe.Number.Uint64() {
log.Warn("SetHead invalidated safe block")
bc.SetSafe(nil)
}
log.Info("ZXL", "safe after set", safe.Number.Uint64(), "head", head)

var finalized *types.Header

if finalized = bc.CurrentFinalBlock(); finalized != nil && head < finalized.Number.Uint64() {
log.Error("SetHead invalidated finalized block")
bc.SetFinalized(nil)
}
log.Info("ZXL", "finalized after set", finalized.Number.Uint64(), "head", head)

}

log.Info("ZXL", "rootNumber", rootNumber)

return rootNumber, bc.loadLastState()
}

Expand Down
26 changes: 18 additions & 8 deletions eth/catalyst/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ import (

var (
forkchoiceUpdateAttributesTimer = metrics.NewRegisteredTimer("api/engine/forkchoiceUpdate/attributes", nil)
forkchoiceUpdateHeadsTimer = metrics.NewRegisteredTimer("api/engine/forkchoiceUpdate/heads", nil)
getPayloadTimer = metrics.NewRegisteredTimer("api/engine/get/payload", nil)
newPayloadTimer = metrics.NewRegisteredTimer("api/engine/new/payload", nil)
forkchoiceUpdateHeadsTimer = metrics.NewRegisteredTimer("api/engine/forkchoiceUpdate/heads", nil)
getPayloadTimer = metrics.NewRegisteredTimer("api/engine/get/payload", nil)
newPayloadTimer = metrics.NewRegisteredTimer("api/engine/new/payload", nil)
)

// Register adds the engine API to the full node.
Expand Down Expand Up @@ -256,6 +256,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
// reason.
block := api.eth.BlockChain().GetBlockByHash(update.HeadBlockHash)
if block == nil {
log.Info("ZXL: fcu has not block", "block", block.NumberU64())
// If this block was previously invalidated, keep rejecting it here too
if res := api.checkInvalidAncestor(update.HeadBlockHash, update.HeadBlockHash); res != nil {
return engine.ForkChoiceResponse{PayloadStatus: *res, PayloadID: nil}, nil
Expand Down Expand Up @@ -468,10 +469,10 @@ func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.Execu

func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID, full bool) (*engine.ExecutionPayloadEnvelope, error) {
start := time.Now()
defer func () {
defer func() {
getPayloadTimer.UpdateSince(start)
log.Debug("getPayloadTimer", "duration", common.PrettyDuration(time.Since(start)), "id", payloadID)
} ()
}()
log.Trace("Engine API request received", "method", "GetPayload", "id", payloadID)
data := api.localBlocks.get(payloadID, full)
if data == nil {
Expand Down Expand Up @@ -527,10 +528,10 @@ func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHas

func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash) (engine.PayloadStatusV1, error) {
start := time.Now()
defer func () {
defer func() {
newPayloadTimer.UpdateSince(start)
log.Debug("newPayloadTimer", "duration", common.PrettyDuration(time.Since(start)), "parentHash", params.ParentHash)
} ()
}()

// The locking here is, strictly, not required. Without these locks, this can happen:
//
Expand Down Expand Up @@ -577,9 +578,17 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
// will not trigger a sync cycle. That is fine though, if we get a fork choice
// update after legit payload executions.
parent := api.eth.BlockChain().GetBlock(block.ParentHash(), block.NumberU64()-1)

if parent == nil {
return api.delayPayloadImport(block)
}

/*
if parent == nil || !api.eth.BlockChain().HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
return api.delayPayloadImport(block)
}
*/
// We have an existing parent, do some sanity checks to avoid the beacon client
// triggering too early
var (
Expand Down Expand Up @@ -609,7 +618,8 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData, versionedHashe
if !api.eth.BlockChain().HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
api.remoteBlocks.put(block.Hash(), block.Header())
log.Warn("State not available, ignoring new payload")
return engine.PayloadStatusV1{Status: engine.ACCEPTED}, nil
//return unconsistent
return engine.PayloadStatusV1{Status: engine.UNCONSISTENT}, nil
}
log.Trace("Inserting block without sethead", "hash", block.Hash(), "number", block.Number)
if err := api.eth.BlockChain().InsertBlockWithoutSetHead(block); err != nil {
Expand Down

0 comments on commit 7c537b7

Please sign in to comment.