Skip to content

Commit 4074f74

Browse files
authored
internal/ethapi: fix merge transition in eth_simulate (#32616)
This PR fixes the fork detection of `eth_simulateV1`, particularly for networks that are post-merge since genesis, like Hoodi.
1 parent 1cd0048 commit 4074f74

File tree

3 files changed

+23
-15
lines changed

3 files changed

+23
-15
lines changed

consensus/beacon/consensus.go

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,6 @@ func New(ethone consensus.Engine) *Beacon {
7171
return &Beacon{ethone: ethone}
7272
}
7373

74-
// isPostMerge reports whether the given block number is assumed to be post-merge.
75-
// Here we check the MergeNetsplitBlock to allow configuring networks with a PoW or
76-
// PoA chain for unit testing purposes.
77-
func isPostMerge(config *params.ChainConfig, blockNum uint64, timestamp uint64) bool {
78-
mergedAtGenesis := config.TerminalTotalDifficulty != nil && config.TerminalTotalDifficulty.Sign() == 0
79-
return mergedAtGenesis ||
80-
config.MergeNetsplitBlock != nil && blockNum >= config.MergeNetsplitBlock.Uint64() ||
81-
config.ShanghaiTime != nil && timestamp >= *config.ShanghaiTime
82-
}
83-
8474
// Author implements consensus.Engine, returning the verified author of the block.
8575
func (beacon *Beacon) Author(header *types.Header) (common.Address, error) {
8676
if !beacon.IsPoSHeader(header) {
@@ -328,7 +318,7 @@ func (beacon *Beacon) verifyHeaders(chain consensus.ChainHeaderReader, headers [
328318
// Prepare implements consensus.Engine, initializing the difficulty field of a
329319
// header to conform to the beacon protocol. The changes are done inline.
330320
func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
331-
if !isPostMerge(chain.Config(), header.Number.Uint64(), header.Time) {
321+
if !chain.Config().IsPostMerge(header.Number.Uint64(), header.Time) {
332322
return beacon.ethone.Prepare(chain, header)
333323
}
334324
header.Difficulty = beaconDifficulty
@@ -442,7 +432,7 @@ func (beacon *Beacon) SealHash(header *types.Header) common.Hash {
442432
// the difficulty that a new block should have when created at time
443433
// given the parent block's time and difficulty.
444434
func (beacon *Beacon) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int {
445-
if !isPostMerge(chain.Config(), parent.Number.Uint64()+1, time) {
435+
if !chain.Config().IsPostMerge(parent.Number.Uint64()+1, time) {
446436
return beacon.ethone.CalcDifficulty(chain, time, parent)
447437
}
448438
return beaconDifficulty

internal/ethapi/simulate.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -474,22 +474,30 @@ func (sim *simulator) makeHeaders(blocks []simBlock) ([]*types.Header, error) {
474474
overrides := block.BlockOverrides
475475

476476
var withdrawalsHash *common.Hash
477-
if sim.chainConfig.IsShanghai(overrides.Number.ToInt(), (uint64)(*overrides.Time)) {
477+
number := overrides.Number.ToInt()
478+
timestamp := (uint64)(*overrides.Time)
479+
if sim.chainConfig.IsShanghai(number, timestamp) {
478480
withdrawalsHash = &types.EmptyWithdrawalsHash
479481
}
480482
var parentBeaconRoot *common.Hash
481-
if sim.chainConfig.IsCancun(overrides.Number.ToInt(), (uint64)(*overrides.Time)) {
483+
if sim.chainConfig.IsCancun(number, timestamp) {
482484
parentBeaconRoot = &common.Hash{}
483485
if overrides.BeaconRoot != nil {
484486
parentBeaconRoot = overrides.BeaconRoot
485487
}
486488
}
489+
// Set difficulty to zero if the given block is post-merge. Without this, all post-merge hardforks would remain inactive.
490+
// For example, calling eth_simulateV1(..., blockParameter: 0x0) on hoodi network will cause all blocks to have a difficulty of 1 and be treated as pre-merge.
491+
difficulty := header.Difficulty
492+
if sim.chainConfig.IsPostMerge(number.Uint64(), timestamp) {
493+
difficulty = big.NewInt(0)
494+
}
487495
header = overrides.MakeHeader(&types.Header{
488496
UncleHash: types.EmptyUncleHash,
489497
ReceiptHash: types.EmptyReceiptsHash,
490498
TxHash: types.EmptyTxsHash,
491499
Coinbase: header.Coinbase,
492-
Difficulty: header.Difficulty,
500+
Difficulty: difficulty,
493501
GasLimit: header.GasLimit,
494502
WithdrawalsHash: withdrawalsHash,
495503
ParentBeaconRoot: parentBeaconRoot,

params/config.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,16 @@ func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *bi
678678
return parentTotalDiff.Cmp(c.TerminalTotalDifficulty) < 0 && totalDiff.Cmp(c.TerminalTotalDifficulty) >= 0
679679
}
680680

681+
// IsPostMerge reports whether the given block number is assumed to be post-merge.
682+
// Here we check the MergeNetsplitBlock to allow configuring networks with a PoW or
683+
// PoA chain for unit testing purposes.
684+
func (c *ChainConfig) IsPostMerge(blockNum uint64, timestamp uint64) bool {
685+
mergedAtGenesis := c.TerminalTotalDifficulty != nil && c.TerminalTotalDifficulty.Sign() == 0
686+
return mergedAtGenesis ||
687+
c.MergeNetsplitBlock != nil && blockNum >= c.MergeNetsplitBlock.Uint64() ||
688+
c.ShanghaiTime != nil && timestamp >= *c.ShanghaiTime
689+
}
690+
681691
// IsShanghai returns whether time is either equal to the Shanghai fork time or greater.
682692
func (c *ChainConfig) IsShanghai(num *big.Int, time uint64) bool {
683693
return c.IsLondon(num) && isTimestampForked(c.ShanghaiTime, time)

0 commit comments

Comments
 (0)