diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index d71be6ca53..18ea72629f 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -107,9 +107,7 @@ type SimulatedBackend struct { // and uses a simulated blockchain for testing purposes. // A simulated backend always uses chainID 1337. func NewSimulatedBackendWithDatabase(database ethdb.Database, alloc core.GenesisAlloc, gasLimit uint64) *SimulatedBackend { - cpcfg := params.TestChainConfig - cpcfg.ChainID = big.NewInt(1337) - genesis := core.Genesis{Config: cpcfg, GasLimit: gasLimit, Alloc: alloc} + genesis := core.Genesis{Config: params.SimulatedTestChainConfig, GasLimit: gasLimit, Alloc: alloc} genesis.MustCommit(database) cacheConfig := &core.CacheConfig{} blockchain, _ := core.NewBlockChain(database, cacheConfig, genesis.Config, dummy.NewCoinbaseFaker(), vm.Config{}, common.Hash{}) @@ -599,7 +597,6 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call interfaces.Call for lo+1 < hi { mid := (hi + lo) / 2 failed, _, err := executable(mid) - // If the error is not nil(consensus error), it means the provided message // call or transaction will never be accepted no matter how much gas it is // assigned. Return the error directly, don't struggle any more diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go index 7598010a99..3a03b6cb1a 100644 --- a/accounts/abi/bind/backends/simulated_test.go +++ b/accounts/abi/bind/backends/simulated_test.go @@ -136,11 +136,11 @@ func TestNewSimulatedBackend(t *testing.T) { sim := simTestBackend(testAddr) defer sim.Close() - if sim.config != params.TestChainConfig { + if sim.config != params.SimulatedTestChainConfig { t.Errorf("expected sim config to equal params.AllEthashProtocolChanges, got %v", sim.config) } - if sim.blockchain.Config() != params.TestChainConfig { + if sim.blockchain.Config() != params.SimulatedTestChainConfig { t.Errorf("expected sim blockchain config to equal params.AllEthashProtocolChanges, got %v", sim.config) } diff --git a/core/genesis_test.go b/core/genesis_test.go index d81e5088bb..14193cbf23 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -238,13 +238,13 @@ func TestStatefulPrecompilesConfigure(t *testing.T) { // regression test for precompile activation after header block func TestPrecompileActivationAfterHeaderBlock(t *testing.T) { db := rawdb.NewMemoryDatabase() - + copyCfg := *params.TestChainConfig customg := Genesis{ - Config: params.SubnetEVMDefaultChainConfig, + Config: ©Cfg, Alloc: GenesisAlloc{ {1}: {Balance: big.NewInt(1), Storage: map[common.Hash]common.Hash{{1}: {1}}}, }, - GasLimit: params.SubnetEVMDefaultChainConfig.FeeConfig.GasLimit.Uint64(), + GasLimit: params.TestChainConfig.FeeConfig.GasLimit.Uint64(), } genesis := customg.MustCommit(db) bc, _ := NewBlockChain(db, DefaultCacheConfig, customg.Config, dummy.NewFullFaker(), vm.Config{}, common.Hash{}) diff --git a/core/state_processor_test.go b/core/state_processor_test.go index b48f612333..2d738c0269 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -44,7 +44,8 @@ import ( ) var ( - config = params.TestChainConfig + cpcfg = *params.TestChainConfig + config = &cpcfg signer = types.LatestSigner(config) testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") ) @@ -312,7 +313,7 @@ func TestBadTxAllowListBlock(t *testing.T) { PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0), - NetworkUpgrades: params.NetworkUpgrades{ + MandatoryNetworkUpgrades: params.MandatoryNetworkUpgrades{ SubnetEVMTimestamp: big.NewInt(0), }, GenesisPrecompiles: params.Precompiles{ diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 57f6fe421f..b998710dbc 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -74,7 +74,7 @@ func setDefaults(cfg *Config) { PetersburgBlock: new(big.Int), IstanbulBlock: new(big.Int), MuirGlacierBlock: new(big.Int), - NetworkUpgrades: params.NetworkUpgrades{ + MandatoryNetworkUpgrades: params.MandatoryNetworkUpgrades{ SubnetEVMTimestamp: new(big.Int), }, } diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index 6f8ff8fbb9..0e7d6aef98 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -225,7 +225,7 @@ func newBackendMock() *backendMock { PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0), - NetworkUpgrades: params.NetworkUpgrades{ + MandatoryNetworkUpgrades: params.MandatoryNetworkUpgrades{ SubnetEVMTimestamp: big.NewInt(1000), }, } diff --git a/params/config.go b/params/config.go index 0dc08c4e25..fdcd2d9194 100644 --- a/params/config.go +++ b/params/config.go @@ -70,26 +70,25 @@ var ( ) var ( - // SubnetEVMDefaultChainConfig is the default configuration + // SubnetEVMDefaultConfig is the default configuration + // without any network upgrades. SubnetEVMDefaultChainConfig = &ChainConfig{ ChainID: SubnetEVMChainID, FeeConfig: DefaultFeeConfig, AllowFeeRecipients: false, - HomesteadBlock: big.NewInt(0), - EIP150Block: big.NewInt(0), - EIP150Hash: common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"), - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - GenesisPrecompiles: Precompiles{}, - NetworkUpgrades: NetworkUpgrades{ - SubnetEVMTimestamp: big.NewInt(0), - }, + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP150Hash: common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"), + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + MandatoryNetworkUpgrades: MainnetNetworkUpgrades, // This can be changed to correct network (local, test) via VM. + GenesisPrecompiles: Precompiles{}, } TestChainConfig = &ChainConfig{ @@ -107,14 +106,37 @@ var ( PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0), - NetworkUpgrades: NetworkUpgrades{big.NewInt(0)}, - GenesisPrecompiles: Precompiles{}, - UpgradeConfig: UpgradeConfig{}, + MandatoryNetworkUpgrades: MandatoryNetworkUpgrades{ + SubnetEVMTimestamp: big.NewInt(0), + DUpgradeTimestamp: big.NewInt(0), + }, + GenesisPrecompiles: Precompiles{}, + UpgradeConfig: UpgradeConfig{}, } TestPreSubnetEVMConfig = &ChainConfig{ + AvalancheContext: AvalancheContext{snow.DefaultContextTest()}, + ChainID: big.NewInt(1), + FeeConfig: DefaultFeeConfig, + AllowFeeRecipients: false, + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP150Hash: common.Hash{}, + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + MandatoryNetworkUpgrades: MandatoryNetworkUpgrades{}, + GenesisPrecompiles: Precompiles{}, + UpgradeConfig: UpgradeConfig{}, + } + + SimulatedTestChainConfig = &ChainConfig{ AvalancheContext: AvalancheContext{snow.DefaultContextTest()}, - ChainID: big.NewInt(1), + ChainID: big.NewInt(1337), FeeConfig: DefaultFeeConfig, AllowFeeRecipients: false, HomesteadBlock: big.NewInt(0), @@ -127,9 +149,12 @@ var ( PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0), - NetworkUpgrades: NetworkUpgrades{}, - GenesisPrecompiles: Precompiles{}, - UpgradeConfig: UpgradeConfig{}, + MandatoryNetworkUpgrades: MandatoryNetworkUpgrades{ + SubnetEVMTimestamp: big.NewInt(0), + DUpgradeTimestamp: big.NewInt(0), + }, + GenesisPrecompiles: Precompiles{}, + UpgradeConfig: UpgradeConfig{}, } ) @@ -137,10 +162,10 @@ var ( // - Timestamps that enable avalanche network upgrades, // - Enabling or disabling precompiles as network upgrades. type UpgradeConfig struct { - // Config for blocks/timestamps that enable network upgrades. - // Note: if NetworkUpgrades is specified in the JSON all previously activated + // Config for optional timestamps that enable network upgrades. + // Note: if OptionalUpgrades is specified in the JSON all previously activated // forks must be present or upgradeBytes will be rejected. - NetworkUpgrades *NetworkUpgrades `json:"networkUpgrades,omitempty"` + OptionalNetworkUpgrades *OptionalNetworkUpgrades `json:"networkUpgrades,omitempty"` // Config for modifying state as a network upgrade. StateUpgrades []StateUpgrade `json:"stateUpgrades,omitempty"` @@ -181,9 +206,10 @@ type ChainConfig struct { IstanbulBlock *big.Int `json:"istanbulBlock,omitempty"` // Istanbul switch block (nil = no fork, 0 = already on istanbul) MuirGlacierBlock *big.Int `json:"muirGlacierBlock,omitempty"` // Eip-2384 (bomb delay) switch block (nil = no fork, 0 = already activated) - NetworkUpgrades // Config for timestamps that enable avalanche network upgrades - GenesisPrecompiles Precompiles `json:"-"` // Config for enabling precompiles from genesis. JSON encode/decode will be handled by the custom marshaler/unmarshaler. - UpgradeConfig `json:"-"` // Config specified in upgradeBytes (avalanche network upgrades or enable/disabling precompiles). Skip encoding/decoding directly into ChainConfig. + MandatoryNetworkUpgrades // Config for timestamps that enable mandatory network upgrades. Skip encoding/decoding directly into ChainConfig. + OptionalNetworkUpgrades // Config for optional timestamps that enable network upgrades + GenesisPrecompiles Precompiles `json:"-"` // Config for enabling precompiles from genesis. JSON encode/decode will be handled by the custom marshaler/unmarshaler. + UpgradeConfig `json:"-"` // Config specified in upgradeBytes (avalanche network upgrades or enable/disabling precompiles). Skip encoding/decoding directly into ChainConfig. } // UnmarshalJSON parses the JSON-encoded data and stores the result in the @@ -241,9 +267,13 @@ func (c *ChainConfig) String() string { if err != nil { feeBytes = []byte("cannot marshal FeeConfig") } - networkUpgradesBytes, err := json.Marshal(c.NetworkUpgrades) + networkUpgradesBytes, err := json.Marshal(c.MandatoryNetworkUpgrades) + if err != nil { + networkUpgradesBytes = []byte("cannot marshal MandatoryNetworkUpgrades") + } + optionalNetworkUpgradeBytes, err := json.Marshal(c.OptionalNetworkUpgrades) if err != nil { - networkUpgradesBytes = []byte("cannot marshal NetworkUpgrades") + optionalNetworkUpgradeBytes = []byte("cannot marshal OptionalNetworkUpgrades") } precompileUpgradeBytes, err := json.Marshal(c.GenesisPrecompiles) if err != nil { @@ -254,7 +284,7 @@ func (c *ChainConfig) String() string { upgradeConfigBytes = []byte("cannot marshal UpgradeConfig") } - return fmt.Sprintf("{ChainID: %v Homestead: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Subnet EVM: %v, FeeConfig: %v, AllowFeeRecipients: %v, NetworkUpgrades: %v, PrecompileUpgrade: %v, UpgradeConfig: %v, Engine: Dummy Consensus Engine}", + return fmt.Sprintf("{ChainID: %v Homestead: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Subnet EVM: %v, DUpgrade: %v, FeeConfig: %v, AllowFeeRecipients: %v, MandatoryNetworkUpgrades: %v, OptionalNetworkUprades: %v, PrecompileUpgrade: %v, UpgradeConfig: %v, Engine: Dummy Consensus Engine}", c.ChainID, c.HomesteadBlock, c.EIP150Block, @@ -266,9 +296,11 @@ func (c *ChainConfig) String() string { c.IstanbulBlock, c.MuirGlacierBlock, c.SubnetEVMTimestamp, + c.DUpgradeTimestamp, string(feeBytes), c.AllowFeeRecipients, string(networkUpgradesBytes), + string(optionalNetworkUpgradeBytes), string(precompileUpgradeBytes), string(upgradeConfigBytes), ) @@ -323,7 +355,7 @@ func (c *ChainConfig) IsIstanbul(num *big.Int) bool { // IsSubnetEVM returns whether [blockTimestamp] is either equal to the SubnetEVM fork block timestamp or greater. func (c *ChainConfig) IsSubnetEVM(blockTimestamp *big.Int) bool { - return utils.IsForked(c.getNetworkUpgrades().SubnetEVMTimestamp, blockTimestamp) + return utils.IsForked(c.SubnetEVMTimestamp, blockTimestamp) } func (r *Rules) PredicatesExist() bool { @@ -383,16 +415,16 @@ func (c *ChainConfig) Verify() error { return nil } +type fork struct { + name string + block *big.Int + optional bool // if true, the fork may be nil and next fork is still allowed +} + // CheckConfigForkOrder checks that we don't "skip" any forks, geth isn't pluggable enough // to guarantee that forks can be implemented in a different order than on official networks func (c *ChainConfig) CheckConfigForkOrder() error { - type fork struct { - name string - block *big.Int - optional bool // if true, the fork may be nil and next fork is still allowed - } - var lastFork fork - for _, cur := range []fork{ + ethForks := []fork{ {name: "homesteadBlock", block: c.HomesteadBlock}, {name: "eip150Block", block: c.EIP150Block}, {name: "eip155Block", block: c.EIP155Block}, @@ -402,27 +434,11 @@ func (c *ChainConfig) CheckConfigForkOrder() error { {name: "petersburgBlock", block: c.PetersburgBlock}, {name: "istanbulBlock", block: c.IstanbulBlock}, {name: "muirGlacierBlock", block: c.MuirGlacierBlock, optional: true}, - } { - if cur.block != nil && common.Big0.Cmp(cur.block) != 0 { - return errNonGenesisForkByHeight - } - if lastFork.name != "" { - // Next one must be higher number - if lastFork.block == nil && cur.block != nil { - return fmt.Errorf("unsupported fork ordering: %v not enabled, but %v enabled at %v", - lastFork.name, cur.name, cur.block) - } - if lastFork.block != nil && cur.block != nil { - if lastFork.block.Cmp(cur.block) > 0 { - return fmt.Errorf("unsupported fork ordering: %v enabled at %v, but %v enabled at %v", - lastFork.name, lastFork.block, cur.name, cur.block) - } - } - } - // If it was optional and not set, then ignore it - if !cur.optional || cur.block != nil { - lastFork = cur - } + } + + // Check that forks are enabled in order + if err := checkForks(ethForks, true); err != nil { + return err } // Note: In Avalanche, hard forks must take place via block timestamps instead @@ -433,10 +449,24 @@ func (c *ChainConfig) CheckConfigForkOrder() error { // Note: we do not add the optional stateful precompile configs in here because they are optional // and independent, such that the ordering they are enabled does not impact the correctness of the // chain config. - lastFork = fork{} - for _, cur := range []fork{ - {name: "subnetEVMTimestamp", block: c.SubnetEVMTimestamp}, - } { + if err := checkForks(c.mandatoryForkOrder(), false); err != nil { + return err + } + + // Check optional forks are enabled in order + if err := checkForks(c.optionalForkOrder(), false); err != nil { + return err + } + + return nil +} + +func checkForks(forks []fork, heightFork bool) error { + lastFork := fork{} + for _, cur := range forks { + if heightFork && cur.block != nil && common.Big0.Cmp(cur.block) != 0 { + return errNonGenesisForkByHeight + } if lastFork.name != "" { // Next one must be higher number if lastFork.block == nil && cur.block != nil { @@ -497,15 +527,20 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, lastHeight *big.Int, return newCompatError("Muir Glacier fork block", c.MuirGlacierBlock, newcfg.MuirGlacierBlock) } + // Check avalanhe network upgrades + if err := c.CheckMandatoryCompatible(&newcfg.MandatoryNetworkUpgrades, lastTimestamp); err != nil { + return err + } + // Check subnet-evm specific activations - newNetworkUpgrades := newcfg.getNetworkUpgrades() - if c.UpgradeConfig.NetworkUpgrades != nil && newcfg.UpgradeConfig.NetworkUpgrades == nil { - // Note: if the current NetworkUpgrades are set via UpgradeConfig, then a new config - // without NetworkUpgrades will be treated as having specified an empty set of network + newOptionalNetworkUpgrades := newcfg.getOptionalNetworkUpgrades() + if c.UpgradeConfig.OptionalNetworkUpgrades != nil && newcfg.UpgradeConfig.OptionalNetworkUpgrades == nil { + // Note: if the current OptionalNetworkUpgrades are set via UpgradeConfig, then a new config + // without OptionalNetworkUpgrades will be treated as having specified an empty set of network // upgrades (ie., treated as the user intends to cancel scheduled forks) - newNetworkUpgrades = &NetworkUpgrades{} + newOptionalNetworkUpgrades = &OptionalNetworkUpgrades{} } - if err := c.getNetworkUpgrades().CheckCompatible(newNetworkUpgrades, lastTimestamp); err != nil { + if err := c.getOptionalNetworkUpgrades().CheckOptionalCompatible(newOptionalNetworkUpgrades, lastTimestamp); err != nil { return err } @@ -523,13 +558,13 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, lastHeight *big.Int, return nil } -// getNetworkUpgrades returns NetworkUpgrades from upgrade config if set there, +// getOptionalNetworkUpgrades returns OptionalNetworkUpgrades from upgrade config if set there, // otherwise it falls back to the genesis chain config. -func (c *ChainConfig) getNetworkUpgrades() *NetworkUpgrades { - if upgradeConfigOverride := c.UpgradeConfig.NetworkUpgrades; upgradeConfigOverride != nil { +func (c *ChainConfig) getOptionalNetworkUpgrades() *OptionalNetworkUpgrades { + if upgradeConfigOverride := c.UpgradeConfig.OptionalNetworkUpgrades; upgradeConfigOverride != nil { return upgradeConfigOverride } - return &c.NetworkUpgrades + return &c.OptionalNetworkUpgrades } // isForkIncompatible returns true if a fork scheduled at s1 cannot be rescheduled to diff --git a/params/config_test.go b/params/config_test.go index 12d7b8beb2..009b9428b1 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -232,21 +232,21 @@ func TestActivePrecompiles(t *testing.T) { func TestChainConfigMarshalWithUpgrades(t *testing.T) { config := ChainConfigWithUpgradesJSON{ ChainConfig: ChainConfig{ - ChainID: big.NewInt(1), - FeeConfig: DefaultFeeConfig, - AllowFeeRecipients: false, - HomesteadBlock: big.NewInt(0), - EIP150Block: big.NewInt(0), - EIP150Hash: common.Hash{}, - EIP155Block: big.NewInt(0), - EIP158Block: big.NewInt(0), - ByzantiumBlock: big.NewInt(0), - ConstantinopleBlock: big.NewInt(0), - PetersburgBlock: big.NewInt(0), - IstanbulBlock: big.NewInt(0), - MuirGlacierBlock: big.NewInt(0), - NetworkUpgrades: NetworkUpgrades{big.NewInt(0)}, - GenesisPrecompiles: Precompiles{}, + ChainID: big.NewInt(1), + FeeConfig: DefaultFeeConfig, + AllowFeeRecipients: false, + HomesteadBlock: big.NewInt(0), + EIP150Block: big.NewInt(0), + EIP150Hash: common.Hash{}, + EIP155Block: big.NewInt(0), + EIP158Block: big.NewInt(0), + ByzantiumBlock: big.NewInt(0), + ConstantinopleBlock: big.NewInt(0), + PetersburgBlock: big.NewInt(0), + IstanbulBlock: big.NewInt(0), + MuirGlacierBlock: big.NewInt(0), + MandatoryNetworkUpgrades: MandatoryNetworkUpgrades{big.NewInt(0), big.NewInt(0)}, + GenesisPrecompiles: Precompiles{}, }, UpgradeConfig: UpgradeConfig{ PrecompileUpgrades: []PrecompileUpgrade{ @@ -258,7 +258,40 @@ func TestChainConfigMarshalWithUpgrades(t *testing.T) { } result, err := json.Marshal(&config) require.NoError(t, err) - expectedJSON := `{"chainId":1,"feeConfig":{"gasLimit":8000000,"targetBlockRate":2,"minBaseFee":25000000000,"targetGas":15000000,"baseFeeChangeDenominator":36,"minBlockGasCost":0,"maxBlockGasCost":1000000,"blockGasCostStep":200000},"homesteadBlock":0,"eip150Block":0,"eip150Hash":"0x0000000000000000000000000000000000000000000000000000000000000000","eip155Block":0,"eip158Block":0,"byzantiumBlock":0,"constantinopleBlock":0,"petersburgBlock":0,"istanbulBlock":0,"muirGlacierBlock":0,"subnetEVMTimestamp":0,"upgrades":{"precompileUpgrades":[{"txAllowListConfig":{"blockTimestamp":100}}]}}` + expectedJSON := `{ + "chainId": 1, + "feeConfig": { + "gasLimit": 8000000, + "targetBlockRate": 2, + "minBaseFee": 25000000000, + "targetGas": 15000000, + "baseFeeChangeDenominator": 36, + "minBlockGasCost": 0, + "maxBlockGasCost": 1000000, + "blockGasCostStep": 200000 + }, + "homesteadBlock": 0, + "eip150Block": 0, + "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "subnetEVMTimestamp": 0, + "dUpgradeTimestamp": 0, + "upgrades": { + "precompileUpgrades": [ + { + "txAllowListConfig": { + "blockTimestamp": 100 + } + } + ] + } + }` require.JSONEq(t, expectedJSON, string(result)) var unmarshalled ChainConfigWithUpgradesJSON diff --git a/params/network_upgrades.go b/params/network_upgrades.go index 9d91ec9327..329fff48da 100644 --- a/params/network_upgrades.go +++ b/params/network_upgrades.go @@ -5,18 +5,74 @@ package params import ( "math/big" + + "github.com/ava-labs/avalanchego/utils/constants" +) + +var ( + LocalNetworkUpgrades = MandatoryNetworkUpgrades{ + SubnetEVMTimestamp: big.NewInt(0), + DUpgradeTimestamp: big.NewInt(0), + } + + FujiNetworkUpgrades = MandatoryNetworkUpgrades{ + SubnetEVMTimestamp: big.NewInt(0), + // DUpgradeTimestamp: big.NewInt(0), // TODO: Uncomment and set this to the correct value + } + + MainnetNetworkUpgrades = MandatoryNetworkUpgrades{ + SubnetEVMTimestamp: big.NewInt(0), + // DUpgradeTimestamp: big.NewInt(0), // TODO: Uncomment and set this to the correct value + } ) -// NetworkUpgrades contains timestamps that enable avalanche network upgrades. -type NetworkUpgrades struct { - SubnetEVMTimestamp *big.Int `json:"subnetEVMTimestamp,omitempty"` // A placeholder for the latest avalanche forks (nil = no fork, 0 = already activated) +// MandatoryNetworkUpgrades contains timestamps that enable mandatory network upgrades. +// These upgrades are mandatory, meaning that if a node does not upgrade by the +// specified timestamp, it will be unable to participate in consensus. +// Avalanche specific network upgrades are also included here. +type MandatoryNetworkUpgrades struct { + SubnetEVMTimestamp *big.Int `json:"subnetEVMTimestamp,omitempty"` // initial subnet-evm upgrade (nil = no fork, 0 = already activated) + DUpgradeTimestamp *big.Int `json:"dUpgradeTimestamp,omitempty"` // A placeholder for the latest avalanche forks (nil = no fork, 0 = already activated) +} + +func (m *MandatoryNetworkUpgrades) CheckMandatoryCompatible(newcfg *MandatoryNetworkUpgrades, headTimestamp *big.Int) *ConfigCompatError { + if isForkIncompatible(m.SubnetEVMTimestamp, newcfg.SubnetEVMTimestamp, headTimestamp) { + return newCompatError("SubnetEVM fork block timestamp", m.SubnetEVMTimestamp, newcfg.SubnetEVMTimestamp) + } + if isForkIncompatible(m.DUpgradeTimestamp, newcfg.DUpgradeTimestamp, headTimestamp) { + return newCompatError("DUpgrade fork block timestamp", m.DUpgradeTimestamp, newcfg.DUpgradeTimestamp) + } + return nil +} + +func (m *MandatoryNetworkUpgrades) mandatoryForkOrder() []fork { + return []fork{ + {name: "subnetEVMTimestamp", block: m.SubnetEVMTimestamp}, + {name: "dUpgradeTimestamp", block: m.DUpgradeTimestamp}, + } } -func (n *NetworkUpgrades) CheckCompatible(newcfg *NetworkUpgrades, headTimestamp *big.Int) *ConfigCompatError { - // Check subnet-evm specific activations - if isForkIncompatible(n.SubnetEVMTimestamp, newcfg.SubnetEVMTimestamp, headTimestamp) { - return newCompatError("SubnetEVM fork block timestamp", n.SubnetEVMTimestamp, newcfg.SubnetEVMTimestamp) +func GetMandatoryNetworkUpgrades(networkID uint32) MandatoryNetworkUpgrades { + switch networkID { + case constants.FujiID: + return FujiNetworkUpgrades + case constants.MainnetID: + return MainnetNetworkUpgrades + default: + return LocalNetworkUpgrades } +} + +// OptionalNetworkUpgrades includes overridable and optional Subnet-EVM network upgrades. +// These can be specified in genesis and upgrade configs. +// Timestamps can be different for each subnet network. +// TODO: once we add the first optional upgrade here, we should uncomment TestVMUpgradeBytesOptionalNetworkUpgrades +type OptionalNetworkUpgrades struct{} +func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetworkUpgrades, headTimestamp *big.Int) *ConfigCompatError { return nil } + +func (n *OptionalNetworkUpgrades) optionalForkOrder() []fork { + return []fork{} +} diff --git a/params/precompile_config_test.go b/params/precompile_config_test.go index 8d634b34d1..524e4ee78c 100644 --- a/params/precompile_config_test.go +++ b/params/precompile_config_test.go @@ -20,7 +20,7 @@ import ( func TestVerifyWithChainConfig(t *testing.T) { admins := []common.Address{{1}} - baseConfig := *SubnetEVMDefaultChainConfig + baseConfig := *TestChainConfig config := &baseConfig config.GenesisPrecompiles = Precompiles{ txallowlist.ConfigKey: txallowlist.NewConfig(big.NewInt(2), nil, nil), @@ -65,7 +65,7 @@ func TestVerifyWithChainConfig(t *testing.T) { func TestVerifyWithChainConfigAtNilTimestamp(t *testing.T) { admins := []common.Address{{0}} - baseConfig := *SubnetEVMDefaultChainConfig + baseConfig := *TestChainConfig config := &baseConfig config.PrecompileUpgrades = []PrecompileUpgrade{ // this does NOT enable the precompile, so it should be upgradeable. @@ -185,7 +185,7 @@ func TestVerifyPrecompileUpgrades(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { require := require.New(t) - baseConfig := *SubnetEVMDefaultChainConfig + baseConfig := *TestChainConfig config := &baseConfig config.PrecompileUpgrades = tt.upgrades @@ -229,7 +229,7 @@ func TestVerifyPrecompiles(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { require := require.New(t) - baseConfig := *SubnetEVMDefaultChainConfig + baseConfig := *TestChainConfig config := &baseConfig config.GenesisPrecompiles = tt.precompiles @@ -245,7 +245,7 @@ func TestVerifyPrecompiles(t *testing.T) { func TestVerifyRequiresSortedTimestamps(t *testing.T) { admins := []common.Address{{1}} - baseConfig := *SubnetEVMDefaultChainConfig + baseConfig := *TestChainConfig config := &baseConfig config.PrecompileUpgrades = []PrecompileUpgrade{ { @@ -263,7 +263,7 @@ func TestVerifyRequiresSortedTimestamps(t *testing.T) { func TestGetPrecompileConfig(t *testing.T) { require := require.New(t) - baseConfig := *SubnetEVMDefaultChainConfig + baseConfig := *TestChainConfig config := &baseConfig config.GenesisPrecompiles = Precompiles{ deployerallowlist.ConfigKey: deployerallowlist.NewConfig(big.NewInt(10), nil, nil), diff --git a/params/state_upgrade_test.go b/params/state_upgrade_test.go index 5009a82bc4..dd96be3d88 100644 --- a/params/state_upgrade_test.go +++ b/params/state_upgrade_test.go @@ -58,7 +58,7 @@ func TestVerifyStateUpgrades(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { require := require.New(t) - baseConfig := *SubnetEVMDefaultChainConfig + baseConfig := *TestChainConfig config := &baseConfig config.StateUpgrades = tt.upgrades diff --git a/plugin/evm/config.go b/plugin/evm/config.go index 1032a896eb..9d76f844ce 100644 --- a/plugin/evm/config.go +++ b/plugin/evm/config.go @@ -197,9 +197,6 @@ type Config struct { // identical state with the pre-upgrade ruleset. SkipUpgradeCheck bool `json:"skip-upgrade-check"` - // SkipSubnetEVMUpgradeCheck disables checking that SubnetEVM Upgrade is enabled at genesis - SkipSubnetEVMUpgradeCheck bool `json:"skip-subnet-evm-upgrade-check"` - // AcceptedCacheSize is the depth to keep in the accepted headers cache and the // accepted logs cache at the accepted tip. // diff --git a/plugin/evm/tx_gossiping_test.go b/plugin/evm/tx_gossiping_test.go index c2978db73f..82573e348c 100644 --- a/plugin/evm/tx_gossiping_test.go +++ b/plugin/evm/tx_gossiping_test.go @@ -43,7 +43,8 @@ func fundAddressByGenesis(addrs []common.Address) (string, error) { } } genesis.Alloc = funds - genesis.Config = params.TestChainConfig + cpcfg := *params.TestChainConfig + genesis.Config = &cpcfg bytes, err := json.Marshal(genesis) return string(bytes), err diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 63e0213ed7..af19c1c861 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -114,14 +114,13 @@ var ( ) var ( - errEmptyBlock = errors.New("empty block") - errUnsupportedFXs = errors.New("unsupported feature extensions") - errInvalidBlock = errors.New("invalid block") - errInvalidNonce = errors.New("invalid nonce") - errUnclesUnsupported = errors.New("uncles unsupported") - errNilBaseFeeSubnetEVM = errors.New("nil base fee is invalid after subnetEVM") - errNilBlockGasCostSubnetEVM = errors.New("nil blockGasCost is invalid after subnetEVM") - errSubnetEVMUpgradeNotEnabled = errors.New("SubnetEVM upgrade is not enabled in genesis") + errEmptyBlock = errors.New("empty block") + errUnsupportedFXs = errors.New("unsupported feature extensions") + errInvalidBlock = errors.New("invalid block") + errInvalidNonce = errors.New("invalid nonce") + errUnclesUnsupported = errors.New("uncles unsupported") + errNilBaseFeeSubnetEVM = errors.New("nil base fee is invalid after subnetEVM") + errNilBlockGasCostSubnetEVM = errors.New("nil blockGasCost is invalid after subnetEVM") ) // legacyApiNames maps pre geth v1.10.20 api names to their updated counterparts. @@ -290,6 +289,10 @@ func (vm *VM) Initialize( g.Config = params.SubnetEVMDefaultChainConfig } + // We enforce network upgrades here, regardless of the chain config + // provided in the genesis file. + g.Config.MandatoryNetworkUpgrades = params.GetMandatoryNetworkUpgrades(chainCtx.NetworkID) + // Load airdrop file if provided if vm.config.AirdropFile != "" { g.AirdropData, err = os.ReadFile(vm.config.AirdropFile) @@ -310,6 +313,11 @@ func (vm *VM) Initialize( vm.ethConfig = ethconfig.NewDefaultConfig() vm.ethConfig.Genesis = g + // NetworkID here is different than Avalanche's NetworkID. + // Avalanche's NetworkID represents the Avalanche network is running on + // like Fuji, Mainnet, Local, etc. + // The NetworkId here is kept same as ChainID to be compatible with + // Ethereum tooling. vm.ethConfig.NetworkId = g.Config.ChainID.Uint64() // Set minimum price for mining and default gas price oracle value to the min @@ -376,14 +384,6 @@ func (vm *VM) Initialize( vm.chainConfig = g.Config vm.networkID = vm.ethConfig.NetworkId - // TODO: remove SkipSubnetEVMUpgradeCheck after next network upgrade - if !vm.config.SkipSubnetEVMUpgradeCheck { - // check that subnetEVM upgrade is enabled from genesis before upgradeBytes - if !vm.chainConfig.IsSubnetEVM(common.Big0) { - return errSubnetEVMUpgradeNotEnabled - } - } - // Apply upgradeBytes (if any) by unmarshalling them into [chainConfig.UpgradeConfig]. // Initializing the chain will verify upgradeBytes are compatible with existing values. if len(upgradeBytes) > 0 { diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index ca30cccac2..7acecb0023 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -77,10 +77,9 @@ var ( password = "CjasdjhiPeirbSenfeI13" // #nosec G101 // Use chainId: 43111, so that it does not overlap with any Avalanche ChainIDs, which may have their // config overridden in vm.Initialize. - genesisJSONSubnetEVMLateEnablement = "{\"config\":{\"chainId\":43111,\"homesteadBlock\":0,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0,\"subnetEVMTimestamp\":50},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x7A1200\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"0x71562b71999873DB5b286dF957af199Ec94617F7\": {\"balance\":\"0x4192927743b88000\"}, \"0x703c4b2bD70c169f5717101CaeE543299Fc946C7\": {\"balance\":\"0x4192927743b88000\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}" - genesisJSONSubnetEVM = "{\"config\":{\"chainId\":43111,\"homesteadBlock\":0,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0,\"subnetEVMTimestamp\":0},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x7A1200\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"0x71562b71999873DB5b286dF957af199Ec94617F7\": {\"balance\":\"0x4192927743b88000\"}, \"0x703c4b2bD70c169f5717101CaeE543299Fc946C7\": {\"balance\":\"0x4192927743b88000\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}" - genesisJSONPreSubnetEVM = "{\"config\":{\"chainId\":43111,\"homesteadBlock\":0,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x7A1200\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"0x71562b71999873DB5b286dF957af199Ec94617F7\": {\"balance\":\"0x4192927743b88000\"}, \"0x703c4b2bD70c169f5717101CaeE543299Fc946C7\": {\"balance\":\"0x4192927743b88000\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}" - genesisJSONLatest = genesisJSONSubnetEVM + genesisJSONSubnetEVM = "{\"config\":{\"chainId\":43111,\"homesteadBlock\":0,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0,\"subnetEVMTimestamp\":0},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x7A1200\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"0x71562b71999873DB5b286dF957af199Ec94617F7\": {\"balance\":\"0x4192927743b88000\"}, \"0x703c4b2bD70c169f5717101CaeE543299Fc946C7\": {\"balance\":\"0x4192927743b88000\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}" + genesisJSONPreSubnetEVM = "{\"config\":{\"chainId\":43111,\"homesteadBlock\":0,\"eip150Block\":0,\"eip150Hash\":\"0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0},\"nonce\":\"0x0\",\"timestamp\":\"0x0\",\"extraData\":\"0x00\",\"gasLimit\":\"0x7A1200\",\"difficulty\":\"0x0\",\"mixHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"coinbase\":\"0x0000000000000000000000000000000000000000\",\"alloc\":{\"0x71562b71999873DB5b286dF957af199Ec94617F7\": {\"balance\":\"0x4192927743b88000\"}, \"0x703c4b2bD70c169f5717101CaeE543299Fc946C7\": {\"balance\":\"0x4192927743b88000\"}},\"number\":\"0x0\",\"gasUsed\":\"0x0\",\"parentHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}" + genesisJSONLatest = genesisJSONSubnetEVM firstTxAmount *big.Int genesisBalance *big.Int @@ -387,57 +386,6 @@ func issueAndAccept(t *testing.T, issuer <-chan commonEng.Message, vm *VM) snowm return blk } -func TestSubnetEVMUpgradeRequiredAtGenesis(t *testing.T) { - genesisTests := []struct { - genesisJSON string - configJSON string - expectedErr error - }{ - { - // we expect an error when subnet evm upgrade is nil in chain config - genesisJSON: genesisJSONPreSubnetEVM, - configJSON: "", - expectedErr: errSubnetEVMUpgradeNotEnabled, - }, - { - // we expect an error when subnet evm upgrade is not enabled at genesis and at a later block instead - genesisJSON: genesisJSONSubnetEVMLateEnablement, - configJSON: "", - expectedErr: errSubnetEVMUpgradeNotEnabled, - }, - { - // we do not expect an err when skip-subnet-evm-upgrade-check is set to true - genesisJSON: genesisJSONPreSubnetEVM, - configJSON: "{\"skip-subnet-evm-upgrade-check\": true}", - expectedErr: nil, - }, - { - // we do not expect an err when skip-subnet-evm-upgrade-check is set to true - genesisJSON: genesisJSONSubnetEVMLateEnablement, - configJSON: "{\"skip-subnet-evm-upgrade-check\": true}", - expectedErr: nil, - }, - } - - for _, test := range genesisTests { - ctx, dbManager, genesisBytes, issuer, _ := setupGenesis(t, test.genesisJSON) - vm := &VM{} - err := vm.Initialize( - context.Background(), - ctx, - dbManager, - genesisBytes, - []byte(""), - []byte(test.configJSON), - issuer, - []*commonEng.Fx{}, - nil, - ) - - require.ErrorIs(t, err, test.expectedErr) - } -} - func TestBuildEthTxBlock(t *testing.T) { // reduce block gas cost issuer, vm, dbManager, _ := GenesisVM(t, true, genesisJSONSubnetEVM, "{\"pruning-enabled\":true}", "") @@ -3016,6 +2964,28 @@ func TestSkipChainConfigCheckCompatible(t *testing.T) { require.NoError(t, reinitVM.Shutdown(context.Background())) } +func TestMandatoryUpgrades(t *testing.T) { + modifiedSubnetEVMGenesis := &core.Genesis{} + err := json.Unmarshal([]byte(genesisJSONSubnetEVM), &modifiedSubnetEVMGenesis) + require.NoError(t, err) + modifiedSubnetEVMGenesis.Config.SubnetEVMTimestamp = big.NewInt(1) + modifiedSubnetEVMGenesisBytes, err := json.Marshal(modifiedSubnetEVMGenesis) + modifiedSubnetEVMGenesisString := string(modifiedSubnetEVMGenesisBytes) + require.NoError(t, err) + require.Contains(t, modifiedSubnetEVMGenesisString, `"subnetEVMTimestamp":1`) + // use modified genesis to set SubnetEVM timestamp to 1 + _, vm, _, _ := GenesisVM(t, true, modifiedSubnetEVMGenesisString, "", "") + + defer func() { + if err := vm.Shutdown(context.Background()); err != nil { + t.Fatal(err) + } + }() + + // modification to genesis for mandatory upgrades should have no effect on the VM + require.Equal(t, vm.chainConfig.SubnetEVMTimestamp, big.NewInt(0)) +} + func TestCrossChainMessagestoVM(t *testing.T) { crossChainCodec := message.CrossChainCodec require := require.New(t) diff --git a/plugin/evm/vm_upgrade_bytes_test.go b/plugin/evm/vm_upgrade_bytes_test.go index c5957a0dda..7f5424d4d3 100644 --- a/plugin/evm/vm_upgrade_bytes_test.go +++ b/plugin/evm/vm_upgrade_bytes_test.go @@ -157,76 +157,81 @@ func TestVMUpgradeBytesPrecompile(t *testing.T) { assert.Equal(t, signedTx1.Hash(), txs[0].Hash()) } -func TestVMUpgradeBytesNetworkUpgrades(t *testing.T) { - // Hack: registering metrics uses global variables, so we need to disable metrics here so that we can initialize the VM twice. - metrics.Enabled = false - defer func() { - metrics.Enabled = true - }() - - // Get a json specifying a Network upgrade at genesis - // to apply as upgradeBytes. - subnetEVMTimestamp := time.Unix(10, 0) - upgradeConfig := ¶ms.UpgradeConfig{ - NetworkUpgrades: ¶ms.NetworkUpgrades{ - SubnetEVMTimestamp: big.NewInt(subnetEVMTimestamp.Unix()), - }, - } - upgradeBytesJSON, err := json.Marshal(upgradeConfig) - if err != nil { - t.Fatalf("could not marshal upgradeConfig to json: %s", err) - } - configJSON := "{\"skip-subnet-evm-upgrade-check\": true}" - - // initialize the VM with these upgrade bytes - issuer, vm, dbManager, appSender := GenesisVM(t, true, genesisJSONPreSubnetEVM, configJSON, string(upgradeBytesJSON)) - vm.clock.Set(subnetEVMTimestamp) - - // verify upgrade is applied - if !vm.chainConfig.IsSubnetEVM(big.NewInt(subnetEVMTimestamp.Unix())) { - t.Fatal("expected subnet-evm network upgrade to have been enabled") - } - - // Submit a successful transaction and build a block to move the chain head past the SubnetEVMTimestamp network upgrade - tx0 := types.NewTransaction(uint64(0), testEthAddrs[0], big.NewInt(1), 21000, big.NewInt(testMinGasPrice), nil) - signedTx0, err := types.SignTx(tx0, types.NewEIP155Signer(vm.chainConfig.ChainID), testKeys[0]) - assert.NoError(t, err) - errs := vm.txPool.AddRemotesSync([]*types.Transaction{signedTx0}) - if err := errs[0]; err != nil { - t.Fatalf("Failed to add tx at index: %s", err) - } - - issueAndAccept(t, issuer, vm) // make a block - - if err := vm.Shutdown(context.Background()); err != nil { - t.Fatal(err) - } - - // VM should not start again without proper upgrade bytes. - err = vm.Initialize(context.Background(), vm.ctx, dbManager, []byte(genesisJSONPreSubnetEVM), []byte{}, []byte{}, issuer, []*commonEng.Fx{}, appSender) - assert.ErrorContains(t, err, "mismatching SubnetEVM fork block timestamp in database") - - // VM should not start if fork is moved back - upgradeConfig.NetworkUpgrades.SubnetEVMTimestamp = big.NewInt(2) - upgradeBytesJSON, err = json.Marshal(upgradeConfig) - if err != nil { - t.Fatalf("could not marshal upgradeConfig to json: %s", err) - } - err = vm.Initialize(context.Background(), vm.ctx, dbManager, []byte(genesisJSONPreSubnetEVM), upgradeBytesJSON, []byte{}, issuer, []*commonEng.Fx{}, appSender) - assert.ErrorContains(t, err, "mismatching SubnetEVM fork block timestamp in database") - - // VM should not start if fork is moved forward - upgradeConfig.NetworkUpgrades.SubnetEVMTimestamp = big.NewInt(30) - upgradeBytesJSON, err = json.Marshal(upgradeConfig) - if err != nil { - t.Fatalf("could not marshal upgradeConfig to json: %s", err) - } - err = vm.Initialize(context.Background(), vm.ctx, dbManager, []byte(genesisJSONPreSubnetEVM), upgradeBytesJSON, []byte{}, issuer, []*commonEng.Fx{}, appSender) - assert.ErrorContains(t, err, "mismatching SubnetEVM fork block timestamp in database") -} +// func TestVMUpgradeBytesOptionalNetworkUpgrades(t *testing.T) { +// tests := []struct { +// name string +// setTimestampFn func(upgrade *params.UpgradeConfig, timestamp *big.Int) +// checkUpgradeFn func(config *params.ChainConfig, blockTimestamp *big.Int) bool +// }{ +// { +// name: "Test", +// setTimestampFn: func(upgrade *params.UpgradeConfig, timestamp *big.Int) { +// upgrade.OptionalNetworkUpgrades.TestTimestamp = timestamp +// }, +// checkUpgradeFn: func(config *params.ChainConfig, blockTimestamp *big.Int) bool { +// return config.IsTest(blockTimestamp) +// }, +// }, +// } +// // Hack: registering metrics uses global variables, so we need to disable metrics here so that we can initialize the VM twice. +// metrics.Enabled = false +// defer func() { +// metrics.Enabled = true +// }() +// for _, test := range tests { +// t.Run(test.name, func(t *testing.T) { +// // Get a json specifying a Network upgrade at genesis +// // to apply as upgradeBytes. +// testTimestamp := time.Unix(10, 0) +// upgradeConfig := ¶ms.UpgradeConfig{ +// OptionalNetworkUpgrades: ¶ms.OptionalNetworkUpgrades{}, +// } +// test.setTimestampFn(upgradeConfig, big.NewInt(testTimestamp.Unix())) +// upgradeBytesJSON, err := json.Marshal(upgradeConfig) +// require.NoError(t, err) + +// // initialize the VM with these upgrade bytes +// issuer, vm, dbManager, appSender := GenesisVM(t, true, genesisJSONPreSubnetEVM, "", string(upgradeBytesJSON)) +// vm.clock.Set(testTimestamp) + +// // verify upgrade is applied +// require.True(t, test.checkUpgradeFn(vm.chainConfig, big.NewInt(testTimestamp.Unix()))) + +// // Submit a successful transaction and build a block to move the chain head past the SubnetEVMTimestamp network upgrade +// tx0 := types.NewTransaction(uint64(0), testEthAddrs[0], big.NewInt(1), 21000, big.NewInt(testMinGasPrice), nil) +// signedTx0, err := types.SignTx(tx0, types.NewEIP155Signer(vm.chainConfig.ChainID), testKeys[0]) +// require.NoError(t, err) +// errs := vm.txPool.AddRemotesSync([]*types.Transaction{signedTx0}) +// require.NoError(t, errs[0]) + +// issueAndAccept(t, issuer, vm) // make a block + +// require.NoError(t, vm.Shutdown(context.Background())) +// // VM should not start again without proper upgrade bytes. +// err = vm.Initialize(context.Background(), vm.ctx, dbManager, []byte(genesisJSONPreSubnetEVM), []byte{}, []byte{}, issuer, []*commonEng.Fx{}, appSender) +// require.ErrorContains(t, err, fmt.Sprintf("mismatching %s fork block timestamp in database", test.name)) + +// // VM should not start if fork is moved back +// test.setTimestampFn(upgradeConfig, big.NewInt(2)) +// upgradeBytesJSON, err = json.Marshal(upgradeConfig) +// require.NoError(t, err) +// err = vm.Initialize(context.Background(), vm.ctx, dbManager, []byte(genesisJSONPreSubnetEVM), upgradeBytesJSON, []byte{}, issuer, []*commonEng.Fx{}, appSender) +// require.ErrorContains(t, err, fmt.Sprintf("mismatching %s fork block timestamp in database", test.name)) + +// // VM should not start if fork is moved forward +// test.setTimestampFn(upgradeConfig, big.NewInt(30)) +// upgradeBytesJSON, err = json.Marshal(upgradeConfig) +// require.NoError(t, err) +// err = vm.Initialize(context.Background(), vm.ctx, dbManager, []byte(genesisJSONPreSubnetEVM), upgradeBytesJSON, []byte{}, issuer, []*commonEng.Fx{}, appSender) +// require.ErrorContains(t, err, fmt.Sprintf("mismatching %s fork block timestamp in database", test.name)) +// }) +// } +// } func TestVMUpgradeBytesNetworkUpgradesWithGenesis(t *testing.T) { // make genesis w/ fork at block 5 + // but this should not be used because we are enforcing + // network upgrades within the code var genesis core.Genesis if err := json.Unmarshal([]byte(genesisJSONPreSubnetEVM), &genesis); err != nil { t.Fatalf("could not unmarshal genesis bytes: %s", err) @@ -238,44 +243,11 @@ func TestVMUpgradeBytesNetworkUpgradesWithGenesis(t *testing.T) { t.Fatalf("could not unmarshal genesis bytes: %s", err) } - // Get a json specifying a Network upgrade at genesis - // to apply as upgradeBytes. - subnetEVMTimestamp := time.Unix(10, 0) - upgradeConfig := ¶ms.UpgradeConfig{ - NetworkUpgrades: ¶ms.NetworkUpgrades{ - SubnetEVMTimestamp: big.NewInt(subnetEVMTimestamp.Unix()), - }, - } - upgradeBytesJSON, err := json.Marshal(upgradeConfig) - if err != nil { - t.Fatalf("could not marshal upgradeConfig to json: %s", err) - } - configJSON := "{\"skip-subnet-evm-upgrade-check\": true}" - // initialize the VM with these upgrade bytes - _, vm, _, _ := GenesisVM(t, true, string(genesisBytes), configJSON, string(upgradeBytesJSON)) + _, vm, _, _ := GenesisVM(t, true, string(genesisBytes), "", "") // verify upgrade is rescheduled - assert.False(t, vm.chainConfig.IsSubnetEVM(genesisSubnetEVMTimestamp)) - assert.True(t, vm.chainConfig.IsSubnetEVM(big.NewInt(subnetEVMTimestamp.Unix()))) - - if err := vm.Shutdown(context.Background()); err != nil { - t.Fatal(err) - } - - // abort a fork specified in genesis - upgradeConfig.NetworkUpgrades.SubnetEVMTimestamp = nil - upgradeBytesJSON, err = json.Marshal(upgradeConfig) - if err != nil { - t.Fatalf("could not marshal upgradeConfig to json: %s", err) - } - - // initialize the VM with these upgrade bytes - _, vm, _, _ = GenesisVM(t, true, string(genesisBytes), configJSON, string(upgradeBytesJSON)) - - // verify upgrade is aborted - assert.False(t, vm.chainConfig.IsSubnetEVM(genesisSubnetEVMTimestamp)) - assert.False(t, vm.chainConfig.IsSubnetEVM(big.NewInt(subnetEVMTimestamp.Unix()))) + require.True(t, vm.chainConfig.IsSubnetEVM(big.NewInt(0))) if err := vm.Shutdown(context.Background()); err != nil { t.Fatal(err) diff --git a/tests/init.go b/tests/init.go index ee2a2994a5..723f61e939 100644 --- a/tests/init.go +++ b/tests/init.go @@ -151,7 +151,7 @@ var Forks = map[string]*params.ChainConfig{ ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0), - NetworkUpgrades: params.NetworkUpgrades{ + MandatoryNetworkUpgrades: params.MandatoryNetworkUpgrades{ SubnetEVMTimestamp: big.NewInt(0), }, },