diff --git a/params/config.go b/params/config.go index 96b653ec34..8cee68d45d 100644 --- a/params/config.go +++ b/params/config.go @@ -31,7 +31,6 @@ import ( "errors" "fmt" "math/big" - "time" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/subnet-evm/commontype" @@ -105,12 +104,9 @@ var ( PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0), - NetworkUpgrades: NetworkUpgrades{ - SubnetEVMTimestamp: utils.NewUint64(0), - DurangoTimestamp: utils.NewUint64(0), - }, - GenesisPrecompiles: Precompiles{}, - UpgradeConfig: UpgradeConfig{}, + NetworkUpgrades: TestNetworkUpgrades, + GenesisPrecompiles: Precompiles{}, + UpgradeConfig: UpgradeConfig{}, } TestSubnetEVMConfig = &ChainConfig{ @@ -156,15 +152,6 @@ var ( TestRules = TestChainConfig.Rules(new(big.Int), 0) ) -func getUpgradeTime(networkID uint32, upgradeTimes map[uint32]time.Time) *uint64 { - if upgradeTime, ok := upgradeTimes[networkID]; ok { - return utils.TimeToNewUint64(upgradeTime) - } - // If the upgrade time isn't specified, default being enabled in the - // genesis. - return utils.NewUint64(0) -} - // ChainConfig is the core config which determines the blockchain settings. // // ChainConfig is stored in the database on a per block basis. This means @@ -227,8 +214,7 @@ func (c *ChainConfig) Description() string { banner += fmt.Sprintf(" - Cancun Timestamp: @%-10v (https://github.com/ava-labs/avalanchego/releases/tag/v1.12.0)\n", ptrToString(c.CancunTime)) banner += "Avalanche Upgrades (timestamp based):\n" - banner += fmt.Sprintf(" - SubnetEVM Timestamp: @%-10v (https://github.com/ava-labs/avalanchego/releases/tag/v1.10.0)\n", ptrToString(c.SubnetEVMTimestamp)) - banner += fmt.Sprintf(" - Durango Timestamp: @%-10v (https://github.com/ava-labs/avalanchego/releases/tag/v1.11.0)\n", ptrToString(c.DurangoTimestamp)) + banner += c.NetworkUpgrades.Description() banner += "\n" precompileUpgradeBytes, err := json.Marshal(c.GenesisPrecompiles) @@ -257,42 +243,6 @@ func (c *ChainConfig) Description() string { return banner } -func (c *ChainConfig) SetNetworkUpgradeDefaults() { - if c.HomesteadBlock == nil { - c.HomesteadBlock = big.NewInt(0) - } - if c.EIP150Block == nil { - c.EIP150Block = big.NewInt(0) - } - if c.EIP155Block == nil { - c.EIP155Block = big.NewInt(0) - } - if c.EIP158Block == nil { - c.EIP158Block = big.NewInt(0) - } - if c.ByzantiumBlock == nil { - c.ByzantiumBlock = big.NewInt(0) - } - if c.ConstantinopleBlock == nil { - c.ConstantinopleBlock = big.NewInt(0) - } - if c.PetersburgBlock == nil { - c.PetersburgBlock = big.NewInt(0) - } - if c.IstanbulBlock == nil { - c.IstanbulBlock = big.NewInt(0) - } - if c.MuirGlacierBlock == nil { - c.MuirGlacierBlock = big.NewInt(0) - } - - c.NetworkUpgrades.setDefaults(c.SnowCtx.NetworkID) - - // if c.CancunTime == nil { - // c.CancunTime = c.EUpgrade - // } -} - // IsHomestead returns whether num is either equal to the homestead block or greater. func (c *ChainConfig) IsHomestead(num *big.Int) bool { return utils.IsBlockForked(c.HomesteadBlock, num) @@ -340,19 +290,6 @@ func (c *ChainConfig) IsIstanbul(num *big.Int) bool { return utils.IsBlockForked(c.IstanbulBlock, num) } -// IsSubnetEVM returns whether [time] represents a block -// with a timestamp after the SubnetEVM upgrade time. -func (c *ChainConfig) IsSubnetEVM(time uint64) bool { - return utils.IsTimestampForked(c.SubnetEVMTimestamp, time) -} - -// TODO: move avalanche hardforks to network_upgrades.go -// IsDurango returns whether [time] represents a block -// with a timestamp after the Durango upgrade time. -func (c *ChainConfig) IsDurango(time uint64) bool { - return utils.IsTimestampForked(c.DurangoTimestamp, time) -} - // IsCancun returns whether [time] represents a block // with a timestamp after the Cancun upgrade time. func (c *ChainConfig) IsCancun(num *big.Int, time uint64) bool { @@ -676,8 +613,7 @@ type Rules struct { IsCancun bool // Rules for Avalanche releases - IsSubnetEVM bool - IsDurango bool + AvalancheRules // ActivePrecompiles maps addresses to stateful precompiled contracts that are enabled // for this rule set. @@ -723,8 +659,7 @@ func (c *ChainConfig) rules(num *big.Int, timestamp uint64) Rules { func (c *ChainConfig) Rules(blockNum *big.Int, timestamp uint64) Rules { rules := c.rules(blockNum, timestamp) - rules.IsSubnetEVM = c.IsSubnetEVM(timestamp) - rules.IsDurango = c.IsDurango(timestamp) + rules.AvalancheRules = c.GetAvalancheRules(timestamp) // Initialize the stateful precompiles that should be enabled at [blockTimestamp]. rules.ActivePrecompiles = make(map[common.Address]precompileconfig.Config) diff --git a/params/config_extra.go b/params/config_extra.go index df8f3b8912..805fd500a7 100644 --- a/params/config_extra.go +++ b/params/config_extra.go @@ -6,6 +6,8 @@ package params import ( "encoding/json" "errors" + "math/big" + "time" "github.com/ava-labs/avalanchego/snow" ) @@ -145,3 +147,49 @@ func (c *ChainConfig) ToWithUpgradesJSON() *ChainConfigWithUpgradesJSON { UpgradeConfig: c.UpgradeConfig, } } + +func (c *ChainConfig) SetNetworkUpgradeDefaults() { + if c.HomesteadBlock == nil { + c.HomesteadBlock = big.NewInt(0) + } + if c.EIP150Block == nil { + c.EIP150Block = big.NewInt(0) + } + if c.EIP155Block == nil { + c.EIP155Block = big.NewInt(0) + } + if c.EIP158Block == nil { + c.EIP158Block = big.NewInt(0) + } + if c.ByzantiumBlock == nil { + c.ByzantiumBlock = big.NewInt(0) + } + if c.ConstantinopleBlock == nil { + c.ConstantinopleBlock = big.NewInt(0) + } + if c.PetersburgBlock == nil { + c.PetersburgBlock = big.NewInt(0) + } + if c.IstanbulBlock == nil { + c.IstanbulBlock = big.NewInt(0) + } + if c.MuirGlacierBlock == nil { + c.MuirGlacierBlock = big.NewInt(0) + } + + c.NetworkUpgrades.setDefaults(c.SnowCtx.NetworkID) +} + +// SetMappedUpgrades sets the mapped upgrades (usually Avalanche > EVM upgrades) for the chain config. +func (c *ChainConfig) SetEVMUpgrades(avalancheUpgrades NetworkUpgrades) { + // c.CancunTime = utils.NewUint64(*avalancheUpgrades.EUpgradeTimestamp) +} + +func getUpgradeTime(networkID uint32, upgradeTimes map[uint32]time.Time) uint64 { + if upgradeTime, ok := upgradeTimes[networkID]; ok { + return uint64(upgradeTime.Unix()) + } + // If the upgrade time isn't specified, default being enabled in the + // genesis. + return 0 +} diff --git a/params/network_upgrades.go b/params/network_upgrades.go index ed3aa696c9..2c5f21a4ba 100644 --- a/params/network_upgrades.go +++ b/params/network_upgrades.go @@ -6,19 +6,27 @@ package params import ( "fmt" "reflect" - "strconv" "github.com/ava-labs/avalanchego/version" "github.com/ava-labs/subnet-evm/utils" ) +var ( + errCannotBeNil = fmt.Errorf("timestamp cannot be nil") + + TestNetworkUpgrades = NetworkUpgrades{ + SubnetEVMTimestamp: utils.NewUint64(0), + DurangoTimestamp: utils.NewUint64(0), + } +) + // NetworkUpgrades contains timestamps that enable network upgrades. // Avalanche specific network upgrades are also included here. type NetworkUpgrades struct { - // SubnetEVMTimestamp is a placeholder that activates Avalanche Upgrades prior to ApricotPhase6 (nil = no fork, 0 = already activated) + // SubnetEVMTimestamp is a placeholder that activates Avalanche Upgrades prior to ApricotPhase6 SubnetEVMTimestamp *uint64 `json:"subnetEVMTimestamp,omitempty"` // Durango activates the Shanghai Execution Spec Upgrade from Ethereum (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md#included-eips) - // and Avalanche Warp Messaging. (nil = no fork, 0 = already activated) + // and Avalanche Warp Messaging. // Note: EIP-4895 is excluded since withdrawals are not relevant to the Avalanche C-Chain or Subnets running the EVM. DurangoTimestamp *uint64 `json:"durangoTimestamp,omitempty"` } @@ -48,10 +56,15 @@ func (n *NetworkUpgrades) forkOrder() []fork { // This overrides deactivating the network upgrade by providing a timestamp of nil value. func (n *NetworkUpgrades) setDefaults(networkID uint32) { defaults := getDefaultNetworkUpgrades(networkID) - if n.SubnetEVMTimestamp == nil { + // If the network upgrade is not set, set it to the default value. + // If the network upgrade is set to 0, we also treat it as nil and set it default. + // This is because in prior versions, upgrades were not modifiable and were directly set to their default values. + // Most of the tools and configurations just provide these as 0, so it is safer to treat 0 as nil and set to default + // to prevent premature activations of the network upgrades for live networks. + if n.SubnetEVMTimestamp == nil || *n.SubnetEVMTimestamp == 0 { n.SubnetEVMTimestamp = defaults.SubnetEVMTimestamp } - if n.DurangoTimestamp == nil { + if n.DurangoTimestamp == nil || *n.DurangoTimestamp == 0 { n.DurangoTimestamp = defaults.DurangoTimestamp } } @@ -59,11 +72,11 @@ func (n *NetworkUpgrades) setDefaults(networkID uint32) { // VerifyNetworkUpgrades checks that the network upgrades are well formed. func (n *NetworkUpgrades) VerifyNetworkUpgrades(networkID uint32) error { defaults := getDefaultNetworkUpgrades(networkID) - if isNilOrSmaller(n.SubnetEVMTimestamp, *defaults.SubnetEVMTimestamp) { - return fmt.Errorf("SubnetEVM fork block timestamp (%v) must be greater than or equal to %v", nilOrValueStr(n.SubnetEVMTimestamp), *defaults.SubnetEVMTimestamp) + if err := verifyWithDefault(n.SubnetEVMTimestamp, defaults.SubnetEVMTimestamp); err != nil { + return fmt.Errorf("SubnetEVM fork block timestamp is invalid: %w", err) } - if isNilOrSmaller(n.DurangoTimestamp, *defaults.DurangoTimestamp) { - return fmt.Errorf("Durango fork block timestamp (%v) must be greater than or equal to %v", nilOrValueStr(n.DurangoTimestamp), *defaults.DurangoTimestamp) + if err := verifyWithDefault(n.DurangoTimestamp, defaults.DurangoTimestamp); err != nil { + return fmt.Errorf("Durango fork block timestamp is invalid: %w", err) } return nil } @@ -77,25 +90,55 @@ func (n *NetworkUpgrades) Override(o *NetworkUpgrades) { } } +// IsSubnetEVM returns whether [time] represents a block +// with a timestamp after the SubnetEVM upgrade time. +func (n *NetworkUpgrades) IsSubnetEVM(time uint64) bool { + return utils.IsTimestampForked(n.SubnetEVMTimestamp, time) +} + +// IsDurango returns whether [time] represents a block +// with a timestamp after the Durango upgrade time. +func (n *NetworkUpgrades) IsDurango(time uint64) bool { + return utils.IsTimestampForked(n.DurangoTimestamp, time) +} + +func (n *NetworkUpgrades) Description() string { + var banner string + banner += fmt.Sprintf(" - SubnetEVM Timestamp: @%-10v (https://github.com/ava-labs/avalanchego/releases/tag/v1.10.0)\n", ptrToString(n.SubnetEVMTimestamp)) + banner += fmt.Sprintf(" - Durango Timestamp: @%-10v (https://github.com/ava-labs/avalanchego/releases/tag/v1.11.0)\n", ptrToString(n.DurangoTimestamp)) + return banner +} + +type AvalancheRules struct { + IsSubnetEVM bool + IsDurango bool + IsEUpgrade bool +} + +func (n *NetworkUpgrades) GetAvalancheRules(time uint64) AvalancheRules { + return AvalancheRules{ + IsSubnetEVM: n.IsSubnetEVM(time), + IsDurango: n.IsDurango(time), + } +} + // getDefaultNetworkUpgrades returns the network upgrades for the specified network ID. // These should not return nil values. func getDefaultNetworkUpgrades(networkID uint32) NetworkUpgrades { return NetworkUpgrades{ SubnetEVMTimestamp: utils.NewUint64(0), - DurangoTimestamp: getUpgradeTime(networkID, version.DurangoTimes), + DurangoTimestamp: utils.NewUint64(getUpgradeTime(networkID, version.DurangoTimes)), } } -func isNilOrSmaller(a *uint64, b uint64) bool { - if a == nil { - return true +// verifyWithDefault checks that the provided timestamp is greater than or equal to the default timestamp. +func verifyWithDefault(configTimestamp *uint64, defaultTimestamp *uint64) error { + if configTimestamp == nil { + return errCannotBeNil } - return *a < b -} -func nilOrValueStr(a *uint64) string { - if a == nil { - return "nil" + if *configTimestamp < *defaultTimestamp { + return fmt.Errorf("provided timestamp (%d) must be greater than or equal to the default timestamp (%d)", *configTimestamp, defaultTimestamp) } - return strconv.FormatUint(*a, 10) + return nil } diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index dae61f6e0f..dd46e42251 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -369,6 +369,8 @@ func (vm *VM) Initialize( g.Config.Override(overrides) } + g.Config.SetEVMUpgrades(g.Config.NetworkUpgrades) + if err := g.Verify(); err != nil { return fmt.Errorf("failed to verify genesis: %w", err) }