forked from cerc-io/plugeth
eth/catalyst: set the correct LatestValidHash (#24855)
* eth/catalyst: set the correct LatestValidHash * eth/catalyst: core: return LVH during reorg, rework invalid teminal block * eth/catalyst: nitpicks
This commit is contained in:
@@ -16,7 +16,10 @@
|
||||
|
||||
package beacon
|
||||
|
||||
import "github.com/ethereum/go-ethereum/rpc"
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
var (
|
||||
// VALID is returned by the engine API in the following calls:
|
||||
@@ -38,13 +41,13 @@ var (
|
||||
// - newPayloadV1: if the payload was accepted, but not processed (side chain)
|
||||
ACCEPTED = "ACCEPTED"
|
||||
|
||||
INVALIDBLOCKHASH = "INVALID_BLOCK_HASH"
|
||||
INVALIDTERMINALBLOCK = "INVALID_TERMINAL_BLOCK"
|
||||
INVALIDBLOCKHASH = "INVALID_BLOCK_HASH"
|
||||
|
||||
GenericServerError = rpc.CustomError{Code: -32000, ValidationError: "Server error"}
|
||||
UnknownPayload = rpc.CustomError{Code: -32001, ValidationError: "Unknown payload"}
|
||||
InvalidTB = rpc.CustomError{Code: -32002, ValidationError: "Invalid terminal block"}
|
||||
|
||||
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
|
||||
STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}
|
||||
STATUS_INVALID = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: INVALID}, PayloadID: nil}
|
||||
STATUS_SYNCING = ForkChoiceResponse{PayloadStatus: PayloadStatusV1{Status: SYNCING}, PayloadID: nil}
|
||||
INVALID_TERMINAL_BLOCK = PayloadStatusV1{Status: INVALID, LatestValidHash: &common.Hash{}}
|
||||
)
|
||||
|
||||
+15
-13
@@ -1480,7 +1480,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
|
||||
} else {
|
||||
// We're post-merge and the parent is pruned, try to recover the parent state
|
||||
log.Debug("Pruned ancestor", "number", block.Number(), "hash", block.Hash())
|
||||
return it.index, bc.recoverAncestors(block)
|
||||
_, err := bc.recoverAncestors(block)
|
||||
return it.index, err
|
||||
}
|
||||
// First block is future, shove it (and all children) to the future queue (unknown ancestor)
|
||||
case errors.Is(err, consensus.ErrFutureBlock) || (errors.Is(err, consensus.ErrUnknownAncestor) && bc.futureBlocks.Contains(it.first().ParentHash())):
|
||||
@@ -1849,7 +1850,8 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
|
||||
// recoverAncestors finds the closest ancestor with available state and re-execute
|
||||
// all the ancestor blocks since that.
|
||||
// recoverAncestors is only used post-merge.
|
||||
func (bc *BlockChain) recoverAncestors(block *types.Block) error {
|
||||
// We return the hash of the latest block that we could correctly validate.
|
||||
func (bc *BlockChain) recoverAncestors(block *types.Block) (common.Hash, error) {
|
||||
// Gather all the sidechain hashes (full blocks may be memory heavy)
|
||||
var (
|
||||
hashes []common.Hash
|
||||
@@ -1864,18 +1866,18 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) error {
|
||||
// If the chain is terminating, stop iteration
|
||||
if bc.insertStopped() {
|
||||
log.Debug("Abort during blocks iteration")
|
||||
return errInsertionInterrupted
|
||||
return common.Hash{}, errInsertionInterrupted
|
||||
}
|
||||
}
|
||||
if parent == nil {
|
||||
return errors.New("missing parent")
|
||||
return common.Hash{}, errors.New("missing parent")
|
||||
}
|
||||
// Import all the pruned blocks to make the state available
|
||||
for i := len(hashes) - 1; i >= 0; i-- {
|
||||
// If the chain is terminating, stop processing blocks
|
||||
if bc.insertStopped() {
|
||||
log.Debug("Abort during blocks processing")
|
||||
return errInsertionInterrupted
|
||||
return common.Hash{}, errInsertionInterrupted
|
||||
}
|
||||
var b *types.Block
|
||||
if i == 0 {
|
||||
@@ -1884,10 +1886,10 @@ func (bc *BlockChain) recoverAncestors(block *types.Block) error {
|
||||
b = bc.GetBlock(hashes[i], numbers[i])
|
||||
}
|
||||
if _, err := bc.insertChain(types.Blocks{b}, false, false); err != nil {
|
||||
return err
|
||||
return b.ParentHash(), err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return block.Hash(), nil
|
||||
}
|
||||
|
||||
// collectLogs collects the logs that were generated or removed during
|
||||
@@ -2090,16 +2092,16 @@ func (bc *BlockChain) InsertBlockWithoutSetHead(block *types.Block) error {
|
||||
// SetCanonical rewinds the chain to set the new head block as the specified
|
||||
// block. It's possible that the state of the new head is missing, and it will
|
||||
// be recovered in this function as well.
|
||||
func (bc *BlockChain) SetCanonical(head *types.Block) error {
|
||||
func (bc *BlockChain) SetCanonical(head *types.Block) (common.Hash, error) {
|
||||
if !bc.chainmu.TryLock() {
|
||||
return errChainStopped
|
||||
return common.Hash{}, errChainStopped
|
||||
}
|
||||
defer bc.chainmu.Unlock()
|
||||
|
||||
// Re-execute the reorged chain in case the head state is missing.
|
||||
if !bc.HasState(head.Root()) {
|
||||
if err := bc.recoverAncestors(head); err != nil {
|
||||
return err
|
||||
if latestValidHash, err := bc.recoverAncestors(head); err != nil {
|
||||
return latestValidHash, err
|
||||
}
|
||||
log.Info("Recovered head state", "number", head.Number(), "hash", head.Hash())
|
||||
}
|
||||
@@ -2107,7 +2109,7 @@ func (bc *BlockChain) SetCanonical(head *types.Block) error {
|
||||
start := time.Now()
|
||||
if head.ParentHash() != bc.CurrentBlock().Hash() {
|
||||
if err := bc.reorg(bc.CurrentBlock(), head); err != nil {
|
||||
return err
|
||||
return common.Hash{}, err
|
||||
}
|
||||
}
|
||||
bc.writeHeadBlock(head)
|
||||
@@ -2130,7 +2132,7 @@ func (bc *BlockChain) SetCanonical(head *types.Block) error {
|
||||
context = append(context, []interface{}{"age", common.PrettyAge(timestamp)}...)
|
||||
}
|
||||
log.Info("Chain head was updated", context...)
|
||||
return nil
|
||||
return head.Hash(), nil
|
||||
}
|
||||
|
||||
func (bc *BlockChain) updateFutureBlocks() {
|
||||
|
||||
Reference in New Issue
Block a user