From 79427857e5024df45f8102ca0c14dca3102b169a Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 21 Apr 2023 00:08:59 +0530 Subject: [PATCH 1/5] Set IsShanghai true if the ArbOS version is >= 11 --- core/evm.go | 22 ++++++++++++---------- core/state_transition.go | 2 +- core/vm/evm.go | 7 +++++-- core/vm/runtime/runtime.go | 6 +++--- eth/tracers/js/goja.go | 2 +- eth/tracers/native/4byte.go | 2 +- internal/ethapi/api.go | 6 +++++- params/config.go | 6 +++--- params/config_test.go | 15 +++++++++------ tests/state_test.go | 2 +- 10 files changed, 41 insertions(+), 29 deletions(-) diff --git a/core/evm.go b/core/evm.go index 35e12338ef05..804b4c022fc8 100644 --- a/core/evm.go +++ b/core/evm.go @@ -55,17 +55,19 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common if header.Difficulty.Cmp(common.Big0) == 0 { random = &header.MixDigest } + headerInfo, _ := types.DeserializeHeaderExtraInformation(header) return vm.BlockContext{ - CanTransfer: CanTransfer, - Transfer: Transfer, - GetHash: GetHashFn(header, chain), - Coinbase: beneficiary, - BlockNumber: new(big.Int).Set(header.Number), - Time: header.Time, - Difficulty: new(big.Int).Set(header.Difficulty), - BaseFee: baseFee, - GasLimit: header.GasLimit, - Random: random, + CanTransfer: CanTransfer, + Transfer: Transfer, + GetHash: GetHashFn(header, chain), + Coinbase: beneficiary, + BlockNumber: new(big.Int).Set(header.Number), + Time: header.Time, + Difficulty: new(big.Int).Set(header.Difficulty), + BaseFee: baseFee, + GasLimit: header.GasLimit, + Random: random, + ArbOSVersion: headerInfo.ArbOSFormatVersion, } } diff --git a/core/state_transition.go b/core/state_transition.go index af5ad4ac45b4..d98f205ac881 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -351,7 +351,7 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) { var ( msg = st.msg sender = vm.AccountRef(msg.From()) - rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil, st.evm.Context.Time) + rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil, st.evm.Context.Time, st.evm.Context.ArbOSVersion) contractCreation = msg.To() == nil ) diff --git a/core/vm/evm.go b/core/vm/evm.go index 5f6fece400b3..4a2e00ef2332 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -78,6 +78,9 @@ type BlockContext struct { Difficulty *big.Int // Provides information for DIFFICULTY BaseFee *big.Int // Provides information for BASEFEE Random *common.Hash // Provides information for PREVRANDAO + + // Arbitrum information + ArbOSVersion uint64 } // TxContext provides the EVM with information about a transaction. @@ -136,7 +139,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig StateDB: statedb, Config: config, chainConfig: chainConfig, - chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), + chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time, blockCtx.ArbOSVersion), } evm.ProcessingHook = DefaultTxProcessor{evm: evm} evm.interpreter = NewEVMInterpreter(evm) @@ -171,7 +174,7 @@ func (evm *EVM) SetBlockContext(blockCtx BlockContext) { evm.Context = blockCtx num := blockCtx.BlockNumber timestamp := blockCtx.Time - evm.chainRules = evm.chainConfig.Rules(num, blockCtx.Random != nil, timestamp) + evm.chainRules = evm.chainConfig.Rules(num, blockCtx.Random != nil, timestamp, blockCtx.ArbOSVersion) } // Call executes the contract associated with the addr with the given input as diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 56ff5eeabe33..1544ed649dc9 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -113,7 +113,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { address = common.BytesToAddress([]byte("contract")) vmenv = NewEnv(cfg) sender = vm.AccountRef(cfg.Origin) - rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) + rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time, vmenv.Context.ArbOSVersion) ) // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin) @@ -146,7 +146,7 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { var ( vmenv = NewEnv(cfg) sender = vm.AccountRef(cfg.Origin) - rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) + rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time, vmenv.Context.ArbOSVersion) ) // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin) @@ -174,7 +174,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er vmenv = NewEnv(cfg) sender = cfg.State.GetOrNewStateObject(cfg.Origin) statedb = cfg.State - rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time) + rules = cfg.ChainConfig.Rules(vmenv.Context.BlockNumber, vmenv.Context.Random != nil, vmenv.Context.Time, vmenv.Context.ArbOSVersion) ) // Execute the preparatory steps for state transition which includes: // - prepare accessList(post-berlin) diff --git a/eth/tracers/js/goja.go b/eth/tracers/js/goja.go index 9b72341bc564..546b66cb9d56 100644 --- a/eth/tracers/js/goja.go +++ b/eth/tracers/js/goja.go @@ -249,7 +249,7 @@ func (t *jsTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Addr t.ctx["value"] = valueBig t.ctx["block"] = t.vm.ToValue(env.Context.BlockNumber.Uint64()) // Update list of precompiles based on current block - rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time, env.Context.ArbOSVersion) t.activePrecompiles = vm.ActivePrecompiles(rules) } diff --git a/eth/tracers/native/4byte.go b/eth/tracers/native/4byte.go index 1b4649baa33e..d36a7b9956fa 100644 --- a/eth/tracers/native/4byte.go +++ b/eth/tracers/native/4byte.go @@ -81,7 +81,7 @@ func (t *fourByteTracer) store(id []byte, size int) { // CaptureStart implements the EVMLogger interface to initialize the tracing operation. func (t *fourByteTracer) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) { // Update list of precompiles based on current block - rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time) + rules := env.ChainConfig().Rules(env.Context.BlockNumber, env.Context.Random != nil, env.Context.Time, env.Context.ArbOSVersion) t.activePrecompiles = vm.ActivePrecompiles(rules) // Save the outer calldata also diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index c0bbc557d9d1..486e5f27f4f9 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1640,8 +1640,12 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH to = crypto.CreateAddress(args.from(), uint64(*args.Nonce)) } isPostMerge := header.Difficulty.Cmp(common.Big0) == 0 + headerInfo, err := types.DeserializeHeaderExtraInformation(header) + if err != nil { + return nil, 0, nil, err + } // Retrieve the precompiles since they don't need to be added to the access list - precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time)) + precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time, headerInfo.ArbOSFormatVersion)) // Create an initial tracer prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles) diff --git a/params/config.go b/params/config.go index 97eaf61d53c0..ae2b9c3097ae 100644 --- a/params/config.go +++ b/params/config.go @@ -345,7 +345,7 @@ var ( Clique: nil, ArbitrumChainParams: DisableArbitrumParams(), } - TestRules = TestChainConfig.Rules(new(big.Int), false, 0) + TestRules = TestChainConfig.Rules(new(big.Int), false, 0, 0) ) // NetworkNames are user friendly names to use in the chain spec banner. @@ -974,7 +974,7 @@ type Rules struct { } // Rules ensures c's ChainID is not nil. -func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules { +func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64, currentArbosVersion uint64) Rules { chainID := c.ChainID if chainID == nil { chainID = new(big.Int) @@ -993,7 +993,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules IsBerlin: c.IsBerlin(num), IsLondon: c.IsLondon(num), IsMerge: isMerge, - IsShanghai: c.IsShanghai(timestamp), + IsShanghai: currentArbosVersion >= 11, isCancun: c.IsCancun(timestamp), isPrague: c.IsPrague(timestamp), } diff --git a/params/config_test.go b/params/config_test.go index 5634569e29f0..0b3578f5e712 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -124,15 +124,18 @@ func TestConfigRules(t *testing.T) { ShanghaiTime: newUint64(500), } var stamp uint64 - if r := c.Rules(big.NewInt(0), true, stamp); r.IsShanghai { - t.Errorf("expected %v to not be shanghai", stamp) + var currentArbosVersion uint64 + if r := c.Rules(big.NewInt(0), true, stamp, currentArbosVersion); r.IsShanghai { + t.Errorf("expected %v to not be shanghai", currentArbosVersion) } stamp = 500 - if r := c.Rules(big.NewInt(0), true, stamp); !r.IsShanghai { - t.Errorf("expected %v to be shanghai", stamp) + currentArbosVersion = 11 + if r := c.Rules(big.NewInt(0), true, stamp, currentArbosVersion); !r.IsShanghai { + t.Errorf("expected %v to be shanghai", currentArbosVersion) } stamp = math.MaxInt64 - if r := c.Rules(big.NewInt(0), true, stamp); !r.IsShanghai { - t.Errorf("expected %v to be shanghai", stamp) + currentArbosVersion = math.MaxInt64 + if r := c.Rules(big.NewInt(0), true, stamp, currentArbosVersion); !r.IsShanghai { + t.Errorf("expected %v to be shanghai", currentArbosVersion) } } diff --git a/tests/state_test.go b/tests/state_test.go index 7dd2f678c683..9e6b645e045c 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -183,7 +183,7 @@ func runBenchmark(b *testing.B, t *StateTest) { b.Error(err) return } - var rules = config.Rules(new(big.Int), false, 0) + var rules = config.Rules(new(big.Int), false, 0, 0) vmconfig.ExtraEips = eips block := t.genesis(config).ToBlock() From 940cc23d93a75148e50bd74a26f6b51201416e2a Mon Sep 17 00:00:00 2001 From: amsanghi Date: Fri, 21 Apr 2023 00:41:40 +0530 Subject: [PATCH 2/5] minor fix --- cmd/evm/internal/t8ntool/execution.go | 3 +++ core/vm/runtime/env.go | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 2c68659945eb..f0ed7f2b9cbf 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -109,6 +109,9 @@ type rejectedTx struct { func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, txs types.Transactions, miningReward int64, getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, error) { + if chainConfig.IsArbitrum() { + return nil, nil, NewError(ErrorConfig, fmt.Errorf("chain config has arbitrum enabled")) + } // Capture errors for BLOCKHASH operation, if we haven't been supplied the // required blockhashes var hashError error diff --git a/core/vm/runtime/env.go b/core/vm/runtime/env.go index dcb097428454..3bd78e4c7120 100644 --- a/core/vm/runtime/env.go +++ b/core/vm/runtime/env.go @@ -17,11 +17,16 @@ package runtime import ( + "fmt" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/vm" ) func NewEnv(cfg *Config) *vm.EVM { + if cfg.ChainConfig.IsArbitrum() { + panic(fmt.Errorf("chain config has arbitrum enabled")) + } txContext := vm.TxContext{ Origin: cfg.Origin, GasPrice: cfg.GasPrice, From 778cf0a8e0ea4c6062d4fe5b2d1d08a7ae2f50fb Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 26 Apr 2023 19:13:09 +0530 Subject: [PATCH 3/5] Changes based on PR comments --- core/vm/runtime/env.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/vm/runtime/env.go b/core/vm/runtime/env.go index 3bd78e4c7120..8885b10af9e1 100644 --- a/core/vm/runtime/env.go +++ b/core/vm/runtime/env.go @@ -17,15 +17,13 @@ package runtime import ( - "fmt" - "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/vm" ) func NewEnv(cfg *Config) *vm.EVM { if cfg.ChainConfig.IsArbitrum() { - panic(fmt.Errorf("chain config has arbitrum enabled")) + panic("chain config has arbitrum enabled") } txContext := vm.TxContext{ Origin: cfg.Origin, From e803c335aada568a8470cba3f7523570abda2b62 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Wed, 26 Apr 2023 19:52:45 +0530 Subject: [PATCH 4/5] Changes based on PR comments --- cmd/evm/internal/t8ntool/transaction.go | 4 ++-- cmd/evm/internal/t8ntool/transition.go | 2 +- consensus/beacon/consensus.go | 12 ++++++++++-- consensus/clique/clique.go | 6 +++++- consensus/ethash/consensus.go | 6 +++++- core/genesis.go | 6 +++++- core/state_processor.go | 6 +++++- core/state_processor_test.go | 12 ++++++++++-- core/txpool/txpool.go | 7 ++++++- eth/catalyst/api.go | 18 +++++++++++++++--- light/txpool.go | 7 ++++++- params/config.go | 7 +++++-- 12 files changed, 75 insertions(+), 18 deletions(-) diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index 21279e8f0a80..0fe084a07381 100644 --- a/cmd/evm/internal/t8ntool/transaction.go +++ b/cmd/evm/internal/t8ntool/transaction.go @@ -140,7 +140,7 @@ func Transaction(ctx *cli.Context) error { } // Check intrinsic gas if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, - chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(0)); err != nil { + chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(0, 0)); err != nil { r.Error = err results = append(results, r) continue @@ -172,7 +172,7 @@ func Transaction(ctx *cli.Context) error { r.Error = errors.New("gas * maxFeePerGas exceeds 256 bits") } // Check whether the init code size has been exceeded. - if chainConfig.IsShanghai(0) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { + if chainConfig.IsShanghai(0, 0) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { r.Error = errors.New("max initcode size exceeded") } results = append(results, r) diff --git a/cmd/evm/internal/t8ntool/transition.go b/cmd/evm/internal/t8ntool/transition.go index cb7466d86cae..4270ebf7792a 100644 --- a/cmd/evm/internal/t8ntool/transition.go +++ b/cmd/evm/internal/t8ntool/transition.go @@ -262,7 +262,7 @@ func Transition(ctx *cli.Context) error { return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section")) } } - if chainConfig.IsShanghai(prestate.Env.Number) && prestate.Env.Withdrawals == nil { + if chainConfig.IsShanghai(prestate.Env.Number, 0) && prestate.Env.Withdrawals == nil { return NewError(ErrorConfig, errors.New("Shanghai config but missing 'withdrawals' in env section")) } isMerged := chainConfig.TerminalTotalDifficulty != nil && chainConfig.TerminalTotalDifficulty.BitLen() == 0 diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index eb5aa58ca887..6d4fa4bb1101 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -261,7 +261,11 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa return err } // Verify existence / non-existence of withdrawalsHash. - shanghai := chain.Config().IsShanghai(header.Time) + headerInfo, err := types.DeserializeHeaderExtraInformation(header) + if err != nil { + return err + } + shanghai := chain.Config().IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) if shanghai && header.WithdrawalsHash == nil { return fmt.Errorf("missing withdrawalsHash") } @@ -354,7 +358,11 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea if !beacon.IsPoSHeader(header) { return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts, nil) } - shanghai := chain.Config().IsShanghai(header.Time) + headerInfo, err := types.DeserializeHeaderExtraInformation(header) + if err != nil { + return nil, err + } + shanghai := chain.Config().IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) if shanghai { // All blocks after Shanghai must include a withdrawals root. if withdrawals == nil { diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 4706bbac1ca9..7fc4f22851d7 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -298,7 +298,11 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H if header.GasLimit > params.MaxGasLimit { return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) } - if chain.Config().IsShanghai(header.Time) { + headerInfo, err := types.DeserializeHeaderExtraInformation(header) + if err != nil { + return err + } + if chain.Config().IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) { return fmt.Errorf("clique does not support shanghai fork") } // If all checks passed, validate any special fields for hard forks diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index da29e16597b6..140416741b2a 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -310,7 +310,11 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { return consensus.ErrInvalidNumber } - if chain.Config().IsShanghai(header.Time) { + headerInfo, err := types.DeserializeHeaderExtraInformation(header) + if err != nil { + return err + } + if chain.Config().IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) { return fmt.Errorf("ethash does not support shanghai fork") } // Verify the engine specific seal securing the block diff --git a/core/genesis.go b/core/genesis.go index a522b20dc5d9..9176fd3a60bf 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -466,7 +466,11 @@ func (g *Genesis) ToBlock() *types.Block { } } var withdrawals []*types.Withdrawal - if g.Config != nil && g.Config.IsShanghai(g.Timestamp) { + headInfo, err := types.DeserializeHeaderExtraInformation(head) + if err != nil { + return nil + } + if g.Config != nil && g.Config.IsShanghai(g.Timestamp, headInfo.ArbOSFormatVersion) { head.WithdrawalsHash = &types.EmptyWithdrawalsHash withdrawals = make([]*types.Withdrawal, 0) } diff --git a/core/state_processor.go b/core/state_processor.go index 599221ad634f..3b4c2e561269 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -87,7 +87,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } // Fail if Shanghai not enabled and len(withdrawals) is non-zero. withdrawals := block.Withdrawals() - if len(withdrawals) > 0 && !p.config.IsShanghai(block.Time()) { + headerInfo, err := types.DeserializeHeaderExtraInformation(header) + if err != nil { + return nil, nil, 0, err + } + if len(withdrawals) > 0 && !p.config.IsShanghai(block.Time(), headerInfo.ArbOSFormatVersion) { return nil, nil, 0, fmt.Errorf("withdrawals before shanghai") } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 59391fa86199..4a2570a11765 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -403,7 +403,11 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr if config.IsLondon(header.Number) { header.BaseFee = misc.CalcBaseFee(config, parent.Header()) } - if config.IsShanghai(header.Time) { + headerInfo, err := types.DeserializeHeaderExtraInformation(header) + if err != nil { + return nil + } + if config.IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) { header.WithdrawalsHash = &types.EmptyWithdrawalsHash } var receipts []*types.Receipt @@ -423,7 +427,11 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr } header.Root = common.BytesToHash(hasher.Sum(nil)) // Assemble and return the final block for sealing - if config.IsShanghai(header.Time) { + headerInfo, err = types.DeserializeHeaderExtraInformation(header) + if err != nil { + return nil + } + if config.IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) { return types.NewBlockWithWithdrawals(header, txs, nil, receipts, []*types.Withdrawal{}, trie.NewStackTrie(nil)) } return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)) diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index c80520186627..84ee0bc5e4aa 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -1312,7 +1312,12 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { pool.istanbul = pool.chainconfig.IsIstanbul(next) pool.eip2718 = pool.chainconfig.IsBerlin(next) pool.eip1559 = pool.chainconfig.IsLondon(next) - pool.shanghai = pool.chainconfig.IsShanghai(uint64(time.Now().Unix())) + newHeadInfo, err := types.DeserializeHeaderExtraInformation(newHead) + if err != nil { + log.Error(err.Error()) + return + } + pool.shanghai = pool.chainconfig.IsShanghai(uint64(time.Now().Unix()), newHeadInfo.ArbOSFormatVersion) } // promoteExecutables moves transactions that have become processable from the diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 95eed408f031..684e6d9542ee 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -173,7 +173,11 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, pa if payloadAttributes.Withdrawals != nil { return engine.STATUS_INVALID, engine.InvalidParams.With(fmt.Errorf("withdrawals not supported in V1")) } - if api.eth.BlockChain().Config().IsShanghai(payloadAttributes.Timestamp) { + headerInfo, err := types.DeserializeHeaderExtraInformation(api.eth.BlockChain().CurrentHeader()) + if err != nil { + return engine.ForkChoiceResponse{}, err + } + if api.eth.BlockChain().Config().IsShanghai(payloadAttributes.Timestamp, headerInfo.ArbOSFormatVersion) { return engine.STATUS_INVALID, engine.InvalidParams.With(fmt.Errorf("forkChoiceUpdateV1 called post-shanghai")) } } @@ -191,7 +195,11 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, pa } func (api *ConsensusAPI) verifyPayloadAttributes(attr *engine.PayloadAttributes) error { - if !api.eth.BlockChain().Config().IsShanghai(attr.Timestamp) { + headerInfo, err := types.DeserializeHeaderExtraInformation(api.eth.BlockChain().CurrentHeader()) + if err != nil { + return err + } + if !api.eth.BlockChain().Config().IsShanghai(attr.Timestamp, headerInfo.ArbOSFormatVersion) { // Reject payload attributes with withdrawals before shanghai if attr.Withdrawals != nil { return errors.New("withdrawals before shanghai") @@ -417,7 +425,11 @@ func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.Payl // NewPayloadV2 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) { - if api.eth.BlockChain().Config().IsShanghai(params.Timestamp) { + headerInfo, err := types.DeserializeHeaderExtraInformation(api.eth.BlockChain().CurrentHeader()) + if err != nil { + return engine.PayloadStatusV1{}, err + } + if api.eth.BlockChain().Config().IsShanghai(params.Timestamp, headerInfo.ArbOSFormatVersion) { if params.Withdrawals == nil { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("nil withdrawals post-shanghai")) } diff --git a/light/txpool.go b/light/txpool.go index e59dc3e77434..68dac43cc360 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -318,7 +318,12 @@ func (pool *TxPool) setNewHead(head *types.Header) { next := new(big.Int).Add(head.Number, big.NewInt(1)) pool.istanbul = pool.config.IsIstanbul(next) pool.eip2718 = pool.config.IsBerlin(next) - pool.shanghai = pool.config.IsShanghai(uint64(time.Now().Unix())) + headInfo, err := types.DeserializeHeaderExtraInformation(head) + if err != nil { + log.Error(err.Error()) + return + } + pool.shanghai = pool.config.IsShanghai(uint64(time.Now().Unix()), headInfo.ArbOSFormatVersion) } // Stop stops the light transaction pool diff --git a/params/config.go b/params/config.go index ae2b9c3097ae..a92218647093 100644 --- a/params/config.go +++ b/params/config.go @@ -650,7 +650,10 @@ func (c *ChainConfig) IsTerminalPoWBlock(parentTotalDiff *big.Int, totalDiff *bi } // IsShanghai returns whether time is either equal to the Shanghai fork time or greater. -func (c *ChainConfig) IsShanghai(time uint64) bool { +func (c *ChainConfig) IsShanghai(time uint64, currentArbosVersion uint64) bool { + if c.IsArbitrum() { + return currentArbosVersion >= 11 + } return isTimestampForked(c.ShanghaiTime, time) } @@ -993,7 +996,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64, curren IsBerlin: c.IsBerlin(num), IsLondon: c.IsLondon(num), IsMerge: isMerge, - IsShanghai: currentArbosVersion >= 11, + IsShanghai: c.IsShanghai(timestamp, currentArbosVersion), isCancun: c.IsCancun(timestamp), isPrague: c.IsPrague(timestamp), } From 94b5d941f84ec97ecda61086041ca7b4d43dd0d3 Mon Sep 17 00:00:00 2001 From: amsanghi Date: Tue, 2 May 2023 23:28:16 +0530 Subject: [PATCH 5/5] Changes based on PR comments --- consensus/beacon/consensus.go | 12 ++---------- consensus/clique/clique.go | 6 +----- consensus/ethash/consensus.go | 6 +----- core/evm.go | 3 +-- core/genesis.go | 6 +----- core/state_processor.go | 6 +----- core/state_processor_test.go | 12 ++---------- core/txpool/txpool.go | 7 +------ core/types/arb_types.go | 12 ++++-------- eth/catalyst/api.go | 18 +++--------------- internal/ethapi/api.go | 25 ++++++------------------- light/txpool.go | 7 +------ 12 files changed, 24 insertions(+), 96 deletions(-) diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index 6d4fa4bb1101..b738c15ceb52 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -261,11 +261,7 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa return err } // Verify existence / non-existence of withdrawalsHash. - headerInfo, err := types.DeserializeHeaderExtraInformation(header) - if err != nil { - return err - } - shanghai := chain.Config().IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) + shanghai := chain.Config().IsShanghai(header.Time, types.DeserializeHeaderExtraInformation(header).ArbOSFormatVersion) if shanghai && header.WithdrawalsHash == nil { return fmt.Errorf("missing withdrawalsHash") } @@ -358,11 +354,7 @@ func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, hea if !beacon.IsPoSHeader(header) { return beacon.ethone.FinalizeAndAssemble(chain, header, state, txs, uncles, receipts, nil) } - headerInfo, err := types.DeserializeHeaderExtraInformation(header) - if err != nil { - return nil, err - } - shanghai := chain.Config().IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) + shanghai := chain.Config().IsShanghai(header.Time, types.DeserializeHeaderExtraInformation(header).ArbOSFormatVersion) if shanghai { // All blocks after Shanghai must include a withdrawals root. if withdrawals == nil { diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 7fc4f22851d7..be4a4528adac 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -298,11 +298,7 @@ func (c *Clique) verifyHeader(chain consensus.ChainHeaderReader, header *types.H if header.GasLimit > params.MaxGasLimit { return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) } - headerInfo, err := types.DeserializeHeaderExtraInformation(header) - if err != nil { - return err - } - if chain.Config().IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) { + if chain.Config().IsShanghai(header.Time, types.DeserializeHeaderExtraInformation(header).ArbOSFormatVersion) { return fmt.Errorf("clique does not support shanghai fork") } // If all checks passed, validate any special fields for hard forks diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index 140416741b2a..5a6ce3136f18 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -310,11 +310,7 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 { return consensus.ErrInvalidNumber } - headerInfo, err := types.DeserializeHeaderExtraInformation(header) - if err != nil { - return err - } - if chain.Config().IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) { + if chain.Config().IsShanghai(header.Time, types.DeserializeHeaderExtraInformation(header).ArbOSFormatVersion) { return fmt.Errorf("ethash does not support shanghai fork") } // Verify the engine specific seal securing the block diff --git a/core/evm.go b/core/evm.go index 804b4c022fc8..25aef80a0970 100644 --- a/core/evm.go +++ b/core/evm.go @@ -55,7 +55,6 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common if header.Difficulty.Cmp(common.Big0) == 0 { random = &header.MixDigest } - headerInfo, _ := types.DeserializeHeaderExtraInformation(header) return vm.BlockContext{ CanTransfer: CanTransfer, Transfer: Transfer, @@ -67,7 +66,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common BaseFee: baseFee, GasLimit: header.GasLimit, Random: random, - ArbOSVersion: headerInfo.ArbOSFormatVersion, + ArbOSVersion: types.DeserializeHeaderExtraInformation(header).ArbOSFormatVersion, } } diff --git a/core/genesis.go b/core/genesis.go index 9176fd3a60bf..88be75025f5d 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -466,11 +466,7 @@ func (g *Genesis) ToBlock() *types.Block { } } var withdrawals []*types.Withdrawal - headInfo, err := types.DeserializeHeaderExtraInformation(head) - if err != nil { - return nil - } - if g.Config != nil && g.Config.IsShanghai(g.Timestamp, headInfo.ArbOSFormatVersion) { + if g.Config != nil && g.Config.IsShanghai(g.Timestamp, types.DeserializeHeaderExtraInformation(head).ArbOSFormatVersion) { head.WithdrawalsHash = &types.EmptyWithdrawalsHash withdrawals = make([]*types.Withdrawal, 0) } diff --git a/core/state_processor.go b/core/state_processor.go index 3b4c2e561269..60ce3838e564 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -87,11 +87,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg } // Fail if Shanghai not enabled and len(withdrawals) is non-zero. withdrawals := block.Withdrawals() - headerInfo, err := types.DeserializeHeaderExtraInformation(header) - if err != nil { - return nil, nil, 0, err - } - if len(withdrawals) > 0 && !p.config.IsShanghai(block.Time(), headerInfo.ArbOSFormatVersion) { + if len(withdrawals) > 0 && !p.config.IsShanghai(block.Time(), types.DeserializeHeaderExtraInformation(header).ArbOSFormatVersion) { return nil, nil, 0, fmt.Errorf("withdrawals before shanghai") } // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 4a2570a11765..e2ddebb6ec99 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -403,11 +403,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr if config.IsLondon(header.Number) { header.BaseFee = misc.CalcBaseFee(config, parent.Header()) } - headerInfo, err := types.DeserializeHeaderExtraInformation(header) - if err != nil { - return nil - } - if config.IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) { + if config.IsShanghai(header.Time, types.DeserializeHeaderExtraInformation(header).ArbOSFormatVersion) { header.WithdrawalsHash = &types.EmptyWithdrawalsHash } var receipts []*types.Receipt @@ -427,11 +423,7 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr } header.Root = common.BytesToHash(hasher.Sum(nil)) // Assemble and return the final block for sealing - headerInfo, err = types.DeserializeHeaderExtraInformation(header) - if err != nil { - return nil - } - if config.IsShanghai(header.Time, headerInfo.ArbOSFormatVersion) { + if config.IsShanghai(header.Time, types.DeserializeHeaderExtraInformation(header).ArbOSFormatVersion) { return types.NewBlockWithWithdrawals(header, txs, nil, receipts, []*types.Withdrawal{}, trie.NewStackTrie(nil)) } return types.NewBlock(header, txs, nil, receipts, trie.NewStackTrie(nil)) diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 84ee0bc5e4aa..e44e42b712a6 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -1312,12 +1312,7 @@ func (pool *TxPool) reset(oldHead, newHead *types.Header) { pool.istanbul = pool.chainconfig.IsIstanbul(next) pool.eip2718 = pool.chainconfig.IsBerlin(next) pool.eip1559 = pool.chainconfig.IsLondon(next) - newHeadInfo, err := types.DeserializeHeaderExtraInformation(newHead) - if err != nil { - log.Error(err.Error()) - return - } - pool.shanghai = pool.chainconfig.IsShanghai(uint64(time.Now().Unix()), newHeadInfo.ArbOSFormatVersion) + pool.shanghai = pool.chainconfig.IsShanghai(uint64(time.Now().Unix()), types.DeserializeHeaderExtraInformation(newHead).ArbOSFormatVersion) } // promoteExecutables moves transactions that have become processable from the diff --git a/core/types/arb_types.go b/core/types/arb_types.go index 84be0cbc5746..aa99308b7e17 100644 --- a/core/types/arb_types.go +++ b/core/types/arb_types.go @@ -3,7 +3,6 @@ package types import ( "context" "encoding/binary" - "fmt" "math/big" "github.com/ethereum/go-ethereum/common/hexutil" @@ -444,19 +443,16 @@ func (info HeaderInfo) UpdateHeaderWithInfo(header *Header) { header.Extra = info.extra() } -func DeserializeHeaderExtraInformation(header *Header) (HeaderInfo, error) { - if header.BaseFee == nil || header.BaseFee.Sign() == 0 || len(header.Extra) == 0 { +func DeserializeHeaderExtraInformation(header *Header) HeaderInfo { + if header.BaseFee == nil || header.BaseFee.Sign() == 0 || len(header.Extra) != 32 || header.Difficulty.Cmp(common.Big1) != 0 { // imported blocks have no base fee // The genesis block doesn't have an ArbOS encoded extra field - return HeaderInfo{}, nil - } - if len(header.Extra) != 32 { - return HeaderInfo{}, fmt.Errorf("unexpected header extra field length %v", len(header.Extra)) + return HeaderInfo{} } extra := HeaderInfo{} copy(extra.SendRoot[:], header.Extra) extra.SendCount = binary.BigEndian.Uint64(header.MixDigest[:8]) extra.L1BlockNumber = binary.BigEndian.Uint64(header.MixDigest[8:16]) extra.ArbOSFormatVersion = binary.BigEndian.Uint64(header.MixDigest[16:24]) - return extra, nil + return extra } diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 684e6d9542ee..d11692be38b9 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -173,11 +173,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, pa if payloadAttributes.Withdrawals != nil { return engine.STATUS_INVALID, engine.InvalidParams.With(fmt.Errorf("withdrawals not supported in V1")) } - headerInfo, err := types.DeserializeHeaderExtraInformation(api.eth.BlockChain().CurrentHeader()) - if err != nil { - return engine.ForkChoiceResponse{}, err - } - if api.eth.BlockChain().Config().IsShanghai(payloadAttributes.Timestamp, headerInfo.ArbOSFormatVersion) { + if api.eth.BlockChain().Config().IsShanghai(payloadAttributes.Timestamp, types.DeserializeHeaderExtraInformation(api.eth.BlockChain().CurrentHeader()).ArbOSFormatVersion) { return engine.STATUS_INVALID, engine.InvalidParams.With(fmt.Errorf("forkChoiceUpdateV1 called post-shanghai")) } } @@ -195,11 +191,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, pa } func (api *ConsensusAPI) verifyPayloadAttributes(attr *engine.PayloadAttributes) error { - headerInfo, err := types.DeserializeHeaderExtraInformation(api.eth.BlockChain().CurrentHeader()) - if err != nil { - return err - } - if !api.eth.BlockChain().Config().IsShanghai(attr.Timestamp, headerInfo.ArbOSFormatVersion) { + if !api.eth.BlockChain().Config().IsShanghai(attr.Timestamp, types.DeserializeHeaderExtraInformation(api.eth.BlockChain().CurrentHeader()).ArbOSFormatVersion) { // Reject payload attributes with withdrawals before shanghai if attr.Withdrawals != nil { return errors.New("withdrawals before shanghai") @@ -425,11 +417,7 @@ func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.Payl // NewPayloadV2 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.PayloadStatusV1, error) { - headerInfo, err := types.DeserializeHeaderExtraInformation(api.eth.BlockChain().CurrentHeader()) - if err != nil { - return engine.PayloadStatusV1{}, err - } - if api.eth.BlockChain().Config().IsShanghai(params.Timestamp, headerInfo.ArbOSFormatVersion) { + if api.eth.BlockChain().Config().IsShanghai(params.Timestamp, types.DeserializeHeaderExtraInformation(api.eth.BlockChain().CurrentHeader()).ArbOSFormatVersion) { if params.Withdrawals == nil { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(fmt.Errorf("nil withdrawals post-shanghai")) } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 486e5f27f4f9..e12c70dd2c05 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1353,14 +1353,10 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, config *param } func fillArbitrumNitroHeaderInfo(header *types.Header, fields map[string]interface{}) { - info, err := types.DeserializeHeaderExtraInformation(header) - if err != nil { - log.Error("Expected header to contain arbitrum data", "blockHash", header.Hash()) - } else { - fields["l1BlockNumber"] = hexutil.Uint64(info.L1BlockNumber) - fields["sendRoot"] = info.SendRoot - fields["sendCount"] = hexutil.Uint64(info.SendCount) - } + info := types.DeserializeHeaderExtraInformation(header) + fields["l1BlockNumber"] = hexutil.Uint64(info.L1BlockNumber) + fields["sendRoot"] = info.SendRoot + fields["sendCount"] = hexutil.Uint64(info.SendCount) } // rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field, which requires @@ -1640,12 +1636,8 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH to = crypto.CreateAddress(args.from(), uint64(*args.Nonce)) } isPostMerge := header.Difficulty.Cmp(common.Big0) == 0 - headerInfo, err := types.DeserializeHeaderExtraInformation(header) - if err != nil { - return nil, 0, nil, err - } // Retrieve the precompiles since they don't need to be added to the access list - precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time, headerInfo.ArbOSFormatVersion)) + precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time, types.DeserializeHeaderExtraInformation(header).ArbOSFormatVersion)) // Create an initial tracer prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles) @@ -1882,12 +1874,7 @@ func (s *TransactionAPI) GetTransactionReceipt(ctx context.Context, hash common. } if s.b.ChainConfig().IsArbitrumNitro(header.Number) { fields["effectiveGasPrice"] = hexutil.Uint64(header.BaseFee.Uint64()) - info, err := types.DeserializeHeaderExtraInformation(header) - if err != nil { - log.Error("Expected header to contain arbitrum data", "blockHash", blockHash) - } else { - fields["l1BlockNumber"] = hexutil.Uint64(info.L1BlockNumber) - } + fields["l1BlockNumber"] = hexutil.Uint64(types.DeserializeHeaderExtraInformation(header).L1BlockNumber) } else { inner := tx.GetInner() arbTx, ok := inner.(*types.ArbitrumLegacyTxData) diff --git a/light/txpool.go b/light/txpool.go index 68dac43cc360..83b5aac0ce99 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -318,12 +318,7 @@ func (pool *TxPool) setNewHead(head *types.Header) { next := new(big.Int).Add(head.Number, big.NewInt(1)) pool.istanbul = pool.config.IsIstanbul(next) pool.eip2718 = pool.config.IsBerlin(next) - headInfo, err := types.DeserializeHeaderExtraInformation(head) - if err != nil { - log.Error(err.Error()) - return - } - pool.shanghai = pool.config.IsShanghai(uint64(time.Now().Unix()), headInfo.ArbOSFormatVersion) + pool.shanghai = pool.config.IsShanghai(uint64(time.Now().Unix()), types.DeserializeHeaderExtraInformation(head).ArbOSFormatVersion) } // Stop stops the light transaction pool