From 2b57a27d9e2865d3a82ab8f57eb1d80e23e1cd3c Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Wed, 25 Jan 2023 06:12:28 -0500 Subject: [PATCH] all: make timestamp-based fork checks based on uint64 (#26474) This PR changes the API so that uint64 is used for fork timestamps. It's a good choice because types.Header also uses uint64 for time. Co-authored-by: Felix Lange --- cmd/evm/internal/t8ntool/execution.go | 2 +- cmd/evm/internal/t8ntool/transaction.go | 4 +- cmd/evm/runner.go | 2 +- cmd/geth/config.go | 3 +- cmd/utils/flags.go | 2 +- core/blockchain_test.go | 2 +- core/evm.go | 2 +- core/forkid/forkid.go | 18 +++---- core/forkid/forkid_test.go | 7 +-- core/genesis.go | 2 +- core/state_processor_test.go | 4 +- core/txpool/txpool.go | 2 +- core/vm/evm.go | 2 +- core/vm/instructions.go | 3 +- core/vm/runtime/runtime.go | 6 +-- core/vm/runtime/runtime_test.go | 5 +- eth/ethconfig/config.go | 3 +- eth/ethconfig/gen_config.go | 5 +- .../internal/tracetest/calltrace_test.go | 6 +-- .../internal/tracetest/prestate_test.go | 2 +- eth/tracers/tracers_test.go | 2 +- internal/ethapi/api.go | 6 +-- light/txpool.go | 2 +- params/config.go | 50 +++++++++---------- params/config_test.go | 34 ++++++++++--- tests/init.go | 4 +- tests/state_test.go | 2 +- 27 files changed, 100 insertions(+), 82 deletions(-) diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 08d829d7db..63c54b1d8a 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -138,7 +138,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, Transfer: core.Transfer, Coinbase: pre.Env.Coinbase, BlockNumber: new(big.Int).SetUint64(pre.Env.Number), - Time: new(big.Int).SetUint64(pre.Env.Timestamp), + Time: pre.Env.Timestamp, Difficulty: pre.Env.Difficulty, GasLimit: pre.Env.GasLimit, GetHash: getHash, diff --git a/cmd/evm/internal/t8ntool/transaction.go b/cmd/evm/internal/t8ntool/transaction.go index 1bd370918e..21279e8f0a 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(new(big.Int))); err != nil { + chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int)), chainConfig.IsShanghai(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(new(big.Int)) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { + if chainConfig.IsShanghai(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/runner.go b/cmd/evm/runner.go index 9b1975c050..3a010da9f2 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -209,7 +209,7 @@ func runCmd(ctx *cli.Context) error { GasPrice: flags.GlobalBig(ctx, PriceFlag.Name), Value: flags.GlobalBig(ctx, ValueFlag.Name), Difficulty: genesisConfig.Difficulty, - Time: new(big.Int).SetUint64(genesisConfig.Timestamp), + Time: genesisConfig.Timestamp, Coinbase: genesisConfig.Coinbase, BlockNumber: new(big.Int).SetUint64(genesisConfig.Number), EVMConfig: vm.Config{ diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 9c6fd9baae..61b7ed5ec1 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -159,7 +159,8 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) { func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { stack, cfg := makeConfigNode(ctx) if ctx.IsSet(utils.OverrideShanghai.Name) { - cfg.Eth.OverrideShanghai = flags.GlobalBig(ctx, utils.OverrideShanghai.Name) + v := ctx.Uint64(utils.OverrideShanghai.Name) + cfg.Eth.OverrideShanghai = &v } backend, eth := utils.RegisterEthService(stack, &cfg.Eth) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index e4a9f2ff7d..2bbbc381be 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -267,7 +267,7 @@ var ( Value: 2048, Category: flags.EthCategory, } - OverrideShanghai = &flags.BigFlag{ + OverrideShanghai = &cli.Uint64Flag{ Name: "override.shanghai", Usage: "Manually specify the Shanghai fork timestamp, overriding the bundled setting", Category: flags.EthCategory, diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 36bfa07525..2f9e604de9 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -4275,7 +4275,7 @@ func TestEIP3651(t *testing.T) { gspec.Config.BerlinBlock = common.Big0 gspec.Config.LondonBlock = common.Big0 - gspec.Config.ShanghaiTime = common.Big0 + gspec.Config.ShanghaiTime = u64(0) signer := types.LatestSigner(gspec.Config) _, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) { diff --git a/core/evm.go b/core/evm.go index e929da25ea..35e12338ef 100644 --- a/core/evm.go +++ b/core/evm.go @@ -61,7 +61,7 @@ func NewEVMBlockContext(header *types.Header, chain ChainContext, author *common GetHash: GetHashFn(header, chain), Coinbase: beneficiary, BlockNumber: new(big.Int).Set(header.Number), - Time: new(big.Int).SetUint64(header.Time), + Time: header.Time, Difficulty: new(big.Int).Set(header.Difficulty), BaseFee: baseFee, GasLimit: header.GasLimit, diff --git a/core/forkid/forkid.go b/core/forkid/forkid.go index 300dca6cfb..f536019dac 100644 --- a/core/forkid/forkid.go +++ b/core/forkid/forkid.go @@ -244,7 +244,7 @@ func gatherForks(config *params.ChainConfig) ([]uint64, []uint64) { // Gather all the fork block numbers via reflection kind := reflect.TypeOf(params.ChainConfig{}) conf := reflect.ValueOf(config).Elem() - + x := uint64(0) var ( forksByBlock []uint64 forksByTime []uint64 @@ -257,15 +257,15 @@ func gatherForks(config *params.ChainConfig) ([]uint64, []uint64) { if !time && !strings.HasSuffix(field.Name, "Block") { continue } - if field.Type != reflect.TypeOf(new(big.Int)) { - continue - } + // Extract the fork rule block number or timestamp and aggregate it - rule := conf.Field(i).Interface().(*big.Int) - if rule != nil { - if time { - forksByTime = append(forksByTime, rule.Uint64()) - } else { + if field.Type == reflect.TypeOf(&x) { + if rule := conf.Field(i).Interface().(*uint64); rule != nil { + forksByTime = append(forksByTime, *rule) + } + } + if field.Type == reflect.TypeOf(new(big.Int)) { + if rule := conf.Field(i).Interface().(*big.Int); rule != nil { forksByBlock = append(forksByBlock, rule.Uint64()) } } diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index 7d6e89c811..c4b46bf411 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -19,7 +19,6 @@ package forkid import ( "bytes" "math" - "math/big" "testing" "github.com/ethereum/go-ethereum/common" @@ -27,12 +26,14 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) +func u64(val uint64) *uint64 { return &val } + // TestCreation tests that different genesis and fork rule combinations result in // the correct fork ID. func TestCreation(t *testing.T) { // Temporary non-existent scenario TODO(karalabe): delete when Shanghai is enabled timestampedConfig := *params.MainnetChainConfig - timestampedConfig.ShanghaiTime = big.NewInt(1668000000) + timestampedConfig.ShanghaiTime = u64(1668000000) type testcase struct { head uint64 @@ -201,7 +202,7 @@ func TestCreation(t *testing.T) { func TestValidation(t *testing.T) { // Temporary non-existent scenario TODO(karalabe): delete when Shanghai is enabled timestampedConfig := *params.MainnetChainConfig - timestampedConfig.ShanghaiTime = big.NewInt(1668000000) + timestampedConfig.ShanghaiTime = u64(1668000000) tests := []struct { config *params.ChainConfig diff --git a/core/genesis.go b/core/genesis.go index 47974f63ab..b4f49a1e1a 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -269,7 +269,7 @@ func (e *GenesisMismatchError) Error() string { // ChainOverrides contains the changes to chain config. type ChainOverrides struct { - OverrideShanghai *big.Int + OverrideShanghai *uint64 } // SetupGenesisBlock writes or updates the genesis block in db. diff --git a/core/state_processor_test.go b/core/state_processor_test.go index 400ccd3187..c91adc36ed 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -35,6 +35,8 @@ import ( "golang.org/x/crypto/sha3" ) +func u64(val uint64) *uint64 { return &val } + // TestStateProcessorErrors tests the output from the 'core' errors // as defined in core/error.go. These errors are generated when the // blockchain imports bad blocks, meaning blocks which have valid headers but @@ -327,7 +329,7 @@ func TestStateProcessorErrors(t *testing.T) { ArrowGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0), MergeNetsplitBlock: big.NewInt(0), - ShanghaiTime: big.NewInt(0), + ShanghaiTime: u64(0), }, Alloc: GenesisAlloc{ common.HexToAddress("0x71562b71999873DB5b286dF957af199Ec94617F7"): GenesisAccount{ diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 3e4eb21cfc..6b878ed586 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -1312,7 +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) - pool.shanghai = pool.chainconfig.IsShanghai(big.NewInt(time.Now().Unix())) + pool.shanghai = pool.chainconfig.IsShanghai(uint64(time.Now().Unix())) } // promoteExecutables moves transactions that have become processable from the diff --git a/core/vm/evm.go b/core/vm/evm.go index 149e9f761b..f6a1557e82 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -71,7 +71,7 @@ type BlockContext struct { Coinbase common.Address // Provides information for COINBASE GasLimit uint64 // Provides information for GASLIMIT BlockNumber *big.Int // Provides information for NUMBER - Time *big.Int // Provides information for TIME + Time uint64 // Provides information for TIME Difficulty *big.Int // Provides information for DIFFICULTY BaseFee *big.Int // Provides information for BASEFEE Random *common.Hash // Provides information for PREVRANDAO diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 8fa2fc57e5..886ff6323d 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -460,8 +460,7 @@ func opCoinbase(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([ } func opTimestamp(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) { - v, _ := uint256.FromBig(interpreter.evm.Context.Time) - scope.Stack.push(v) + scope.Stack.push(new(uint256.Int).SetUint64(interpreter.evm.Context.Time)) return nil, nil } diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index a330825b10..15a1f1a1bd 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -19,7 +19,6 @@ package runtime import ( "math" "math/big" - "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" @@ -37,7 +36,7 @@ type Config struct { Origin common.Address Coinbase common.Address BlockNumber *big.Int - Time *big.Int + Time uint64 GasLimit uint64 GasPrice *big.Int Value *big.Int @@ -74,9 +73,6 @@ func setDefaults(cfg *Config) { if cfg.Difficulty == nil { cfg.Difficulty = new(big.Int) } - if cfg.Time == nil { - cfg.Time = big.NewInt(time.Now().Unix()) - } if cfg.GasLimit == 0 { cfg.GasLimit = math.MaxUint64 } diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go index 868d41e503..6072591065 100644 --- a/core/vm/runtime/runtime_test.go +++ b/core/vm/runtime/runtime_test.go @@ -48,9 +48,6 @@ func TestDefaults(t *testing.T) { t.Error("expected difficulty to be non nil") } - if cfg.Time == nil { - t.Error("expected time to be non nil") - } if cfg.GasLimit == 0 { t.Error("didn't expect gaslimit to be zero") } @@ -174,7 +171,7 @@ func benchmarkEVM_Create(bench *testing.B, code string) { State: statedb, GasLimit: 10000000, Difficulty: big.NewInt(0x200000), - Time: new(big.Int).SetUint64(0), + Time: 0, Coinbase: common.Address{}, BlockNumber: new(big.Int).SetUint64(1), ChainConfig: ¶ms.ChainConfig{ diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 04ef21f49d..db686c5d08 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -18,7 +18,6 @@ package ethconfig import ( - "math/big" "os" "os/user" "path/filepath" @@ -207,7 +206,7 @@ type Config struct { CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"` // OverrideShanghai (TODO: remove after the fork) - OverrideShanghai *big.Int `toml:",omitempty"` + OverrideShanghai *uint64 `toml:",omitempty"` } // CreateConsensusEngine creates a consensus engine for the given chain configuration. diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index 3506d39d5b..b7255a242e 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -3,7 +3,6 @@ package ethconfig import ( - "math/big" "time" "github.com/ethereum/go-ethereum/common" @@ -61,7 +60,7 @@ func (c Config) MarshalTOML() (interface{}, error) { RPCTxFeeCap float64 Checkpoint *params.TrustedCheckpoint `toml:",omitempty"` CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"` - OverrideShanghai *big.Int `toml:",omitempty"` + OverrideShanghai *uint64 `toml:",omitempty"` } var enc Config enc.Genesis = c.Genesis @@ -155,7 +154,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { RPCTxFeeCap *float64 Checkpoint *params.TrustedCheckpoint `toml:",omitempty"` CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"` - OverrideShanghai *big.Int `toml:",omitempty"` + OverrideShanghai *uint64 `toml:",omitempty"` } var dec Config if err := unmarshal(&dec); err != nil { diff --git a/eth/tracers/internal/tracetest/calltrace_test.go b/eth/tracers/internal/tracetest/calltrace_test.go index 5cfb5b33c1..d240e9a4b1 100644 --- a/eth/tracers/internal/tracetest/calltrace_test.go +++ b/eth/tracers/internal/tracetest/calltrace_test.go @@ -133,7 +133,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) { Transfer: core.Transfer, Coinbase: test.Context.Miner, BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), - Time: new(big.Int).SetUint64(uint64(test.Context.Time)), + Time: uint64(test.Context.Time), Difficulty: (*big.Int)(test.Context.Difficulty), GasLimit: uint64(test.Context.GasLimit), BaseFee: test.Genesis.BaseFee, @@ -234,7 +234,7 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) { Transfer: core.Transfer, Coinbase: test.Context.Miner, BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), - Time: new(big.Int).SetUint64(uint64(test.Context.Time)), + Time: uint64(test.Context.Time), Difficulty: (*big.Int)(test.Context.Difficulty), GasLimit: uint64(test.Context.GasLimit), } @@ -288,7 +288,7 @@ func TestZeroValueToNotExitCall(t *testing.T) { Transfer: core.Transfer, Coinbase: common.Address{}, BlockNumber: new(big.Int).SetUint64(8000000), - Time: new(big.Int).SetUint64(5), + Time: 5, Difficulty: big.NewInt(0x30000), GasLimit: uint64(6000000), } diff --git a/eth/tracers/internal/tracetest/prestate_test.go b/eth/tracers/internal/tracetest/prestate_test.go index 2fee7d6fb7..03f06311a3 100644 --- a/eth/tracers/internal/tracetest/prestate_test.go +++ b/eth/tracers/internal/tracetest/prestate_test.go @@ -103,7 +103,7 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) { Transfer: core.Transfer, Coinbase: test.Context.Miner, BlockNumber: new(big.Int).SetUint64(uint64(test.Context.Number)), - Time: new(big.Int).SetUint64(uint64(test.Context.Time)), + Time: uint64(test.Context.Time), Difficulty: (*big.Int)(test.Context.Difficulty), GasLimit: uint64(test.Context.GasLimit), BaseFee: test.Genesis.BaseFee, diff --git a/eth/tracers/tracers_test.go b/eth/tracers/tracers_test.go index 12e01abae4..6cd5a022b1 100644 --- a/eth/tracers/tracers_test.go +++ b/eth/tracers/tracers_test.go @@ -56,7 +56,7 @@ func BenchmarkTransactionTrace(b *testing.B) { Transfer: core.Transfer, Coinbase: common.Address{}, BlockNumber: new(big.Int).SetUint64(uint64(5)), - Time: new(big.Int).SetUint64(uint64(5)), + Time: 5, Difficulty: big.NewInt(0xffffffff), GasLimit: gas, BaseFee: big.NewInt(8), diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index b6efba079a..e0e4278bb4 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -920,7 +920,7 @@ func (diff *StateOverride) Apply(state *state.StateDB) error { type BlockOverrides struct { Number *hexutil.Big Difficulty *hexutil.Big - Time *hexutil.Big + Time *hexutil.Uint64 GasLimit *hexutil.Uint64 Coinbase *common.Address Random *common.Hash @@ -939,7 +939,7 @@ func (diff *BlockOverrides) Apply(blockCtx *vm.BlockContext) { blockCtx.Difficulty = diff.Difficulty.ToInt() } if diff.Time != nil { - blockCtx.Time = diff.Time.ToInt() + blockCtx.Time = uint64(*diff.Time) } if diff.GasLimit != nil { blockCtx.GasLimit = uint64(*diff.GasLimit) @@ -1444,7 +1444,7 @@ func AccessList(ctx context.Context, b Backend, blockNrOrHash rpc.BlockNumberOrH } isPostMerge := header.Difficulty.Cmp(common.Big0) == 0 // Retrieve the precompiles since they don't need to be added to the access list - precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, new(big.Int).SetUint64(header.Time))) + precompiles := vm.ActivePrecompiles(b.ChainConfig().Rules(header.Number, isPostMerge, header.Time)) // Create an initial tracer prevTracer := logger.NewAccessListTracer(nil, args.from(), to, precompiles) diff --git a/light/txpool.go b/light/txpool.go index e12f6ef944..e59dc3e774 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -318,7 +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) - pool.shanghai = pool.config.IsShanghai(big.NewInt(time.Now().Unix())) + pool.shanghai = pool.config.IsShanghai(uint64(time.Now().Unix())) } // Stop stops the light transaction pool diff --git a/params/config.go b/params/config.go index 41072d3eac..aac4392301 100644 --- a/params/config.go +++ b/params/config.go @@ -383,7 +383,7 @@ var ( Ethash: new(EthashConfig), Clique: nil, } - TestRules = TestChainConfig.Rules(new(big.Int), false, new(big.Int)) + TestRules = TestChainConfig.Rules(new(big.Int), false, 0) ) // NetworkNames are user friendly names to use in the chain spec banner. @@ -476,9 +476,9 @@ type ChainConfig struct { // Fork scheduling was switched from blocks to timestamps here - ShanghaiTime *big.Int `json:"shanghaiTime,omitempty"` // Shanghai switch time (nil = no fork, 0 = already on shanghai) - CancunTime *big.Int `json:"cancunTime,omitempty"` // Cancun switch time (nil = no fork, 0 = already on cancun) - PragueTime *big.Int `json:"pragueTime,omitempty"` // Prague switch time (nil = no fork, 0 = already on prague) + ShanghaiTime *uint64 `json:"shanghaiTime,omitempty"` // Shanghai switch time (nil = no fork, 0 = already on shanghai) + CancunTime *uint64 `json:"cancunTime,omitempty"` // Cancun switch time (nil = no fork, 0 = already on cancun) + PragueTime *uint64 `json:"pragueTime,omitempty"` // Prague switch time (nil = no fork, 0 = already on prague) // TerminalTotalDifficulty is the amount of total difficulty reached by // the network that triggers the consensus upgrade. @@ -683,17 +683,17 @@ 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 *big.Int) bool { +func (c *ChainConfig) IsShanghai(time uint64) bool { return isTimestampForked(c.ShanghaiTime, time) } // IsCancun returns whether num is either equal to the Cancun fork time or greater. -func (c *ChainConfig) IsCancun(time *big.Int) bool { +func (c *ChainConfig) IsCancun(time uint64) bool { return isTimestampForked(c.CancunTime, time) } // IsPrague returns whether num is either equal to the Prague fork time or greater. -func (c *ChainConfig) IsPrague(time *big.Int) bool { +func (c *ChainConfig) IsPrague(time uint64) bool { return isTimestampForked(c.PragueTime, time) } @@ -702,7 +702,7 @@ func (c *ChainConfig) IsPrague(time *big.Int) bool { func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time uint64) *ConfigCompatError { var ( bhead = new(big.Int).SetUint64(height) - btime = new(big.Int).SetUint64(time) + btime = time ) // Iterate checkCompatible to find the lowest conflict. var lasterr *ConfigCompatError @@ -714,7 +714,7 @@ func (c *ChainConfig) CheckCompatible(newcfg *ChainConfig, height uint64, time u lasterr = err if err.RewindToTime > 0 { - btime.SetUint64(err.RewindToTime) + btime = err.RewindToTime } else { bhead.SetUint64(err.RewindToBlock) } @@ -728,7 +728,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error { type fork struct { name string block *big.Int // forks up to - and including the merge - were defined with block numbers - timestamp *big.Int // forks after the merge are scheduled using timestamps + timestamp *uint64 // forks after the merge are scheduled using timestamps optional bool // if true, the fork may be nil and next fork is still allowed } var lastFork fork @@ -769,7 +769,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error { if lastFork.block != nil && lastFork.block.Cmp(cur.block) > 0 { return fmt.Errorf("unsupported fork ordering: %v enabled at block %v, but %v enabled at block %v", lastFork.name, lastFork.block, cur.name, cur.block) - } else if lastFork.timestamp != nil && lastFork.timestamp.Cmp(cur.timestamp) > 0 { + } else if lastFork.timestamp != nil && *lastFork.timestamp > *cur.timestamp { return fmt.Errorf("unsupported fork ordering: %v enabled at timestamp %v, but %v enabled at timestamp %v", lastFork.name, lastFork.timestamp, cur.name, cur.timestamp) } @@ -789,7 +789,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error { return nil } -func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, headTimestamp *big.Int) *ConfigCompatError { +func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, headTimestamp uint64) *ConfigCompatError { if isForkBlockIncompatible(c.HomesteadBlock, newcfg.HomesteadBlock, headNumber) { return newBlockCompatError("Homestead fork block", c.HomesteadBlock, newcfg.HomesteadBlock) } @@ -895,28 +895,28 @@ func configBlockEqual(x, y *big.Int) bool { // isForkTimestampIncompatible returns true if a fork scheduled at timestamp s1 // cannot be rescheduled to timestamp s2 because head is already past the fork. -func isForkTimestampIncompatible(s1, s2, head *big.Int) bool { +func isForkTimestampIncompatible(s1, s2 *uint64, head uint64) bool { return (isTimestampForked(s1, head) || isTimestampForked(s2, head)) && !configTimestampEqual(s1, s2) } // isTimestampForked returns whether a fork scheduled at timestamp s is active // at the given head timestamp. Whilst this method is the same as isBlockForked, // they are explicitly separate for clearer reading. -func isTimestampForked(s, head *big.Int) bool { - if s == nil || head == nil { +func isTimestampForked(s *uint64, head uint64) bool { + if s == nil { return false } - return s.Cmp(head) <= 0 + return *s <= head } -func configTimestampEqual(x, y *big.Int) bool { +func configTimestampEqual(x, y *uint64) bool { if x == nil { return y == nil } if y == nil { return x == nil } - return x.Cmp(y) == 0 + return *x == *y } // ConfigCompatError is raised if the locally-stored blockchain is initialised with a @@ -928,7 +928,7 @@ type ConfigCompatError struct { StoredBlock, NewBlock *big.Int // timestamps of the stored and new configurations if time based forking - StoredTime, NewTime *big.Int + StoredTime, NewTime *uint64 // the block number to which the local chain must be rewound to correct the error RewindToBlock uint64 @@ -959,12 +959,12 @@ func newBlockCompatError(what string, storedblock, newblock *big.Int) *ConfigCom return err } -func newTimestampCompatError(what string, storedtime, newtime *big.Int) *ConfigCompatError { - var rew *big.Int +func newTimestampCompatError(what string, storedtime, newtime *uint64) *ConfigCompatError { + var rew *uint64 switch { case storedtime == nil: rew = newtime - case newtime == nil || storedtime.Cmp(newtime) < 0: + case newtime == nil || *storedtime < *newtime: rew = storedtime default: rew = newtime @@ -975,8 +975,8 @@ func newTimestampCompatError(what string, storedtime, newtime *big.Int) *ConfigC NewTime: newtime, RewindToTime: 0, } - if rew != nil && rew.Sign() > 0 { - err.RewindToTime = rew.Uint64() - 1 + if rew != nil { + err.RewindToTime = *rew - 1 } return err } @@ -1002,7 +1002,7 @@ type Rules struct { } // Rules ensures c's ChainID is not nil. -func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp *big.Int) Rules { +func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules { chainID := c.ChainID if chainID == nil { chainID = new(big.Int) diff --git a/params/config_test.go b/params/config_test.go index 523ba26fdc..f3911f433f 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -21,8 +21,12 @@ import ( "reflect" "testing" "time" + + "github.com/ethereum/go-ethereum/common/math" ) +func u64(val uint64) *uint64 { return &val } + func TestCheckCompatible(t *testing.T) { type test struct { stored, new *ChainConfig @@ -91,19 +95,19 @@ func TestCheckCompatible(t *testing.T) { }, }, { - stored: &ChainConfig{ShanghaiTime: big.NewInt(10)}, - new: &ChainConfig{ShanghaiTime: big.NewInt(20)}, + stored: &ChainConfig{ShanghaiTime: u64(10)}, + new: &ChainConfig{ShanghaiTime: u64(20)}, headTimestamp: 9, wantErr: nil, }, { - stored: &ChainConfig{ShanghaiTime: big.NewInt(10)}, - new: &ChainConfig{ShanghaiTime: big.NewInt(20)}, + stored: &ChainConfig{ShanghaiTime: u64(10)}, + new: &ChainConfig{ShanghaiTime: u64(20)}, headTimestamp: 25, wantErr: &ConfigCompatError{ What: "Shanghai fork timestamp", - StoredTime: big.NewInt(10), - NewTime: big.NewInt(20), + StoredTime: u64(10), + NewTime: u64(20), RewindToTime: 9, }, }, @@ -116,3 +120,21 @@ func TestCheckCompatible(t *testing.T) { } } } + +func TestConfigRules(t *testing.T) { + c := &ChainConfig{ + ShanghaiTime: u64(500), + } + var stamp uint64 + if r := c.Rules(big.NewInt(0), true, stamp); r.IsShanghai { + t.Errorf("expected %v to not be shanghai", stamp) + } + stamp = 500 + if r := c.Rules(big.NewInt(0), true, stamp); !r.IsShanghai { + t.Errorf("expected %v to be shanghai", stamp) + } + stamp = math.MaxInt64 + if r := c.Rules(big.NewInt(0), true, stamp); !r.IsShanghai { + t.Errorf("expected %v to be shanghai", stamp) + } +} diff --git a/tests/init.go b/tests/init.go index fd0b015086..a36ab4d9d4 100644 --- a/tests/init.go +++ b/tests/init.go @@ -24,6 +24,8 @@ import ( "github.com/ethereum/go-ethereum/params" ) +func u64(val uint64) *uint64 { return &val } + // Forks table defines supported forks and their chain config. var Forks = map[string]*params.ChainConfig{ "Frontier": { @@ -264,7 +266,7 @@ var Forks = map[string]*params.ChainConfig{ ArrowGlacierBlock: big.NewInt(0), MergeNetsplitBlock: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0), - ShanghaiTime: big.NewInt(0), + ShanghaiTime: u64(0), }, } diff --git a/tests/state_test.go b/tests/state_test.go index 4c5e7b914f..a68321e762 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, new(big.Int)) + var rules = config.Rules(new(big.Int), false, 0) vmconfig.ExtraEips = eips block := t.genesis(config).ToBlock()