Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move network upgrade code to file #1136

Merged
merged 3 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 6 additions & 71 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"errors"
"fmt"
"math/big"
"time"

"github.com/ava-labs/avalanchego/utils/constants"
"github.com/ava-labs/subnet-evm/commontype"
Expand Down Expand Up @@ -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{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down
48 changes: 48 additions & 0 deletions params/config_extra.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ package params
import (
"encoding/json"
"errors"
"math/big"
"time"

"github.com/ava-labs/avalanchego/snow"
)
Expand Down Expand Up @@ -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
}
81 changes: 62 additions & 19 deletions params/network_upgrades.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}
Expand Down Expand Up @@ -48,22 +56,27 @@ 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
}
}

// 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
}
Expand All @@ -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
}
2 changes: 2 additions & 0 deletions plugin/evm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Loading