Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
91c6a04
core,miner,parms: DA footprint block limit (constant gas scalar) (#655)
sebastianst Oct 14, 2025
ded9c88
all: Make DA footprint gas scalar configurable (#675)
joshklop Oct 14, 2025
5c6d276
core/types: implement operator fee fix (Jovian) (#696)
geoknee Oct 16, 2025
e061c29
consensus/beacon: Fix OP Legacy header verification dispatch (#697)
sebastianst Oct 16, 2025
6658a36
all: Store DA footprint in blob gas used header field (#694)
sebastianst Oct 17, 2025
f31eb35
all: update c-kzg-4844 to 2.1.5 (#702)
joshklop Oct 22, 2025
f305011
superchain: update scr import to include worldchain-sepolia isthmus t…
bitwiseguy Oct 22, 2025
6706f93
core: add gauge metrics + histograms for block gas used and blob gas …
geoknee Oct 24, 2025
96738d2
superchain: update scr import to include jovian activation timestamp …
bitwiseguy Oct 24, 2025
a19e6a1
Add new precompile limits for Jovian (#709)
pauldowman Oct 27, 2025
0a1c7b4
superchain: Update for new Jovian timestamps (#712)
sebastianst Oct 28, 2025
4fd8b05
core/types: Populate Jovian receipt fields (#710)
sebastianst Oct 28, 2025
37ffc0c
core/txpool/blobpool: migrate billy to new slot size (#31966)
MariusVanDerWijden Sep 15, 2025
3e7dd84
params: set osaka and BPO1 & BPO2 mainnet dates (#33063)
MariusVanDerWijden Nov 3, 2025
67232ee
Merge pull request #715 from ethereum-optimism/joshklop/fusaka-mainnet
sebastianst Nov 3, 2025
9a4dd63
superchain: update for new Jovian timestamps (#716)
joshklop Nov 3, 2025
aa94053
triedb/pathdb: sync ancient store before journal (#32557) (#718)
joshklop Nov 5, 2025
dd5e096
Merge commit 'aa94053' into merge_upstream
blockchaindevsh Nov 11, 2025
0f7e8b6
fix BlockValidator.ValidateBody
blockchaindevsh Nov 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ func (beacon *Beacon) VerifyHeader(chain consensus.ChainHeaderReader, header *ty
// Check >0 TDs with pre-merge, --0 TDs with post-merge rules
if header.Difficulty.Sign() > 0 ||
// OP-Stack: transitioned networks must use legacy consensus pre-Bedrock
cfg.IsOptimismBedrock(header.Number) {
cfg.IsOptimismPreBedrock(header.Number) {
return beacon.ethone.VerifyHeader(chain, header)
}
return beacon.verifyHeader(chain, header, parent)
Expand Down Expand Up @@ -410,6 +410,16 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea
}
}

// Store DA footprint in BlobGasUsed header field if it hasn't already been set yet.
// Builder code may already calculate it during block building to avoid recalculating it here.
if chain.Config().IsDAFootprintBlockLimit(header.Time) && (header.BlobGasUsed == nil || *header.BlobGasUsed == 0) {
daFootprint, err := types.CalcDAFootprint(body.Transactions)
if err != nil {
return nil, fmt.Errorf("error calculating DA footprint: %w", err)
}
header.BlobGasUsed = &daFootprint
}

// Assemble the final block.
block := types.NewBlock(header, body, receipts, trie.NewStackTrie(nil), chain.Config())

Expand Down
26 changes: 18 additions & 8 deletions consensus/misc/eip1559/eip1559.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade
if !config.IsLondon(parent.Number) {
parentGasLimit = parent.GasLimit * config.ElasticityMultiplier()
}
if config.Optimism == nil { // gasLimit can adjust instantly in optimism
if !config.IsOptimism() { // OP Stack gasLimit can adjust instantly
if err := misc.VerifyGaslimit(parentGasLimit, header.GasLimit); err != nil {
return err
}
Expand Down Expand Up @@ -75,7 +75,7 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header, time uint64)
}

// OPStack addition: calculate the base fee using the upstream code.
baseFee := calcBaseFeeInner(parent, elasticity, denominator)
baseFee := calcBaseFeeInner(config, parent, elasticity, denominator)

// OPStack addition: enforce minimum base fee.
// If the minimum base fee is 0, this has no effect.
Expand All @@ -89,10 +89,20 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header, time uint64)
return baseFee
}

func calcBaseFeeInner(parent *types.Header, elasticity uint64, denominator uint64) *big.Int {
func calcBaseFeeInner(config *params.ChainConfig, parent *types.Header, elasticity uint64, denominator uint64) *big.Int {
parentGasTarget := parent.GasLimit / elasticity
// If the parent gasUsed is the same as the target, the baseFee remains unchanged.
if parent.GasUsed == parentGasTarget {
parentGasMetered := parent.GasUsed
if config.IsDAFootprintBlockLimit(parent.Time) {
if parent.BlobGasUsed == nil {
panic("Jovian parent block has nil BlobGasUsed")
} else if *parent.BlobGasUsed > parent.GasUsed {
// Jovian updates the base fee based on the maximum of total transactions gas used and total DA footprint (which is
// stored in the BlobGasUsed field of the header).
parentGasMetered = *parent.BlobGasUsed
}
}
// If the parent gasMetered is the same as the target, the baseFee remains unchanged.
if parentGasMetered == parentGasTarget {
return new(big.Int).Set(parent.BaseFee)
}

Expand All @@ -101,10 +111,10 @@ func calcBaseFeeInner(parent *types.Header, elasticity uint64, denominator uint6
denom = new(big.Int)
)

if parent.GasUsed > parentGasTarget {
if parentGasMetered > parentGasTarget {
// If the parent block used more gas than its target, the baseFee should increase.
// max(1, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
num.SetUint64(parent.GasUsed - parentGasTarget)
num.SetUint64(parentGasMetered - parentGasTarget)
num.Mul(num, parent.BaseFee)
num.Div(num, denom.SetUint64(parentGasTarget))
num.Div(num, denom.SetUint64(denominator))
Expand All @@ -115,7 +125,7 @@ func calcBaseFeeInner(parent *types.Header, elasticity uint64, denominator uint6
} else {
// Otherwise if the parent block used less gas than its target, the baseFee should decrease.
// max(0, parentBaseFee * gasUsedDelta / parentGasTarget / baseFeeChangeDenominator)
num.SetUint64(parentGasTarget - parent.GasUsed)
num.SetUint64(parentGasTarget - parentGasMetered)
num.Mul(num, parent.BaseFee)
num.Div(num, denom.SetUint64(parentGasTarget))
num.Div(num, denom.SetUint64(denominator))
Expand Down
69 changes: 43 additions & 26 deletions consensus/misc/eip1559/eip1559_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,19 @@ func config() *params.ChainConfig {
return config
}

var TestCanyonTime = uint64(10)
var TestHoloceneTime = uint64(12)
var TestJovianTime = uint64(14)
var (
testCanyonTime = uint64(10)
testHoloceneTime = uint64(12)
testJovianTime = uint64(14)
)

func opConfig() *params.ChainConfig {
config := copyConfig(params.TestChainConfig)
config.LondonBlock = big.NewInt(5)
eip1559DenominatorCanyon := uint64(250)
config.CanyonTime = &TestCanyonTime
config.HoloceneTime = &TestHoloceneTime
config.JovianTime = &TestJovianTime
config.CanyonTime = &testCanyonTime
config.HoloceneTime = &testHoloceneTime
config.JovianTime = &testJovianTime
config.Optimism = &params.OptimismConfig{
EIP1559Elasticity: 6,
EIP1559Denominator: 50,
Expand Down Expand Up @@ -227,59 +229,74 @@ func TestCalcBaseFeeOptimismHolocene(t *testing.T) {
// TestCalcBaseFeeJovian tests that the minimum base fee is enforced
// when the computed base fee is less than the minimum base fee,
// if the feature is active and not enforced otherwise.
// It also tests that the base fee udpate will take the DA footprint as stored
// in the blob gas used field into account if it is larger than the gas used
// field.
func TestCalcBaseFeeJovian(t *testing.T) {
parentGasLimit := uint64(30_000_000)
denom := uint64(50)
elasticity := uint64(3)
parentGasTarget := parentGasLimit / elasticity
const zeroParentBlobGasUsed = 0

preJovian := TestJovianTime - 1
postJovian := TestJovianTime
preJovian := testJovianTime - 1
postJovian := testJovianTime

tests := []struct {
parentBaseFee int64
parentGasUsed uint64
parentTime uint64
minBaseFee uint64
expectedBaseFee uint64
parentBaseFee int64
parentGasUsed uint64
parentBlobGasUsed uint64
parentTime uint64
minBaseFee uint64
expectedBaseFee uint64
}{
// Test 0: gas used is below target, and the new calculated base fee is very low.
// But since we are pre Jovian, we don't enforce the minBaseFee.
{1, parentGasLimit/elasticity - 1_000_000, preJovian, 1e9, 1},
{1, parentGasTarget - 1_000_000, zeroParentBlobGasUsed, preJovian, 1e9, 1},
// Test 1: gas used is exactly the target gas, but the base fee is set too low so
// the base fee is expected to be the minBaseFee
{1, parentGasLimit / elasticity, postJovian, 1e9, 1e9},
{1, parentGasTarget, zeroParentBlobGasUsed, postJovian, 1e9, 1e9},
// Test 2: gas used exceeds gas target, but the new calculated base fee is still
// too low so the base fee is expected to be the minBaseFee
{1, parentGasLimit/elasticity + 1_000_000, postJovian, 1e9, 1e9},
{1, parentGasTarget + 1_000_000, zeroParentBlobGasUsed, postJovian, 1e9, 1e9},
// Test 3: gas used exceeds gas target, but the new calculated base fee is higher
// than the minBaseFee, so don't enforce minBaseFee. See the calculation below:
// gasUsedDelta = gasUsed - parentGasTarget = 20_000_000 - 30_000_000 / 3 = 10_000_000
// 2e9 * 10_000_000 / 10_000_000 / 50 = 40_000_000
// 2e9 + 40_000_000 = 2_040_000_000, which is greater than minBaseFee
{2e9, parentGasLimit/elasticity + 10_000_000, postJovian, 1e9, 2_040_000_000},
{2e9, parentGasTarget + 10_000_000, zeroParentBlobGasUsed, postJovian, 1e9, 2_040_000_000},
// Test 4: gas used is below target, but the new calculated base fee is still
// too low so the base fee is expected to be the minBaseFee
{1, parentGasLimit/elasticity - 1_000_000, postJovian, 1e9, 1e9},
{1, parentGasTarget - 1_000_000, zeroParentBlobGasUsed, postJovian, 1e9, 1e9},
// Test 5: gas used is below target, and the new calculated base fee is higher
// than the minBaseFee, so don't enforce minBaseFee. See the calculation below:
// gasUsedDelta = gasUsed - parentGasTarget = 9_000_000 - 30_000_000 / 3 = -1_000_000
// 2_097_152 * -1_000_000 / 10_000_000 / 50 = -4194.304
// 2_097_152 - 4194.304 = 2_092_957.696, which is greater than minBaseFee
{2_097_152, parentGasLimit/elasticity - 1_000_000, postJovian, 2e6, 2_092_958},
{2_097_152, parentGasTarget - 1_000_000, zeroParentBlobGasUsed, postJovian, 2e6, 2_092_958},
// Test 6: parent base fee already at minimum, below target => no change
{1e4, parentGasLimit/elasticity - 1, postJovian, 1e4, 1e4},
{1e4, parentGasTarget - 1, zeroParentBlobGasUsed, postJovian, 1e4, 1e4},
// Test 7: parent base fee already at minimum, above target => small increase as usual
{1e4, parentGasLimit/elasticity + 1, postJovian, 1e4, 1e4 + 1},
{1e4, parentGasTarget + 1, zeroParentBlobGasUsed, postJovian, 1e4, 1e4 + 1},

// Test 8: Pre-Jovian: parent base fee already at minimum, gas used at target, blob gas used at limit
// => no increase, minBaseFee ignored, high blob gas used ignored
{1e4, parentGasTarget, parentGasLimit, preJovian, 1e6, 1e4},
// Test 9: parent base fee already at minimum, gas used at target, da footprint above target => small increase
{1e4, parentGasTarget, parentGasTarget + 1, postJovian, 1e4, 1e4 + 1},
// Test 10: Test 3, but with high blob gas used instead of gas used
{2e9, parentGasTarget, parentGasTarget + 10_000_000, postJovian, 1e9, 2_040_000_000},
}
for i, test := range tests {
testName := fmt.Sprintf("test %d", i)
t.Run(testName, func(t *testing.T) {
parent := &types.Header{
Number: common.Big32,
GasLimit: parentGasLimit,
GasUsed: test.parentGasUsed,
BaseFee: big.NewInt(test.parentBaseFee),
Time: test.parentTime,
Number: common.Big32,
GasLimit: parentGasLimit,
GasUsed: test.parentGasUsed,
BlobGasUsed: &test.parentBlobGasUsed,
BaseFee: big.NewInt(test.parentBaseFee),
Time: test.parentTime,
}
parent.Extra = EncodeOptimismExtraData(opConfig(), test.parentTime, denom, elasticity, &test.minBaseFee)
have, want := CalcBaseFee(opConfig(), parent, parent.Time+2), big.NewInt(int64(test.expectedBaseFee))
Expand Down
16 changes: 10 additions & 6 deletions consensus/misc/eip4844/eip4844.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,16 @@ func VerifyEIP4844Header(config *params.ChainConfig, parent, header *types.Heade
return errors.New("header is missing blobGasUsed")
}

// Verify that the blob gas used remains within reasonable limits.
if !config.IsOptimism() && *header.BlobGasUsed > bcfg.maxBlobGas() {
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, bcfg.maxBlobGas())
}
if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 {
return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob)
// OP Stack sets a zero blobGasUsed pre-Jovian. Post-Jovian, it stores the DA footprint, which is
// probably not a multiple of [params.BlobTxBlobGasPerBlob].
if !config.IsOptimism() {
// Verify that the blob gas used remains within reasonable limits.
if *header.BlobGasUsed > bcfg.maxBlobGas() {
return fmt.Errorf("blob gas used %d exceeds maximum allowance %d", *header.BlobGasUsed, bcfg.maxBlobGas())
}
if *header.BlobGasUsed%params.BlobTxBlobGasPerBlob != 0 {
return fmt.Errorf("blob gas used %d not a multiple of blob gas per blob %d", header.BlobGasUsed, params.BlobTxBlobGasPerBlob)
}
}

// Verify the excessBlobGas is correct based on the parent header
Expand Down
19 changes: 18 additions & 1 deletion core/block_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
}

// Check blob gas usage.
if header.BlobGasUsed != nil {
if (!v.config.IsOptimism() || v.config.IsL2Blob(header.Number, header.Time)) && header.BlobGasUsed != nil {
if want := *header.BlobGasUsed / params.BlobTxBlobGasPerBlob; uint64(blobs) != want { // div because the header is surely good vs the body might be bloated
return fmt.Errorf("blob gas used mismatch (header %v, calculated %v)", *header.BlobGasUsed, blobs*params.BlobTxBlobGasPerBlob)
}
Expand All @@ -116,6 +116,23 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
}
}

// OP Stack Jovian DA footprint block limit.
if v.config.IsDAFootprintBlockLimit(header.Time) {
if header.BlobGasUsed == nil {
return errors.New("nil blob gas used in post-Jovian block header, should store DA footprint")
}
blobGasUsed := *header.BlobGasUsed
daFootprint, err := types.CalcDAFootprint(block.Transactions())
if err != nil {
return fmt.Errorf("failed to calculate DA footprint: %w", err)
} else if blobGasUsed != daFootprint {
return fmt.Errorf("invalid DA footprint in blobGasUsed field (remote: %d local: %d)", blobGasUsed, daFootprint)
}
if daFootprint > block.GasLimit() {
return fmt.Errorf("DA footprint %d exceeds block gas limit %d", daFootprint, block.GasLimit())
}
}

// Ancestor block must be known.
if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) {
if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) {
Expand Down
13 changes: 9 additions & 4 deletions core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ var (
headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil)
headFinalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)
headSafeBlockGauge = metrics.NewRegisteredGauge("chain/head/safe", nil)
headBaseFeeGauge = metrics.NewRegisteredGauge("chain/head/basefee", nil)

chainInfoGauge = metrics.NewRegisteredGaugeInfo("chain/info", nil)
chainMgaspsMeter = metrics.NewRegisteredResettingTimer("chain/mgasps", nil)
Expand Down Expand Up @@ -1230,7 +1229,9 @@ func (bc *BlockChain) writeHeadBlock(block *types.Block) {

bc.currentBlock.Store(block.Header())
headBlockGauge.Update(int64(block.NumberU64()))
headBaseFeeGauge.TryUpdate(block.Header().BaseFee)

// OPStack addition
updateOptimismBlockMetrics(block.Header())
}

// stopWithoutSaving stops the blockchain service. If any imports are currently in progress
Expand Down Expand Up @@ -1398,7 +1399,9 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
bc.currentSnapBlock.Store(header)
headHeaderGauge.Update(header.Number.Int64())
headFastBlockGauge.Update(header.Number.Int64())
headBaseFeeGauge.TryUpdate(header.BaseFee)

// OPStack addition
updateOptimismBlockMetrics(header)
return nil
}
// writeAncient writes blockchain and corresponding receipt chain into ancient store.
Expand Down Expand Up @@ -2771,7 +2774,9 @@ func (bc *BlockChain) InsertHeadersBeforeCutoff(headers []*types.Header) (int, e
bc.currentSnapBlock.Store(last)
headHeaderGauge.Update(last.Number.Int64())
headFastBlockGauge.Update(last.Number.Int64())
headBaseFeeGauge.TryUpdate(last.BaseFee)

// OPStack addition
updateOptimismBlockMetrics(last)
return 0, nil
}

Expand Down
27 changes: 27 additions & 0 deletions core/blockchain_optimism.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package core

import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/metrics"
)

// OPStack additions
var (
headBaseFeeGauge = metrics.NewRegisteredGauge("chain/head/basefee", nil)
headGasUsedGauge = metrics.NewRegisteredGauge("chain/head/gas_used", nil)
headBlobGasUsedGauge = metrics.NewRegisteredGauge("chain/head/blob_gas_used", nil)

headGasUsedHist = metrics.NewRegisteredHistogram("chain/head/gas_used_hist", nil, metrics.NewExpDecaySample(1028, 0.015))
headBlobGasUsedHist = metrics.NewRegisteredHistogram("chain/head/blob_gas_used_hist", nil, metrics.NewExpDecaySample(1028, 0.015))
)

func updateOptimismBlockMetrics(header *types.Header) error {
headBaseFeeGauge.TryUpdate(header.BaseFee)
headGasUsedGauge.Update(int64(header.GasUsed))
headBlobGasUsedGauge.TryUpdateUint64(header.BlobGasUsed)
headGasUsedHist.Update(int64(header.GasUsed))
if header.BlobGasUsed != nil {
headBlobGasUsedHist.Update(int64(*header.BlobGasUsed))
}
return nil
}
19 changes: 14 additions & 5 deletions core/forkid/forkid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,16 @@ func TestCreation(t *testing.T) {
{20000000, 1681338454, ID{Hash: checksumToBytes(0xf0afd0e3), Next: 1681338455}}, // Last Gray Glacier block
{20000000, 1681338455, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}}, // First Shanghai block
{30000000, 1710338134, ID{Hash: checksumToBytes(0xdce96c2d), Next: 1710338135}}, // Last Shanghai block
{40000000, 1710338135, ID{Hash: checksumToBytes(0x9f3d2254), Next: 1746612311}}, // First Cancun block
{30000000, 1710338135, ID{Hash: checksumToBytes(0x9f3d2254), Next: 1746612311}}, // First Cancun block
{30000000, 1746022486, ID{Hash: checksumToBytes(0x9f3d2254), Next: 1746612311}}, // Last Cancun block
{30000000, 1746612311, ID{Hash: checksumToBytes(0xc376cf8b), Next: 0}}, // First Prague block
{50000000, 2000000000, ID{Hash: checksumToBytes(0xc376cf8b), Next: 0}}, // Future Prague block
{30000000, 1746612311, ID{Hash: checksumToBytes(0xc376cf8b), Next: 1764798551}}, // First Prague block
{30000000, 1764798550, ID{Hash: checksumToBytes(0xc376cf8b), Next: 1764798551}}, // Last Prague block
{30000000, 1764798551, ID{Hash: checksumToBytes(0x5167e2a6), Next: 1765290071}}, // First Osaka block
{30000000, 1765290070, ID{Hash: checksumToBytes(0x5167e2a6), Next: 1765290071}}, // Last Osaka block
{30000000, 1765290071, ID{Hash: checksumToBytes(0xcba2a1c0), Next: 1767747671}}, // First BPO1 block
{30000000, 1767747670, ID{Hash: checksumToBytes(0xcba2a1c0), Next: 1767747671}}, // Last BPO1 block
{30000000, 1767747671, ID{Hash: checksumToBytes(0x07c9462e), Next: 0}}, // First BPO2 block
{50000000, 2000000000, ID{Hash: checksumToBytes(0x07c9462e), Next: 0}}, // Future BPO2 block
},
},
// Sepolia test cases
Expand Down Expand Up @@ -162,6 +168,9 @@ func TestValidation(t *testing.T) {
legacyConfig.ShanghaiTime = nil
legacyConfig.CancunTime = nil
legacyConfig.PragueTime = nil
legacyConfig.OsakaTime = nil
legacyConfig.BPO1Time = nil
legacyConfig.BPO2Time = nil

tests := []struct {
config *params.ChainConfig
Expand Down Expand Up @@ -361,11 +370,11 @@ func TestValidation(t *testing.T) {
// Local is mainnet Shanghai, remote is random Shanghai.
{params.MainnetChainConfig, 20000000, 1681338455, ID{Hash: checksumToBytes(0x12345678), Next: 0}, ErrLocalIncompatibleOrStale},

// Local is mainnet Prague, far in the future. Remote announces Gopherium (non existing fork)
// Local is mainnet BPO2, far in the future. Remote announces Gopherium (non existing fork)
// at some future timestamp 8888888888, for itself, but past block for local. Local is incompatible.
//
// This case detects non-upgraded nodes with majority hash power (typical Ropsten mess).
{params.MainnetChainConfig, 88888888, 8888888888, ID{Hash: checksumToBytes(0xc376cf8b), Next: 8888888888}, ErrLocalIncompatibleOrStale},
{params.MainnetChainConfig, 88888888, 8888888888, ID{Hash: checksumToBytes(0x07c9462e), Next: 8888888888}, ErrLocalIncompatibleOrStale},

// Local is mainnet Shanghai. Remote is also in Shanghai, but announces Gopherium (non existing
// fork) at timestamp 1668000000, before Cancun. Local is incompatible.
Expand Down
Loading
Loading