From da48b49785d5eb92c06ebe3f9b61c7c75eae0eac Mon Sep 17 00:00:00 2001 From: "fletcher.fan" Date: Thu, 30 Oct 2025 10:41:19 +0800 Subject: [PATCH] add emerald upgrade --- core/genesis.go | 4 ++++ core/state_processor_test.go | 1 + core/types/transaction_signing.go | 16 +++++++++++++++- core/vm/interpreter.go | 2 ++ core/vm/jump_table.go | 7 +++++++ core/vm/runtime/runtime.go | 1 + eth/gasprice/gasprice_test.go | 1 + genesis_l2.json | 5 ++++- params/config.go | 19 +++++++++++++++++-- params/forks/forks.go | 3 +++ 10 files changed, 55 insertions(+), 4 deletions(-) diff --git a/core/genesis.go b/core/genesis.go index f34627e8e..23d0025ab 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -148,6 +148,7 @@ func (e *GenesisMismatchError) Error() string { type ChainOverrides struct { Morph203Time *uint64 ViridianTime *uint64 + EmeraldTime *uint64 } // apply applies the chain overrides on the supplied chain config. @@ -161,6 +162,9 @@ func (o *ChainOverrides) apply(cfg *params.ChainConfig) error { if o.ViridianTime != nil { cfg.ViridianTime = o.ViridianTime } + if o.EmeraldTime != nil { + cfg.EmeraldTime = o.EmeraldTime + } return cfg.CheckConfigForkOrder() } diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 63e9ed773..707098d6b 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -60,6 +60,7 @@ func TestStateProcessorErrors(t *testing.T) { CurieBlock: big.NewInt(0), Morph203Time: new(uint64), ViridianTime: new(uint64), + EmeraldTime: new(uint64), Ethash: new(params.EthashConfig), } signer = types.LatestSigner(config) diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 452734b25..2f2b0f5bc 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -42,6 +42,8 @@ type sigCache struct { func MakeSigner(config *params.ChainConfig, blockNumber *big.Int, blockTime uint64) Signer { var signer Signer switch { + case config.IsEmerald(blockNumber, blockTime): + signer = NewEmeraldSigner(config.ChainID) case config.IsViridian(blockNumber, blockTime): signer = NewViridianSigner(config.ChainID) case config.IsCurie(blockNumber): @@ -71,6 +73,8 @@ func LatestSigner(config *params.ChainConfig) Signer { var signer Signer if config.ChainID != nil { switch { + case config.EmeraldTime != nil: + signer = NewEmeraldSigner(config.ChainID) case config.ViridianTime != nil: signer = NewViridianSigner(config.ChainID) case config.CurieBlock != nil: @@ -98,7 +102,7 @@ func LatestSigner(config *params.ChainConfig) Signer { func LatestSignerForChainID(chainID *big.Int) Signer { var signer Signer if chainID != nil { - signer = NewViridianSigner(chainID) + signer = NewEmeraldSigner(chainID) } else { signer = HomesteadSigner{} } @@ -224,6 +228,9 @@ func newModernSigner(chainID *big.Int, fork forks.Fork) Signer { if fork >= forks.Viridian { s.txtypes[SetCodeTxType] = struct{}{} } + if fork >= forks.Emerald { + // Future Emerald-specific transaction types can be added here + } return s } @@ -295,6 +302,13 @@ func NewViridianSigner(chainId *big.Int) Signer { return newModernSigner(chainId, forks.Viridian) } +// NewEmeraldSigner returns a signer that accepts +// - All Viridian transaction types +// - Future Emerald-specific transaction types +func NewEmeraldSigner(chainId *big.Int) Signer { + return newModernSigner(chainId, forks.Emerald) +} + // NewCurieSigner returns a signer that accepts // - EIP-4844 blob transactions // - EIP-1559 dynamic fee transactions diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 059089412..0f8781192 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -121,6 +121,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { if cfg.JumpTable[STOP] == nil { var jt JumpTable switch { + case evm.chainRules.IsEmerald: + jt = emeraldInstructionSet case evm.chainRules.IsViridian: jt = viridianInstructionSet case evm.chainRules.IsCurie: diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index e98fa95cc..670e02510 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -57,6 +57,7 @@ var ( shanghaiInstructionSet = newShanghaiInstructionSet() curieInstructionSet = newCurieInstructionSet() viridianInstructionSet = newViridianInstructionSet() + emeraldInstructionSet = newEmeraldInstructionSet() ) // JumpTable contains the EVM opcodes supported at a given fork. @@ -68,6 +69,12 @@ func newViridianInstructionSet() JumpTable { return instructionSet } +func newEmeraldInstructionSet() JumpTable { + instructionSet := newViridianInstructionSet() + // Emerald-specific changes can be added here in the future + return instructionSet +} + // newCurieInstructionSet returns the frontier, homestead, byzantium, // contantinople, istanbul, petersburg, berlin, london, shanghai, and curie instructions. func newCurieInstructionSet() JumpTable { diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index e932b9504..57774e30c 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -75,6 +75,7 @@ func setDefaults(cfg *Config) { CurieBlock: new(big.Int), Morph203Time: new(uint64), ViridianTime: new(uint64), + EmeraldTime: new(uint64), } } diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go index f38ff376c..5e19bad28 100644 --- a/eth/gasprice/gasprice_test.go +++ b/eth/gasprice/gasprice_test.go @@ -116,6 +116,7 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke config.CurieBlock = londonBlock config.Morph203Time = nil config.ViridianTime = nil + config.EmeraldTime = nil engine := ethash.NewFaker() db := rawdb.NewMemoryDatabase() genesis, err := gspec.Commit(db) diff --git a/genesis_l2.json b/genesis_l2.json index 5f0ee96c6..2d2fc4657 100644 --- a/genesis_l2.json +++ b/genesis_l2.json @@ -13,10 +13,13 @@ "berlinBlock": 0, "londonBlock": 0, "terminalTotalDifficulty": 0, - "archimedesBlock": 0, + "archimedesBlock": 0, "shanghaiBlock": 0, "bernoulliBlock": 0, "curieBlock": 0, + "morph203Time": 0, + "viridianTime": 0, + "emeraldTime": 0, "morph": { "useZktrie": true, "feeVaultAddress": "0x0e87cd091e091562F25CB1cf4641065dA2C049F5" diff --git a/params/config.go b/params/config.go index 138c7513a..a202e3018 100644 --- a/params/config.go +++ b/params/config.go @@ -385,6 +385,7 @@ var ( CurieBlock: big.NewInt(0), Morph203Time: new(uint64), ViridianTime: new(uint64), + EmeraldTime: new(uint64), TerminalTotalDifficulty: nil, Ethash: new(EthashConfig), Clique: nil, @@ -422,6 +423,7 @@ var ( CurieBlock: big.NewInt(0), Morph203Time: new(uint64), ViridianTime: new(uint64), + EmeraldTime: new(uint64), TerminalTotalDifficulty: nil, Ethash: nil, Clique: &CliqueConfig{Period: 0, Epoch: 30000}, @@ -454,6 +456,7 @@ var ( CurieBlock: big.NewInt(0), Morph203Time: new(uint64), ViridianTime: new(uint64), + EmeraldTime: new(uint64), TerminalTotalDifficulty: nil, Ethash: new(EthashConfig), Clique: nil, @@ -487,6 +490,7 @@ var ( CurieBlock: big.NewInt(0), Morph203Time: new(uint64), ViridianTime: new(uint64), + EmeraldTime: new(uint64), TerminalTotalDifficulty: nil, Ethash: new(EthashConfig), Clique: nil, @@ -579,6 +583,7 @@ type ChainConfig struct { CurieBlock *big.Int `json:"curieBlock,omitempty"` // Curie switch block (nil = no fork, 0 = already on curie) Morph203Time *uint64 `json:"morph203Time,omitempty"` // Morph203Time switch time (nil = no fork, 0 = already on morph203) ViridianTime *uint64 `json:"viridianTime,omitempty"` // ViridianTime switch time (nil = no fork, 0 = already on viridian) + EmeraldTime *uint64 `json:"emeraldTime,omitempty"` // EmeraldTime switch time (nil = no fork, 0 = already on emerald) // TerminalTotalDifficulty is the amount of total difficulty reached by // the network that triggers the consensus upgrade. @@ -671,7 +676,7 @@ func (c *ChainConfig) String() string { default: engine = "unknown" } - return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Archimedes: %v, Shanghai: %v, Bernoulli: %v, Curie: %v, Morph203: %v, Viridian: %v, Engine: %v, Morph config: %v}", + return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Berlin: %v, London: %v, Arrow Glacier: %v, Archimedes: %v, Shanghai: %v, Bernoulli: %v, Curie: %v, Morph203: %v, Viridian: %v, Emerald: %v, Engine: %v, Morph config: %v}", c.ChainID, c.HomesteadBlock, c.DAOForkBlock, @@ -693,6 +698,7 @@ func (c *ChainConfig) String() string { c.CurieBlock, c.Morph203Time, c.ViridianTime, + c.EmeraldTime, engine, c.Morph, ) @@ -794,6 +800,10 @@ func (c *ChainConfig) IsViridian(num *big.Int, time uint64) bool { return c.IsCurie(num) && isTimestampForked(c.ViridianTime, time) } +func (c *ChainConfig) IsEmerald(num *big.Int, time uint64) bool { + return isTimestampForked(c.EmeraldTime, time) +} + // IsTerminalPoWBlock returns whether the given block is the last block of PoW stage. func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *big.Int) bool { if c.TerminalTotalDifficulty == nil { @@ -857,6 +867,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error { {name: "curieBlock", block: c.CurieBlock, optional: true}, {name: "morph203Time", timestamp: c.Morph203Time, optional: true}, {name: "viridianTime", timestamp: c.ViridianTime, optional: true}, + {name: "emeraldTime", timestamp: c.EmeraldTime, optional: true}, } { if lastFork.name != "" { switch { @@ -963,6 +974,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int, headTi if isForkTimestampIncompatible(c.ViridianTime, newcfg.ViridianTime, headTimestamp) { return newTimestampCompatError("ViridianTime fork timestamp", c.ViridianTime, newcfg.ViridianTime) } + if isForkTimestampIncompatible(c.EmeraldTime, newcfg.EmeraldTime, headTimestamp) { + return newTimestampCompatError("EmeraldTime fork timestamp", c.EmeraldTime, newcfg.EmeraldTime) + } return nil } @@ -1109,7 +1123,7 @@ type Rules struct { IsHomestead, IsEIP150, IsEIP155, IsEIP158 bool IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool IsBerlin, IsLondon, IsArchimedes, IsShanghai bool - IsBernoulli, IsCurie, IsMorph203, IsViridian bool + IsBernoulli, IsCurie, IsMorph203, IsViridian, IsEmerald bool } // Rules ensures c's ChainID is not nil. @@ -1136,5 +1150,6 @@ func (c *ChainConfig) Rules(num *big.Int, time uint64) Rules { IsCurie: c.IsCurie(num), IsMorph203: c.IsMorph203(time), IsViridian: c.IsViridian(num, time), + IsEmerald: c.IsEmerald(num, time), } } diff --git a/params/forks/forks.go b/params/forks/forks.go index 2ba223685..c0759fdbc 100644 --- a/params/forks/forks.go +++ b/params/forks/forks.go @@ -40,6 +40,7 @@ const ( Curie Morph203 Viridian + Emerald ) // String implements fmt.Stringer. @@ -71,4 +72,6 @@ var forkToString = map[Fork]string{ Bernoulli: "Bernoulli", Curie: "Curie", Morph203: "Morph203", + Viridian: "Viridian", + Emerald: "Emerald", }