From 0f72644b2332e64ad974a610f3b6b2d83c23b7ef Mon Sep 17 00:00:00 2001 From: Cesar Date: Fri, 28 Jul 2023 11:14:04 -0400 Subject: [PATCH 01/48] Add handshake codec The goal of the this codec is to serialize `params.UpgradeConfig` in a deterministic way, to be hashed later. This hash is going to be share by nodes at handshake, so they can determine if they have the same upgrade config. This PR leverages the newly introduced support to serilize Maps https://github.com/ava-labs/avalanchego/pull/1790, which are deterministic (the values are sorted by keys before serializing) --- params/config.go | 16 +-- params/network_upgrades.go | 16 ++- params/state_upgrade.go | 10 +- plugin/evm/message/handshake/codec.go | 36 ++++++ .../evm/message/handshake/upgrade_config.go | 116 ++++++++++++++++++ .../message/handshake/upgrade_config_test.go | 35 ++++++ precompile/allowlist/config.go | 6 +- precompile/contracts/feemanager/config.go | 2 +- precompile/contracts/nativeminter/config.go | 6 +- precompile/contracts/rewardmanager/config.go | 4 +- precompile/precompileconfig/upgradeable.go | 4 +- 11 files changed, 218 insertions(+), 33 deletions(-) create mode 100644 plugin/evm/message/handshake/codec.go create mode 100644 plugin/evm/message/handshake/upgrade_config.go create mode 100644 plugin/evm/message/handshake/upgrade_config_test.go diff --git a/params/config.go b/params/config.go index ed15a67c8e..a00e885c49 100644 --- a/params/config.go +++ b/params/config.go @@ -444,17 +444,17 @@ func (c *ChainConfig) Verify() error { return nil } -type fork struct { - name string - block *big.Int // some go-ethereum forks use block numbers - timestamp *uint64 // Avalanche forks use timestamps - optional bool // if true, the fork may be nil and next fork is still allowed +type Fork struct { + name string `serialize:"true"` + block *big.Int `serialize:"true"` // some go-ethereum forks use block numbers + timestamp *uint64 `serialize:"true"` // Avalanche forks use timestamps + optional bool `serialize:"true"` // 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 { - ethForks := []fork{ + ethForks := []Fork{ {name: "homesteadBlock", block: c.HomesteadBlock}, {name: "eip150Block", block: c.EIP150Block}, {name: "eip155Block", block: c.EIP155Block}, @@ -493,8 +493,8 @@ func (c *ChainConfig) CheckConfigForkOrder() error { // checkForks checks that forks are enabled in order and returns an error if not // [blockFork] is true if the fork is a block number fork, false if it is a timestamp fork -func checkForks(forks []fork, blockFork bool) error { - lastFork := fork{} +func checkForks(forks []Fork, blockFork bool) error { + lastFork := Fork{} for _, cur := range forks { if blockFork && cur.block != nil && common.Big0.Cmp(cur.block) != 0 { return errNonGenesisForkByHeight diff --git a/params/network_upgrades.go b/params/network_upgrades.go index e51f3c65f8..916762d8d9 100644 --- a/params/network_upgrades.go +++ b/params/network_upgrades.go @@ -50,23 +50,21 @@ func (m *MandatoryNetworkUpgrades) CheckMandatoryCompatible(newcfg *MandatoryNet return nil } -func (m *MandatoryNetworkUpgrades) mandatoryForkOrder() []fork { - return []fork{ +func (m *MandatoryNetworkUpgrades) mandatoryForkOrder() []Fork { + return []Fork{ {name: "subnetEVMTimestamp", timestamp: m.SubnetEVMTimestamp}, {name: "dUpgradeTimestamp", timestamp: m.DUpgradeTimestamp}, } } -// 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{} +type OptionalNetworkUpgrades struct { + Updates []Fork `json:"serialize,omitempty" serialize:"true"` +} func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetworkUpgrades, time uint64) *ConfigCompatError { return nil } -func (n *OptionalNetworkUpgrades) optionalForkOrder() []fork { - return []fork{} +func (n *OptionalNetworkUpgrades) optionalForkOrder() []Fork { + return n.Updates } diff --git a/params/state_upgrade.go b/params/state_upgrade.go index 3041d656d4..efcd32838d 100644 --- a/params/state_upgrade.go +++ b/params/state_upgrade.go @@ -16,18 +16,18 @@ import ( // StateUpgrade describes the modifications to be made to the state during // a state upgrade. type StateUpgrade struct { - BlockTimestamp *uint64 `json:"blockTimestamp,omitempty"` + BlockTimestamp *uint64 `json:"blockTimestamp,omitempty" serialize:"true"` // map from account address to the modification to be made to the account. - StateUpgradeAccounts map[common.Address]StateUpgradeAccount `json:"accounts"` + StateUpgradeAccounts map[common.Address]StateUpgradeAccount `json:"accounts" serialize:"true"` } // StateUpgradeAccount describes the modifications to be made to an account during // a state upgrade. type StateUpgradeAccount struct { - Code hexutil.Bytes `json:"code,omitempty"` - Storage map[common.Hash]common.Hash `json:"storage,omitempty"` - BalanceChange *math.HexOrDecimal256 `json:"balanceChange,omitempty"` + Code hexutil.Bytes `json:"code,omitempty" serialize:"true"` + Storage map[common.Hash]common.Hash `json:"storage,omitempty" serialize:"true"` + BalanceChange *math.HexOrDecimal256 `json:"balanceChange,omitempty" serialize:"true"` } func (s *StateUpgrade) Equal(other *StateUpgrade) bool { diff --git a/plugin/evm/message/handshake/codec.go b/plugin/evm/message/handshake/codec.go new file mode 100644 index 0000000000..8d6e312487 --- /dev/null +++ b/plugin/evm/message/handshake/codec.go @@ -0,0 +1,36 @@ +// (c) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package handshake + +import ( + "github.com/ava-labs/avalanchego/codec" + "github.com/ava-labs/avalanchego/codec/linearcodec" + "github.com/ava-labs/avalanchego/utils/units" + "github.com/ava-labs/avalanchego/utils/wrappers" +) + +const ( + Version = uint16(0) + maxMessageSize = 1 * units.MiB +) + +var ( + Codec codec.Manager +) + +func init() { + Codec = codec.NewManager(maxMessageSize) + c := linearcodec.NewDefault() + + errs := wrappers.Errs{} + errs.Add( + c.RegisterType(UpgradeConfig{}), + + Codec.RegisterCodec(Version, c), + ) + + if errs.Errored() { + panic(errs.Err) + } +} diff --git a/plugin/evm/message/handshake/upgrade_config.go b/plugin/evm/message/handshake/upgrade_config.go new file mode 100644 index 0000000000..39489b05cf --- /dev/null +++ b/plugin/evm/message/handshake/upgrade_config.go @@ -0,0 +1,116 @@ +package handshake + +import ( + "crypto/sha256" + "fmt" + + "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/precompile/modules" + "github.com/ava-labs/subnet-evm/precompile/precompileconfig" +) + +type PrecompileUpgrade struct { + StructName string `serialize:"true"` + Bytes []byte `serialize:"true"` +} + +type UpgradeConfig struct { + OptionalNetworkUpgrades []params.Fork `serialize:"true"` + + // Config for modifying state as a network upgrade. + StateUpgrades []params.StateUpgrade `serialize:"true"` + + // Config for enabling and disabling precompiles as network upgrades. + PrecompileUpgrades []PrecompileUpgrade `serialize:"true"` + config params.UpgradeConfig + bytes []byte +} + +func ParseUpgradeConfig(bytes []byte) (*UpgradeConfig, error) { + var config UpgradeConfig + version, err := Codec.Unmarshal(bytes, &config) + if err != nil { + return nil, err + } + if version != Version { + return nil, fmt.Errorf("Invalid version") + } + + var PrecompileUpgrades []params.PrecompileUpgrade + + for _, precompileUpgrade := range config.PrecompileUpgrades { + module, ok := modules.GetPrecompileModule(precompileUpgrade.StructName) + if !ok { + return nil, fmt.Errorf("unknown precompile config: %s", precompileUpgrade.StructName) + } + preCompile := module.MakeConfig() + + version, err := Codec.Unmarshal(precompileUpgrade.Bytes, preCompile) + if version != Version { + return nil, fmt.Errorf("Invalid version") + } + if err != nil { + return nil, err + } + if Config, ok := preCompile.(precompileconfig.Config); ok { + PrecompileUpgrades = append(PrecompileUpgrades, params.PrecompileUpgrade{Config: Config}) + } else { + return nil, fmt.Errorf("Error deserializing precompile %s", precompileUpgrade.StructName) + } + } + + config.config = params.UpgradeConfig{ + OptionalNetworkUpgrades: ¶ms.OptionalNetworkUpgrades{config.OptionalNetworkUpgrades}, + StateUpgrades: config.StateUpgrades, + PrecompileUpgrades: PrecompileUpgrades, + } + config.bytes = bytes + + return &config, nil +} + +func NewUpgradeConfig(config params.UpgradeConfig) (*UpgradeConfig, error) { + PrecompileUpgrades := make([]PrecompileUpgrade, 0) + for _, precompileConfig := range config.PrecompileUpgrades { + bytes, err := Codec.Marshal(Version, precompileConfig.Config) + if err != nil { + return nil, err + } + PrecompileUpgrades = append(PrecompileUpgrades, PrecompileUpgrade{ + StructName: precompileConfig.Key(), + Bytes: bytes, + }) + } + + optionalNetworkUpgrades := make([]params.Fork, 0) + if config.OptionalNetworkUpgrades != nil { + optionalNetworkUpgrades = config.OptionalNetworkUpgrades.Updates + } + + wrappedConfig := UpgradeConfig{ + OptionalNetworkUpgrades: optionalNetworkUpgrades, + StateUpgrades: config.StateUpgrades, + PrecompileUpgrades: PrecompileUpgrades, + config: config, + bytes: make([]byte, 0), + } + bytes, err := Codec.Marshal(Version, wrappedConfig) + if err != nil { + return nil, err + } + wrappedConfig.bytes = bytes + + return &wrappedConfig, nil +} + +func (r *UpgradeConfig) Config() params.UpgradeConfig { + return r.config +} + +func (r *UpgradeConfig) Bytes() []byte { + return r.bytes +} + +func (r *UpgradeConfig) Hash() [32]byte { + return sha256.Sum256(r.bytes) +} diff --git a/plugin/evm/message/handshake/upgrade_config_test.go b/plugin/evm/message/handshake/upgrade_config_test.go new file mode 100644 index 0000000000..c605582f09 --- /dev/null +++ b/plugin/evm/message/handshake/upgrade_config_test.go @@ -0,0 +1,35 @@ +package handshake + +import ( + "testing" + + "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/precompile/contracts/nativeminter" + "github.com/stretchr/testify/assert" +) + +func TestSerialize(t *testing.T) { + var t0 uint64 = 0 + var t1 uint64 = 1 + config, err := NewUpgradeConfig(params.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: nativeminter.NewConfig(&t0, nil, nil, nil), // enable at genesis + }, + { + Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + }) + assert.NoError(t, err) + + config2, err := ParseUpgradeConfig(config.Bytes()) + assert.NoError(t, err) + + config3, err := NewUpgradeConfig(config2.Config()) + assert.NoError(t, err) + + assert.Equal(t, config2, config3) + assert.Equal(t, config.Hash(), config2.Hash()) + assert.Equal(t, config.Hash(), config3.Hash()) +} diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index 33f312f052..86e155fe28 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -15,9 +15,9 @@ var ErrCannotAddManagersBeforeDUpgrade = fmt.Errorf("cannot add managers before // AllowListConfig specifies the initial set of addresses with Admin or Enabled roles. type AllowListConfig struct { - AdminAddresses []common.Address `json:"adminAddresses,omitempty"` // initial admin addresses - ManagerAddresses []common.Address `json:"managerAddresses,omitempty"` // initial manager addresses - EnabledAddresses []common.Address `json:"enabledAddresses,omitempty"` // initial enabled addresses + AdminAddresses []common.Address `json:"adminAddresses,omitempty" serialize:"true"` // initial admin addresses + ManagerAddresses []common.Address `json:"managerAddresses,omitempty" serialize:"true"` // initial manager addresses + EnabledAddresses []common.Address `json:"enabledAddresses,omitempty" serialize:"true"` // initial enabled addresses } // Configure initializes the address space of [precompileAddr] by initializing the role of each of diff --git a/precompile/contracts/feemanager/config.go b/precompile/contracts/feemanager/config.go index 50dd7305ed..d415a9789a 100644 --- a/precompile/contracts/feemanager/config.go +++ b/precompile/contracts/feemanager/config.go @@ -17,7 +17,7 @@ var _ precompileconfig.Config = &Config{} type Config struct { allowlist.AllowListConfig // Config for the fee config manager allow list precompileconfig.Upgrade - InitialFeeConfig *commontype.FeeConfig `json:"initialFeeConfig,omitempty"` // initial fee config to be immediately activated + InitialFeeConfig *commontype.FeeConfig `json:"initialFeeConfig,omitempty" serialize:"true"` // initial fee config to be immediately activated } // NewConfig returns a config for a network upgrade at [blockTimestamp] that enables diff --git a/precompile/contracts/nativeminter/config.go b/precompile/contracts/nativeminter/config.go index e9b358abfd..b02d780c8f 100644 --- a/precompile/contracts/nativeminter/config.go +++ b/precompile/contracts/nativeminter/config.go @@ -19,9 +19,9 @@ var _ precompileconfig.Config = &Config{} // Config implements the StatefulPrecompileConfig interface while adding in the // ContractNativeMinter specific precompile config. type Config struct { - allowlist.AllowListConfig - precompileconfig.Upgrade - InitialMint map[common.Address]*math.HexOrDecimal256 `json:"initialMint,omitempty"` // addresses to receive the initial mint mapped to the amount to mint + allowlist.AllowListConfig `serialize:"true"` + precompileconfig.Upgrade `serialize:"true"` + InitialMint map[common.Address]*math.HexOrDecimal256 `json:"initialMint,omitempty" serialize:"true"` // addresses to receive the initial mint mapped to the amount to mint } // NewConfig returns a config for a network upgrade at [blockTimestamp] that enables diff --git a/precompile/contracts/rewardmanager/config.go b/precompile/contracts/rewardmanager/config.go index 25d53e5728..af947ff164 100644 --- a/precompile/contracts/rewardmanager/config.go +++ b/precompile/contracts/rewardmanager/config.go @@ -16,8 +16,8 @@ import ( var _ precompileconfig.Config = &Config{} type InitialRewardConfig struct { - AllowFeeRecipients bool `json:"allowFeeRecipients"` - RewardAddress common.Address `json:"rewardAddress,omitempty"` + AllowFeeRecipients bool `json:"allowFeeRecipients" serialize:"true"` + RewardAddress common.Address `json:"rewardAddress,omitempty" serialize:"true"` } func (i *InitialRewardConfig) Equal(other *InitialRewardConfig) bool { diff --git a/precompile/precompileconfig/upgradeable.go b/precompile/precompileconfig/upgradeable.go index f26bc37a33..9440f4573c 100644 --- a/precompile/precompileconfig/upgradeable.go +++ b/precompile/precompileconfig/upgradeable.go @@ -9,8 +9,8 @@ import "github.com/ava-labs/subnet-evm/utils" // a boolean [Disable]. If [Disable] is set, the upgrade deactivates // the precompile and clears its storage. type Upgrade struct { - BlockTimestamp *uint64 `json:"blockTimestamp"` - Disable bool `json:"disable,omitempty"` + BlockTimestamp *uint64 `json:"blockTimestamp" serialize:"true"` + Disable bool `json:"disable,omitempty" serialize:"true"` } // Timestamp returns the timestamp this network upgrade goes into effect. From 89bf82c0fc98bc00c3dff8af04be88da0a61750d Mon Sep 17 00:00:00 2001 From: Cesar Date: Sun, 13 Aug 2023 23:55:16 -0400 Subject: [PATCH 02/48] Use 8 bytes to hash UpgradeConfig 8 bytes is generally enough to fingerprint the UpgradeConfig changes, so nodes can exchange the hash as part of the handshake[1] [1] https://stackoverflow.com/questions/18134627/how-much-of-a-git-sha-is-generally-considered-necessary-to-uniquely-identify-a --- plugin/evm/message/handshake/upgrade_config.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugin/evm/message/handshake/upgrade_config.go b/plugin/evm/message/handshake/upgrade_config.go index 39489b05cf..24971f2c83 100644 --- a/plugin/evm/message/handshake/upgrade_config.go +++ b/plugin/evm/message/handshake/upgrade_config.go @@ -111,6 +111,9 @@ func (r *UpgradeConfig) Bytes() []byte { return r.bytes } -func (r *UpgradeConfig) Hash() [32]byte { - return sha256.Sum256(r.bytes) +func (r *UpgradeConfig) Hash() [8]byte { + hash := sha256.Sum256(r.bytes) + var firstBytes [8]byte + copy(firstBytes[:], hash[:8]) + return firstBytes } From 19e0d1860de66bb43e98739b31f94e882ffa7cd2 Mon Sep 17 00:00:00 2001 From: Cesar <137245636+nytzuga@users.noreply.github.com> Date: Fri, 8 Sep 2023 02:55:29 -0400 Subject: [PATCH 03/48] Fixed linting issues --- plugin/evm/message/handshake/upgrade_config.go | 9 ++------- plugin/evm/message/handshake/upgrade_config_test.go | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/plugin/evm/message/handshake/upgrade_config.go b/plugin/evm/message/handshake/upgrade_config.go index 24971f2c83..487feed737 100644 --- a/plugin/evm/message/handshake/upgrade_config.go +++ b/plugin/evm/message/handshake/upgrade_config.go @@ -6,7 +6,6 @@ import ( "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/modules" - "github.com/ava-labs/subnet-evm/precompile/precompileconfig" ) type PrecompileUpgrade struct { @@ -52,15 +51,11 @@ func ParseUpgradeConfig(bytes []byte) (*UpgradeConfig, error) { if err != nil { return nil, err } - if Config, ok := preCompile.(precompileconfig.Config); ok { - PrecompileUpgrades = append(PrecompileUpgrades, params.PrecompileUpgrade{Config: Config}) - } else { - return nil, fmt.Errorf("Error deserializing precompile %s", precompileUpgrade.StructName) - } + PrecompileUpgrades = append(PrecompileUpgrades, params.PrecompileUpgrade{Config: preCompile}) } config.config = params.UpgradeConfig{ - OptionalNetworkUpgrades: ¶ms.OptionalNetworkUpgrades{config.OptionalNetworkUpgrades}, + OptionalNetworkUpgrades: ¶ms.OptionalNetworkUpgrades{Updates: config.OptionalNetworkUpgrades}, StateUpgrades: config.StateUpgrades, PrecompileUpgrades: PrecompileUpgrades, } diff --git a/plugin/evm/message/handshake/upgrade_config_test.go b/plugin/evm/message/handshake/upgrade_config_test.go index c605582f09..7b1ad4cd6c 100644 --- a/plugin/evm/message/handshake/upgrade_config_test.go +++ b/plugin/evm/message/handshake/upgrade_config_test.go @@ -14,7 +14,7 @@ func TestSerialize(t *testing.T) { config, err := NewUpgradeConfig(params.UpgradeConfig{ PrecompileUpgrades: []params.PrecompileUpgrade{ { - Config: nativeminter.NewConfig(&t0, nil, nil, nil), // enable at genesis + Config: nativeminter.NewConfig(&t0, nil, nil, nil, nil), // enable at genesis }, { Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 From 30b8aaa1cfb9c79ec2be7a1bfd617cc52e8ebbbc Mon Sep 17 00:00:00 2001 From: Cesar <137245636+nytzuga@users.noreply.github.com> Date: Thu, 14 Sep 2023 09:43:12 -0400 Subject: [PATCH 04/48] Addressed PR comments --- plugin/evm/message/handshake/codec.go | 11 ++++- .../evm/message/handshake/upgrade_config.go | 49 ++++++++++--------- .../message/handshake/upgrade_config_test.go | 17 ++++--- precompile/contracts/feemanager/config.go | 6 +-- 4 files changed, 47 insertions(+), 36 deletions(-) diff --git a/plugin/evm/message/handshake/codec.go b/plugin/evm/message/handshake/codec.go index 8d6e312487..6637f7d76d 100644 --- a/plugin/evm/message/handshake/codec.go +++ b/plugin/evm/message/handshake/codec.go @@ -1,9 +1,14 @@ // (c) 2019-2023, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. +// (c) 2019-2020, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + package handshake import ( + "errors" + "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/codec/linearcodec" "github.com/ava-labs/avalanchego/utils/units" @@ -16,7 +21,9 @@ const ( ) var ( - Codec codec.Manager + ErrInvalidVersion = errors.New("invalid version") + ErrUnknowPrecompile = errors.New("unknown precompile config") + Codec codec.Manager ) func init() { @@ -25,7 +32,7 @@ func init() { errs := wrappers.Errs{} errs.Add( - c.RegisterType(UpgradeConfig{}), + c.RegisterType(upgradeConfigMessage{}), Codec.RegisterCodec(Version, c), ) diff --git a/plugin/evm/message/handshake/upgrade_config.go b/plugin/evm/message/handshake/upgrade_config.go index 487feed737..edba849a6d 100644 --- a/plugin/evm/message/handshake/upgrade_config.go +++ b/plugin/evm/message/handshake/upgrade_config.go @@ -1,52 +1,53 @@ +// (c) 2019-2020, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + package handshake import ( - "crypto/sha256" - "fmt" - "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/modules" + "github.com/ethereum/go-ethereum/crypto" ) -type PrecompileUpgrade struct { - StructName string `serialize:"true"` - Bytes []byte `serialize:"true"` +type rawPrecompileUpgrade struct { + Key string `serialize:"true"` + Bytes []byte `serialize:"true"` } -type UpgradeConfig struct { +type upgradeConfigMessage struct { OptionalNetworkUpgrades []params.Fork `serialize:"true"` // Config for modifying state as a network upgrade. StateUpgrades []params.StateUpgrade `serialize:"true"` // Config for enabling and disabling precompiles as network upgrades. - PrecompileUpgrades []PrecompileUpgrade `serialize:"true"` + PrecompileUpgrades []rawPrecompileUpgrade `serialize:"true"` config params.UpgradeConfig bytes []byte } -func ParseUpgradeConfig(bytes []byte) (*UpgradeConfig, error) { - var config UpgradeConfig +func ParseUpgradeConfig(bytes []byte) (*upgradeConfigMessage, error) { + var config upgradeConfigMessage version, err := Codec.Unmarshal(bytes, &config) if err != nil { return nil, err } if version != Version { - return nil, fmt.Errorf("Invalid version") + return nil, ErrInvalidVersion } var PrecompileUpgrades []params.PrecompileUpgrade for _, precompileUpgrade := range config.PrecompileUpgrades { - module, ok := modules.GetPrecompileModule(precompileUpgrade.StructName) + module, ok := modules.GetPrecompileModule(precompileUpgrade.Key) if !ok { - return nil, fmt.Errorf("unknown precompile config: %s", precompileUpgrade.StructName) + return nil, ErrUnknowPrecompile } preCompile := module.MakeConfig() version, err := Codec.Unmarshal(precompileUpgrade.Bytes, preCompile) if version != Version { - return nil, fmt.Errorf("Invalid version") + return nil, ErrInvalidVersion } if err != nil { return nil, err @@ -64,16 +65,16 @@ func ParseUpgradeConfig(bytes []byte) (*UpgradeConfig, error) { return &config, nil } -func NewUpgradeConfig(config params.UpgradeConfig) (*UpgradeConfig, error) { - PrecompileUpgrades := make([]PrecompileUpgrade, 0) +func NewUpgradeConfig(config params.UpgradeConfig) (*upgradeConfigMessage, error) { + PrecompileUpgrades := make([]rawPrecompileUpgrade, 0) for _, precompileConfig := range config.PrecompileUpgrades { bytes, err := Codec.Marshal(Version, precompileConfig.Config) if err != nil { return nil, err } - PrecompileUpgrades = append(PrecompileUpgrades, PrecompileUpgrade{ - StructName: precompileConfig.Key(), - Bytes: bytes, + PrecompileUpgrades = append(PrecompileUpgrades, rawPrecompileUpgrade{ + Key: precompileConfig.Key(), + Bytes: bytes, }) } @@ -82,7 +83,7 @@ func NewUpgradeConfig(config params.UpgradeConfig) (*UpgradeConfig, error) { optionalNetworkUpgrades = config.OptionalNetworkUpgrades.Updates } - wrappedConfig := UpgradeConfig{ + wrappedConfig := upgradeConfigMessage{ OptionalNetworkUpgrades: optionalNetworkUpgrades, StateUpgrades: config.StateUpgrades, PrecompileUpgrades: PrecompileUpgrades, @@ -98,16 +99,16 @@ func NewUpgradeConfig(config params.UpgradeConfig) (*UpgradeConfig, error) { return &wrappedConfig, nil } -func (r *UpgradeConfig) Config() params.UpgradeConfig { +func (r *upgradeConfigMessage) Config() params.UpgradeConfig { return r.config } -func (r *UpgradeConfig) Bytes() []byte { +func (r *upgradeConfigMessage) Bytes() []byte { return r.bytes } -func (r *UpgradeConfig) Hash() [8]byte { - hash := sha256.Sum256(r.bytes) +func (r *upgradeConfigMessage) Hash() [8]byte { + hash := crypto.Keccak256(r.bytes) var firstBytes [8]byte copy(firstBytes[:], hash[:8]) return firstBytes diff --git a/plugin/evm/message/handshake/upgrade_config_test.go b/plugin/evm/message/handshake/upgrade_config_test.go index 7b1ad4cd6c..fa6679ad7b 100644 --- a/plugin/evm/message/handshake/upgrade_config_test.go +++ b/plugin/evm/message/handshake/upgrade_config_test.go @@ -1,3 +1,6 @@ +// (c) 2019-2020, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + package handshake import ( @@ -5,7 +8,7 @@ import ( "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/contracts/nativeminter" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestSerialize(t *testing.T) { @@ -21,15 +24,15 @@ func TestSerialize(t *testing.T) { }, }, }) - assert.NoError(t, err) + require.NoError(t, err) config2, err := ParseUpgradeConfig(config.Bytes()) - assert.NoError(t, err) + require.NoError(t, err) config3, err := NewUpgradeConfig(config2.Config()) - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, config2, config3) - assert.Equal(t, config.Hash(), config2.Hash()) - assert.Equal(t, config.Hash(), config3.Hash()) + require.Equal(t, config2, config3) + require.Equal(t, config.Hash(), config2.Hash()) + require.Equal(t, config.Hash(), config3.Hash()) } diff --git a/precompile/contracts/feemanager/config.go b/precompile/contracts/feemanager/config.go index d415a9789a..0ab994a09a 100644 --- a/precompile/contracts/feemanager/config.go +++ b/precompile/contracts/feemanager/config.go @@ -15,9 +15,9 @@ var _ precompileconfig.Config = &Config{} // Config implements the StatefulPrecompileConfig interface while adding in the // FeeManager specific precompile config. type Config struct { - allowlist.AllowListConfig // Config for the fee config manager allow list - precompileconfig.Upgrade - InitialFeeConfig *commontype.FeeConfig `json:"initialFeeConfig,omitempty" serialize:"true"` // initial fee config to be immediately activated + allowlist.AllowListConfig `serialize:"true"` + precompileconfig.Upgrade `serialize:"true"` + InitialFeeConfig *commontype.FeeConfig `json:"initialFeeConfig,omitempty" serialize:"true"` // initial fee config to be immediately activated } // NewConfig returns a config for a network upgrade at [blockTimestamp] that enables From 4a59b8a04399d43728be7997c032ac5cd5c6343f Mon Sep 17 00:00:00 2001 From: Cesar <137245636+nytzuga@users.noreply.github.com> Date: Thu, 14 Sep 2023 13:39:04 -0400 Subject: [PATCH 05/48] Improve API usage --- plugin/evm/message/handshake/codec.go | 2 +- .../evm/message/handshake/upgrade_config.go | 65 ++++++++++--------- .../message/handshake/upgrade_config_test.go | 14 ++-- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/plugin/evm/message/handshake/codec.go b/plugin/evm/message/handshake/codec.go index 6637f7d76d..f1943cc2fd 100644 --- a/plugin/evm/message/handshake/codec.go +++ b/plugin/evm/message/handshake/codec.go @@ -32,7 +32,7 @@ func init() { errs := wrappers.Errs{} errs.Add( - c.RegisterType(upgradeConfigMessage{}), + c.RegisterType(networkUpgradeConfigMessage{}), Codec.RegisterCodec(Version, c), ) diff --git a/plugin/evm/message/handshake/upgrade_config.go b/plugin/evm/message/handshake/upgrade_config.go index edba849a6d..9ee72d9525 100644 --- a/plugin/evm/message/handshake/upgrade_config.go +++ b/plugin/evm/message/handshake/upgrade_config.go @@ -14,7 +14,7 @@ type rawPrecompileUpgrade struct { Bytes []byte `serialize:"true"` } -type upgradeConfigMessage struct { +type networkUpgradeConfigMessage struct { OptionalNetworkUpgrades []params.Fork `serialize:"true"` // Config for modifying state as a network upgrade. @@ -22,12 +22,22 @@ type upgradeConfigMessage struct { // Config for enabling and disabling precompiles as network upgrades. PrecompileUpgrades []rawPrecompileUpgrade `serialize:"true"` - config params.UpgradeConfig - bytes []byte } -func ParseUpgradeConfig(bytes []byte) (*upgradeConfigMessage, error) { - var config upgradeConfigMessage +type UpgradeConfigMessage struct { + Bytes []byte + Hash []byte +} + +// Attempts to parse a networkUpgradeConfigMessage from a []byte +// +// This function attempts to parse a stream of bytes as a +// networkUpgradeConfigMessage (as serialized from +// UpgradeConfigToNetworkMessage). +// +// The function returns a reference of *params.UpgradeConfig +func ParseUpgradeConfigMessage(bytes []byte) (*params.UpgradeConfig, error) { + var config networkUpgradeConfigMessage version, err := Codec.Unmarshal(bytes, &config) if err != nil { return nil, err @@ -37,14 +47,12 @@ func ParseUpgradeConfig(bytes []byte) (*upgradeConfigMessage, error) { } var PrecompileUpgrades []params.PrecompileUpgrade - for _, precompileUpgrade := range config.PrecompileUpgrades { module, ok := modules.GetPrecompileModule(precompileUpgrade.Key) if !ok { return nil, ErrUnknowPrecompile } preCompile := module.MakeConfig() - version, err := Codec.Unmarshal(precompileUpgrade.Bytes, preCompile) if version != Version { return nil, ErrInvalidVersion @@ -55,17 +63,23 @@ func ParseUpgradeConfig(bytes []byte) (*upgradeConfigMessage, error) { PrecompileUpgrades = append(PrecompileUpgrades, params.PrecompileUpgrade{Config: preCompile}) } - config.config = params.UpgradeConfig{ + return ¶ms.UpgradeConfig{ OptionalNetworkUpgrades: ¶ms.OptionalNetworkUpgrades{Updates: config.OptionalNetworkUpgrades}, StateUpgrades: config.StateUpgrades, PrecompileUpgrades: PrecompileUpgrades, - } - config.bytes = bytes - - return &config, nil + }, nil } -func NewUpgradeConfig(config params.UpgradeConfig) (*upgradeConfigMessage, error) { +// Wraps an instance of *params.UpgradeConfig +// +// This function returns the serialized UpgradeConfig, ready to be send over to +// other peers. The struct also includes a hash of the content, ready to be used +// as part of the handshake protocol. +// +// Since params.UpgradeConfig should never change without a node reloading, it +// is safe to call this function once and store its output globally to re-use +// multiple times +func UpgradeConfigToNetworkMessage(config *params.UpgradeConfig) (*UpgradeConfigMessage, error) { PrecompileUpgrades := make([]rawPrecompileUpgrade, 0) for _, precompileConfig := range config.PrecompileUpgrades { bytes, err := Codec.Marshal(Version, precompileConfig.Config) @@ -83,33 +97,22 @@ func NewUpgradeConfig(config params.UpgradeConfig) (*upgradeConfigMessage, error optionalNetworkUpgrades = config.OptionalNetworkUpgrades.Updates } - wrappedConfig := upgradeConfigMessage{ + wrappedConfig := networkUpgradeConfigMessage{ OptionalNetworkUpgrades: optionalNetworkUpgrades, StateUpgrades: config.StateUpgrades, PrecompileUpgrades: PrecompileUpgrades, - config: config, - bytes: make([]byte, 0), } bytes, err := Codec.Marshal(Version, wrappedConfig) if err != nil { return nil, err } - wrappedConfig.bytes = bytes - return &wrappedConfig, nil -} - -func (r *upgradeConfigMessage) Config() params.UpgradeConfig { - return r.config -} - -func (r *upgradeConfigMessage) Bytes() []byte { - return r.bytes -} - -func (r *upgradeConfigMessage) Hash() [8]byte { - hash := crypto.Keccak256(r.bytes) + hash := crypto.Keccak256(bytes) var firstBytes [8]byte copy(firstBytes[:], hash[:8]) - return firstBytes + + return &UpgradeConfigMessage{ + Bytes: bytes, + Hash: hash, + }, nil } diff --git a/plugin/evm/message/handshake/upgrade_config_test.go b/plugin/evm/message/handshake/upgrade_config_test.go index fa6679ad7b..17bb449078 100644 --- a/plugin/evm/message/handshake/upgrade_config_test.go +++ b/plugin/evm/message/handshake/upgrade_config_test.go @@ -14,7 +14,7 @@ import ( func TestSerialize(t *testing.T) { var t0 uint64 = 0 var t1 uint64 = 1 - config, err := NewUpgradeConfig(params.UpgradeConfig{ + message, err := UpgradeConfigToNetworkMessage(¶ms.UpgradeConfig{ PrecompileUpgrades: []params.PrecompileUpgrade{ { Config: nativeminter.NewConfig(&t0, nil, nil, nil, nil), // enable at genesis @@ -26,13 +26,15 @@ func TestSerialize(t *testing.T) { }) require.NoError(t, err) - config2, err := ParseUpgradeConfig(config.Bytes()) + config, err := ParseUpgradeConfigMessage(message.Bytes) require.NoError(t, err) - config3, err := NewUpgradeConfig(config2.Config()) + message2, err := UpgradeConfigToNetworkMessage(config) require.NoError(t, err) - require.Equal(t, config2, config3) - require.Equal(t, config.Hash(), config2.Hash()) - require.Equal(t, config.Hash(), config3.Hash()) + config3, err := ParseUpgradeConfigMessage(message2.Bytes) + require.NoError(t, err) + + require.Equal(t, config, config3) + require.Equal(t, message.Hash, message2.Hash) } From acc819551fda695c8af44252347d1996262a439b Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 12 Oct 2023 23:01:36 -0300 Subject: [PATCH 06/48] Rewrote configs Introduce custom serialization which is converted to the expected type for OptionalNetworkUpgrades --- params/config.go | 18 +++++----- params/network_upgrades.go | 35 ++++++++++++++++--- .../evm/message/handshake/upgrade_config.go | 13 +++---- .../message/handshake/upgrade_config_test.go | 4 +++ 4 files changed, 50 insertions(+), 20 deletions(-) diff --git a/params/config.go b/params/config.go index a00e885c49..2503e41ffc 100644 --- a/params/config.go +++ b/params/config.go @@ -166,7 +166,7 @@ type UpgradeConfig struct { // 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. - OptionalNetworkUpgrades *OptionalNetworkUpgrades `json:"networkUpgrades,omitempty"` + OptionalNetworkUpgrades *OptionalNetworkUpgrades // Config for modifying state as a network upgrade. StateUpgrades []StateUpgrade `json:"stateUpgrades,omitempty"` @@ -444,17 +444,17 @@ func (c *ChainConfig) Verify() error { return nil } -type Fork struct { - name string `serialize:"true"` - block *big.Int `serialize:"true"` // some go-ethereum forks use block numbers - timestamp *uint64 `serialize:"true"` // Avalanche forks use timestamps - optional bool `serialize:"true"` // if true, the fork may be nil and next fork is still allowed +type fork struct { + name string + block *big.Int // some go-ethereum forks use block numbers + timestamp *uint64 // Avalanche forks use timestamps + 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 { - ethForks := []Fork{ + ethForks := []fork{ {name: "homesteadBlock", block: c.HomesteadBlock}, {name: "eip150Block", block: c.EIP150Block}, {name: "eip155Block", block: c.EIP155Block}, @@ -493,8 +493,8 @@ func (c *ChainConfig) CheckConfigForkOrder() error { // checkForks checks that forks are enabled in order and returns an error if not // [blockFork] is true if the fork is a block number fork, false if it is a timestamp fork -func checkForks(forks []Fork, blockFork bool) error { - lastFork := Fork{} +func checkForks(forks []fork, blockFork bool) error { + lastFork := fork{} for _, cur := range forks { if blockFork && cur.block != nil && common.Big0.Cmp(cur.block) != 0 { return errNonGenesisForkByHeight diff --git a/params/network_upgrades.go b/params/network_upgrades.go index 916762d8d9..9cec00ba33 100644 --- a/params/network_upgrades.go +++ b/params/network_upgrades.go @@ -4,6 +4,8 @@ package params import ( + "math/big" + "github.com/ava-labs/subnet-evm/utils" ) @@ -50,21 +52,44 @@ func (m *MandatoryNetworkUpgrades) CheckMandatoryCompatible(newcfg *MandatoryNet return nil } -func (m *MandatoryNetworkUpgrades) mandatoryForkOrder() []Fork { - return []Fork{ +func (m *MandatoryNetworkUpgrades) mandatoryForkOrder() []fork { + return []fork{ {name: "subnetEVMTimestamp", timestamp: m.SubnetEVMTimestamp}, {name: "dUpgradeTimestamp", timestamp: m.DUpgradeTimestamp}, } } +type OptionalFork struct { + Name string `json:"name" serialize:"true"` + Block big.Int `json:"block" serialize:"true"` + Timestamp uint64 `json:"timestamp" serialize:"true"` +} + type OptionalNetworkUpgrades struct { - Updates []Fork `json:"serialize,omitempty" serialize:"true"` + OptionalNetworkUpgrades []OptionalFork `json:"networkUpgrades,omitempty" serialize:"true"` } func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetworkUpgrades, time uint64) *ConfigCompatError { return nil } -func (n *OptionalNetworkUpgrades) optionalForkOrder() []Fork { - return n.Updates +func (n *OptionalNetworkUpgrades) optionalForkOrder() []fork { + forks := make([]fork, len(n.OptionalNetworkUpgrades)) + for i, n := range n.OptionalNetworkUpgrades { + var block *big.Int + var timestamp *uint64 + if n.Block.BitLen() > 0 { + block = &n.Block + } + if n.Timestamp != 0 { + timestamp = &n.Timestamp + } + forks[i] = fork{ + name: n.Name, + block: block, + timestamp: timestamp, + optional: true, + } + } + return []fork{} } diff --git a/plugin/evm/message/handshake/upgrade_config.go b/plugin/evm/message/handshake/upgrade_config.go index 9ee72d9525..6599d4e054 100644 --- a/plugin/evm/message/handshake/upgrade_config.go +++ b/plugin/evm/message/handshake/upgrade_config.go @@ -15,7 +15,7 @@ type rawPrecompileUpgrade struct { } type networkUpgradeConfigMessage struct { - OptionalNetworkUpgrades []params.Fork `serialize:"true"` + OptionalNetworkUpgrades params.OptionalNetworkUpgrades `serialize:"true"` // Config for modifying state as a network upgrade. StateUpgrades []params.StateUpgrade `serialize:"true"` @@ -64,7 +64,7 @@ func ParseUpgradeConfigMessage(bytes []byte) (*params.UpgradeConfig, error) { } return ¶ms.UpgradeConfig{ - OptionalNetworkUpgrades: ¶ms.OptionalNetworkUpgrades{Updates: config.OptionalNetworkUpgrades}, + OptionalNetworkUpgrades: &config.OptionalNetworkUpgrades, StateUpgrades: config.StateUpgrades, PrecompileUpgrades: PrecompileUpgrades, }, nil @@ -92,16 +92,17 @@ func UpgradeConfigToNetworkMessage(config *params.UpgradeConfig) (*UpgradeConfig }) } - optionalNetworkUpgrades := make([]params.Fork, 0) - if config.OptionalNetworkUpgrades != nil { - optionalNetworkUpgrades = config.OptionalNetworkUpgrades.Updates + optionalNetworkUpgrades := config.OptionalNetworkUpgrades + if optionalNetworkUpgrades == nil { + optionalNetworkUpgrades = ¶ms.OptionalNetworkUpgrades{} } wrappedConfig := networkUpgradeConfigMessage{ - OptionalNetworkUpgrades: optionalNetworkUpgrades, + OptionalNetworkUpgrades: *optionalNetworkUpgrades, StateUpgrades: config.StateUpgrades, PrecompileUpgrades: PrecompileUpgrades, } + bytes, err := Codec.Marshal(Version, wrappedConfig) if err != nil { return nil, err diff --git a/plugin/evm/message/handshake/upgrade_config_test.go b/plugin/evm/message/handshake/upgrade_config_test.go index 17bb449078..cc289a3880 100644 --- a/plugin/evm/message/handshake/upgrade_config_test.go +++ b/plugin/evm/message/handshake/upgrade_config_test.go @@ -35,6 +35,10 @@ func TestSerialize(t *testing.T) { config3, err := ParseUpgradeConfigMessage(message2.Bytes) require.NoError(t, err) + message3, err := UpgradeConfigToNetworkMessage(config3) + require.NoError(t, err) + require.Equal(t, config, config3) require.Equal(t, message.Hash, message2.Hash) + require.Equal(t, message2.Hash, message3.Hash) } From a0ceae8d27536602312b86ba353975d100d1e395 Mon Sep 17 00:00:00 2001 From: Cesar Date: Fri, 20 Oct 2023 18:00:36 -0300 Subject: [PATCH 07/48] WIP: Optional upgrades tests Using `serialize with omitempty` from https://github.com/ava-labs/avalanchego/pull/2171 to serialize optional upgrades config --- go.mod | 4 +- go.sum | 23 +---- params/config.go | 2 +- params/config_test.go | 88 +++++++++++++++++++ params/network_upgrades.go | 45 +++++----- .../evm/message/handshake/upgrade_config.go | 13 +-- 6 files changed, 122 insertions(+), 53 deletions(-) diff --git a/go.mod b/go.mod index 393d837826..a77673cf58 100644 --- a/go.mod +++ b/go.mod @@ -94,7 +94,6 @@ require ( github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/huin/goupnp v1.0.3 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/influxdata/influxdb-client-go/v2 v2.4.0 // indirect github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c // indirect github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect @@ -126,7 +125,6 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/afero v1.8.2 // indirect - github.com/spf13/cobra v1.7.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/subosito/gotenv v1.3.0 // indirect github.com/supranational/blst v0.3.11 // indirect @@ -161,3 +159,5 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) + +replace github.com/ava-labs/avalanchego => github.com/ava-labs/avalanchego v1.10.14-0.20231020184934-1ad3e42ef00d diff --git a/go.sum b/go.sum index a92c797c98..1870cafc8b 100644 --- a/go.sum +++ b/go.sum @@ -38,7 +38,7 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= @@ -59,12 +59,10 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/ava-labs/avalanche-network-runner v1.7.2 h1:XFad/wZfYzDnqbLzPAPPRYU3a1Zc8QT8x5dtLTS3lUo= -github.com/ava-labs/avalanche-network-runner v1.7.2/go.mod h1:naLveusSrP7YgTAqRykD1SyLOAUilCp9jGjk3MDxoPI= github.com/ava-labs/avalanche-network-runner v1.7.3-0.20231026153158-2931f8a448d9 h1:mTxfmBxmV8GSW0PUt0Qj/Obetzsw0gP6dtoNHaKW2+o= github.com/ava-labs/avalanche-network-runner v1.7.3-0.20231026153158-2931f8a448d9/go.mod h1:M9FC+xU4hQU3Botux8V8j574YETeX6tMvxiOmqLfl5c= -github.com/ava-labs/avalanchego v1.10.14 h1:1jTMrikYD49Pb64ZLUi2z2BnNGLzIGip4fValq6/YfE= -github.com/ava-labs/avalanchego v1.10.14/go.mod h1:En/ti2xoxQqJuN6t9ne2ogckU9leuZzTjl5mbEsfjTc= +github.com/ava-labs/avalanchego v1.10.14-0.20231020184934-1ad3e42ef00d h1:KD/p5wpuW+F54PboAuhHx12Pu0ckez73zvIla3xzWiU= +github.com/ava-labs/avalanchego v1.10.14-0.20231020184934-1ad3e42ef00d/go.mod h1:tbPGmDognRVE/6xqqal/fszBZlr0jyll3KXXO/7cuqo= github.com/ava-labs/coreth v0.12.7-rc.1 h1:fvjow2Jqkq1RNtW4v2Kx0DdTVp+3+fCY421TxpDDRfM= github.com/ava-labs/coreth v0.12.7-rc.1/go.mod h1:sNbwitXv4AhLvWpSqy6V8yzkhGFeWBQFD31/xiRDJ5M= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= @@ -133,7 +131,6 @@ github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoG github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= @@ -197,7 +194,7 @@ github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= @@ -223,7 +220,6 @@ github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxI github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -376,8 +372,6 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1: github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k= github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c h1:qSHzRbhzK8RdXOsAdfDgO49TtqC1oZ+acxPrkfTxcCs= @@ -396,16 +390,13 @@ github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7Bd github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= @@ -436,7 +427,6 @@ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4F github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= @@ -478,11 +468,9 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= @@ -577,8 +565,6 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -593,7 +579,6 @@ github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= diff --git a/params/config.go b/params/config.go index 2503e41ffc..ed15a67c8e 100644 --- a/params/config.go +++ b/params/config.go @@ -166,7 +166,7 @@ type UpgradeConfig struct { // 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. - OptionalNetworkUpgrades *OptionalNetworkUpgrades + OptionalNetworkUpgrades *OptionalNetworkUpgrades `json:"networkUpgrades,omitempty"` // Config for modifying state as a network upgrade. StateUpgrades []StateUpgrade `json:"stateUpgrades,omitempty"` diff --git a/params/config_test.go b/params/config_test.go index 8085cc09e6..4dd05652e8 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -330,3 +330,91 @@ func TestChainConfigMarshalWithUpgrades(t *testing.T) { require.NoError(t, err) require.Equal(t, config, unmarshalled) } + +func TestChainConfigMarshalWithUpgradesAndOptionalUpgrade(t *testing.T) { + block := big.NewInt(0) + ts := uint64(102) + 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), + MandatoryNetworkUpgrades: MandatoryNetworkUpgrades{ + SubnetEVMTimestamp: utils.NewUint64(0), + DUpgradeTimestamp: utils.NewUint64(0), + }, + GenesisPrecompiles: Precompiles{}, + }, + UpgradeConfig: UpgradeConfig{ + OptionalNetworkUpgrades: &OptionalNetworkUpgrades{ + Test: &OptionalFork{ + Block: block, + Timestamp: &ts, + }, + }, + PrecompileUpgrades: []PrecompileUpgrade{ + { + Config: txallowlist.NewConfig(utils.NewUint64(100), nil, nil, nil), + }, + }, + }, + } + 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, + "dUpgradeTimestamp": 0, + "upgrades": { + "networkUpgrades": { + "test": { + "block": 0, + "timestamp": 102 + } + }, + "precompileUpgrades": [ + { + "txAllowListConfig": { + "blockTimestamp": 100 + } + } + ] + } + }` + require.JSONEq(t, expectedJSON, string(result)) + + var unmarshalled ChainConfigWithUpgradesJSON + err = json.Unmarshal(result, &unmarshalled) + require.NoError(t, err) + require.Equal(t, config, unmarshalled) +} diff --git a/params/network_upgrades.go b/params/network_upgrades.go index 9cec00ba33..362479124b 100644 --- a/params/network_upgrades.go +++ b/params/network_upgrades.go @@ -60,13 +60,29 @@ func (m *MandatoryNetworkUpgrades) mandatoryForkOrder() []fork { } type OptionalFork struct { - Name string `json:"name" serialize:"true"` - Block big.Int `json:"block" serialize:"true"` - Timestamp uint64 `json:"timestamp" serialize:"true"` + Block *big.Int `json:"block" serialize:"true"` + Timestamp *uint64 `json:"timestamp" serialize:"true"` +} + +func (m *OptionalFork) ToFork(name string) fork { + var block *big.Int + var timestamp *uint64 + if m.Block != nil { + block = m.Block + } + if m.Timestamp != nil { + timestamp = m.Timestamp + } + return fork{ + name: name, + block: block, + timestamp: timestamp, + optional: true, + } } type OptionalNetworkUpgrades struct { - OptionalNetworkUpgrades []OptionalFork `json:"networkUpgrades,omitempty" serialize:"true"` + Test *OptionalFork `json:"test,omitempty" serialize:"true,omitempty"` } func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetworkUpgrades, time uint64) *ConfigCompatError { @@ -74,22 +90,9 @@ func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetwor } func (n *OptionalNetworkUpgrades) optionalForkOrder() []fork { - forks := make([]fork, len(n.OptionalNetworkUpgrades)) - for i, n := range n.OptionalNetworkUpgrades { - var block *big.Int - var timestamp *uint64 - if n.Block.BitLen() > 0 { - block = &n.Block - } - if n.Timestamp != 0 { - timestamp = &n.Timestamp - } - forks[i] = fork{ - name: n.Name, - block: block, - timestamp: timestamp, - optional: true, - } + forks := make([]fork, 0) + if n.Test != nil { + forks = append(forks, n.Test.ToFork("test")) } - return []fork{} + return forks } diff --git a/plugin/evm/message/handshake/upgrade_config.go b/plugin/evm/message/handshake/upgrade_config.go index 6599d4e054..1235ae6150 100644 --- a/plugin/evm/message/handshake/upgrade_config.go +++ b/plugin/evm/message/handshake/upgrade_config.go @@ -15,11 +15,9 @@ type rawPrecompileUpgrade struct { } type networkUpgradeConfigMessage struct { - OptionalNetworkUpgrades params.OptionalNetworkUpgrades `serialize:"true"` - + OptionalNetworkUpgrades *params.OptionalNetworkUpgrades `serialize:"true,omitempty"` // Config for modifying state as a network upgrade. StateUpgrades []params.StateUpgrade `serialize:"true"` - // Config for enabling and disabling precompiles as network upgrades. PrecompileUpgrades []rawPrecompileUpgrade `serialize:"true"` } @@ -64,7 +62,7 @@ func ParseUpgradeConfigMessage(bytes []byte) (*params.UpgradeConfig, error) { } return ¶ms.UpgradeConfig{ - OptionalNetworkUpgrades: &config.OptionalNetworkUpgrades, + OptionalNetworkUpgrades: config.OptionalNetworkUpgrades, StateUpgrades: config.StateUpgrades, PrecompileUpgrades: PrecompileUpgrades, }, nil @@ -92,13 +90,8 @@ func UpgradeConfigToNetworkMessage(config *params.UpgradeConfig) (*UpgradeConfig }) } - optionalNetworkUpgrades := config.OptionalNetworkUpgrades - if optionalNetworkUpgrades == nil { - optionalNetworkUpgrades = ¶ms.OptionalNetworkUpgrades{} - } - wrappedConfig := networkUpgradeConfigMessage{ - OptionalNetworkUpgrades: *optionalNetworkUpgrades, + OptionalNetworkUpgrades: config.OptionalNetworkUpgrades, StateUpgrades: config.StateUpgrades, PrecompileUpgrades: PrecompileUpgrades, } From c5d86a4f369c12964afdbccdcaaf14a5a2c1b83b Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 2 Nov 2023 01:47:41 -0300 Subject: [PATCH 08/48] Upgrade to the latest version --- go.mod | 6 ++---- go.sum | 12 ++++++------ params/network_upgrades.go | 2 +- plugin/evm/message/handshake/upgrade_config.go | 2 +- plugin/evm/syncervm_test.go | 4 ++-- plugin/evm/vm.go | 3 +-- plugin/evm/vm_test.go | 11 ++++++----- 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/go.mod b/go.mod index a77673cf58..72654ff33f 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/VictoriaMetrics/fastcache v1.10.0 github.com/ava-labs/avalanche-network-runner v1.7.3-0.20231026153158-2931f8a448d9 - github.com/ava-labs/avalanchego v1.10.14 + github.com/ava-labs/avalanchego v1.10.15 github.com/cespare/cp v0.1.0 github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 github.com/davecgh/go-spew v1.1.1 @@ -55,7 +55,7 @@ require ( github.com/DataDog/zstd v1.5.2 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect - github.com/ava-labs/coreth v0.12.7-rc.1 // indirect + github.com/ava-labs/coreth v0.12.8-rc.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect @@ -159,5 +159,3 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) - -replace github.com/ava-labs/avalanchego => github.com/ava-labs/avalanchego v1.10.14-0.20231020184934-1ad3e42ef00d diff --git a/go.sum b/go.sum index 1870cafc8b..652ba5ab6f 100644 --- a/go.sum +++ b/go.sum @@ -38,7 +38,7 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= @@ -61,10 +61,10 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/ava-labs/avalanche-network-runner v1.7.3-0.20231026153158-2931f8a448d9 h1:mTxfmBxmV8GSW0PUt0Qj/Obetzsw0gP6dtoNHaKW2+o= github.com/ava-labs/avalanche-network-runner v1.7.3-0.20231026153158-2931f8a448d9/go.mod h1:M9FC+xU4hQU3Botux8V8j574YETeX6tMvxiOmqLfl5c= -github.com/ava-labs/avalanchego v1.10.14-0.20231020184934-1ad3e42ef00d h1:KD/p5wpuW+F54PboAuhHx12Pu0ckez73zvIla3xzWiU= -github.com/ava-labs/avalanchego v1.10.14-0.20231020184934-1ad3e42ef00d/go.mod h1:tbPGmDognRVE/6xqqal/fszBZlr0jyll3KXXO/7cuqo= -github.com/ava-labs/coreth v0.12.7-rc.1 h1:fvjow2Jqkq1RNtW4v2Kx0DdTVp+3+fCY421TxpDDRfM= -github.com/ava-labs/coreth v0.12.7-rc.1/go.mod h1:sNbwitXv4AhLvWpSqy6V8yzkhGFeWBQFD31/xiRDJ5M= +github.com/ava-labs/avalanchego v1.10.15 h1:GQ1bkwgKnv5D/yUwXUjWPFqx1cWrf35WOaHSykHUXyE= +github.com/ava-labs/avalanchego v1.10.15/go.mod h1:fHTzxKZOMdM0n4EEXDDR0V3Ieb/Jnz7PM8zAsJRsh2U= +github.com/ava-labs/coreth v0.12.8-rc.1 h1:tvJcxQTQzxIQqx8TnrxdyMhZYbdsMaiy6AEiOyjvaa4= +github.com/ava-labs/coreth v0.12.8-rc.1/go.mod h1:GBH5SxHZdScSp95IijDs9+Gxw/QDIWvfoLKiJMNYLsE= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -194,7 +194,7 @@ github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= diff --git a/params/network_upgrades.go b/params/network_upgrades.go index 362479124b..01e7573ff8 100644 --- a/params/network_upgrades.go +++ b/params/network_upgrades.go @@ -82,7 +82,7 @@ func (m *OptionalFork) ToFork(name string) fork { } type OptionalNetworkUpgrades struct { - Test *OptionalFork `json:"test,omitempty" serialize:"true,omitempty"` + Test *OptionalFork `json:"test,omitempty" serialize:"true,nullable"` } func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetworkUpgrades, time uint64) *ConfigCompatError { diff --git a/plugin/evm/message/handshake/upgrade_config.go b/plugin/evm/message/handshake/upgrade_config.go index 1235ae6150..92323bfbc8 100644 --- a/plugin/evm/message/handshake/upgrade_config.go +++ b/plugin/evm/message/handshake/upgrade_config.go @@ -15,7 +15,7 @@ type rawPrecompileUpgrade struct { } type networkUpgradeConfigMessage struct { - OptionalNetworkUpgrades *params.OptionalNetworkUpgrades `serialize:"true,omitempty"` + OptionalNetworkUpgrades *params.OptionalNetworkUpgrades `serialize:"true,nullable"` // Config for modifying state as a network upgrade. StateUpgrades []params.StateUpgrade `serialize:"true"` // Config for enabling and disabling precompiles as network upgrades. diff --git a/plugin/evm/syncervm_test.go b/plugin/evm/syncervm_test.go index b764d5b60d..bcf8ea607b 100644 --- a/plugin/evm/syncervm_test.go +++ b/plugin/evm/syncervm_test.go @@ -15,7 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/ava-labs/avalanchego/database/manager" + "github.com/ava-labs/avalanchego/database" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/choices" @@ -386,7 +386,7 @@ type syncVMSetup struct { fundedAccounts map[*keystore.Key]*types.StateAccount syncerVM *VM - syncerDBManager manager.Manager + syncerDBManager database.Database syncerEngineChan <-chan commonEng.Message } diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 2fc4765202..f91e76f384 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -64,7 +64,6 @@ import ( "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/database/manager" "github.com/ava-labs/avalanchego/database/prefixdb" "github.com/ava-labs/avalanchego/database/versiondb" "github.com/ava-labs/avalanchego/ids" @@ -257,7 +256,7 @@ type VM struct { func (vm *VM) Initialize( _ context.Context, chainCtx *snow.Context, - dbManager manager.Manager, + dbManager database.Database, genesisBytes []byte, upgradeBytes []byte, configBytes []byte, diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index 2c71ebac15..a12c2b96fa 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -26,7 +26,8 @@ import ( "github.com/ava-labs/avalanchego/api/keystore" "github.com/ava-labs/avalanchego/chains/atomic" - "github.com/ava-labs/avalanchego/database/manager" + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/avalanchego/database/prefixdb" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" @@ -158,7 +159,7 @@ func setupGenesis( t *testing.T, genesisJSON string, ) (*snow.Context, - manager.Manager, + database.Database, []byte, chan commonEng.Message, *atomic.Memory, @@ -169,7 +170,7 @@ func setupGenesis( genesisBytes := buildGenesisTest(t, genesisJSON) ctx := NewContext() - baseDBManager := manager.NewMemDB(&version.Semantic{ + baseDBManager := memdb.New(&version.Semantic{ Major: 1, Minor: 4, Patch: 5, @@ -183,7 +184,7 @@ func setupGenesis( // The caller of this function is responsible for unlocking. ctx.Lock.Lock() - userKeystore := keystore.New(logging.NoLog{}, manager.NewMemDB(&version.Semantic{ + userKeystore := keystore.New(logging.NoLog{}, memdb.New(&version.Semantic{ Major: 1, Minor: 4, Patch: 5, @@ -208,7 +209,7 @@ func GenesisVM(t *testing.T, configJSON string, upgradeJSON string, ) (chan commonEng.Message, - *VM, manager.Manager, + *VM, database.Database, *commonEng.SenderTest, ) { vm := &VM{} From 453c84dc57add00740cb342408d17d1ff944f5da Mon Sep 17 00:00:00 2001 From: Cesar Date: Mon, 20 Nov 2023 10:36:50 -0300 Subject: [PATCH 09/48] Remove unknown field --- params/config_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/params/config_test.go b/params/config_test.go index 5939999068..899bc0bd52 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -339,7 +339,6 @@ func TestChainConfigMarshalWithUpgradesAndOptionalUpgrade(t *testing.T) { 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), @@ -383,7 +382,6 @@ func TestChainConfigMarshalWithUpgradesAndOptionalUpgrade(t *testing.T) { }, "homesteadBlock": 0, "eip150Block": 0, - "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", "eip155Block": 0, "eip158Block": 0, "byzantiumBlock": 0, From 7c507ac9dca23b30f15408612f0b7dc16326a2c1 Mon Sep 17 00:00:00 2001 From: Cesar Date: Mon, 20 Nov 2023 13:01:47 -0300 Subject: [PATCH 10/48] Address comments from PR --- ...de_config.go => upgrade_config_message.go} | 23 +++++++++++-------- ...test.go => upgrade_config_message_test.go} | 14 +++++------ 2 files changed, 21 insertions(+), 16 deletions(-) rename plugin/evm/message/handshake/{upgrade_config.go => upgrade_config_message.go} (89%) rename plugin/evm/message/handshake/{upgrade_config_test.go => upgrade_config_message_test.go} (66%) diff --git a/plugin/evm/message/handshake/upgrade_config.go b/plugin/evm/message/handshake/upgrade_config_message.go similarity index 89% rename from plugin/evm/message/handshake/upgrade_config.go rename to plugin/evm/message/handshake/upgrade_config_message.go index 92323bfbc8..36c585452b 100644 --- a/plugin/evm/message/handshake/upgrade_config.go +++ b/plugin/evm/message/handshake/upgrade_config_message.go @@ -23,8 +23,16 @@ type networkUpgradeConfigMessage struct { } type UpgradeConfigMessage struct { - Bytes []byte - Hash []byte + bytes []byte + hash []byte +} + +func (u *UpgradeConfigMessage) Bytes() []byte { + return u.bytes +} + +func (u *UpgradeConfigMessage) ID() []byte { + return u.hash } // Attempts to parse a networkUpgradeConfigMessage from a []byte @@ -34,7 +42,7 @@ type UpgradeConfigMessage struct { // UpgradeConfigToNetworkMessage). // // The function returns a reference of *params.UpgradeConfig -func ParseUpgradeConfigMessage(bytes []byte) (*params.UpgradeConfig, error) { +func NewUpgradeConfigMessageFromBytes(bytes []byte) (*params.UpgradeConfig, error) { var config networkUpgradeConfigMessage version, err := Codec.Unmarshal(bytes, &config) if err != nil { @@ -77,7 +85,7 @@ func ParseUpgradeConfigMessage(bytes []byte) (*params.UpgradeConfig, error) { // Since params.UpgradeConfig should never change without a node reloading, it // is safe to call this function once and store its output globally to re-use // multiple times -func UpgradeConfigToNetworkMessage(config *params.UpgradeConfig) (*UpgradeConfigMessage, error) { +func NewUpgradeConfigMessage(config *params.UpgradeConfig) (*UpgradeConfigMessage, error) { PrecompileUpgrades := make([]rawPrecompileUpgrade, 0) for _, precompileConfig := range config.PrecompileUpgrades { bytes, err := Codec.Marshal(Version, precompileConfig.Config) @@ -102,11 +110,8 @@ func UpgradeConfigToNetworkMessage(config *params.UpgradeConfig) (*UpgradeConfig } hash := crypto.Keccak256(bytes) - var firstBytes [8]byte - copy(firstBytes[:], hash[:8]) - return &UpgradeConfigMessage{ - Bytes: bytes, - Hash: hash, + bytes: bytes, + hash: hash[:8], }, nil } diff --git a/plugin/evm/message/handshake/upgrade_config_test.go b/plugin/evm/message/handshake/upgrade_config_message_test.go similarity index 66% rename from plugin/evm/message/handshake/upgrade_config_test.go rename to plugin/evm/message/handshake/upgrade_config_message_test.go index cc289a3880..e39ce8a51c 100644 --- a/plugin/evm/message/handshake/upgrade_config_test.go +++ b/plugin/evm/message/handshake/upgrade_config_message_test.go @@ -14,7 +14,7 @@ import ( func TestSerialize(t *testing.T) { var t0 uint64 = 0 var t1 uint64 = 1 - message, err := UpgradeConfigToNetworkMessage(¶ms.UpgradeConfig{ + message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ PrecompileUpgrades: []params.PrecompileUpgrade{ { Config: nativeminter.NewConfig(&t0, nil, nil, nil, nil), // enable at genesis @@ -26,19 +26,19 @@ func TestSerialize(t *testing.T) { }) require.NoError(t, err) - config, err := ParseUpgradeConfigMessage(message.Bytes) + config, err := NewUpgradeConfigMessageFromBytes(message.Bytes()) require.NoError(t, err) - message2, err := UpgradeConfigToNetworkMessage(config) + message2, err := NewUpgradeConfigMessage(config) require.NoError(t, err) - config3, err := ParseUpgradeConfigMessage(message2.Bytes) + config3, err := NewUpgradeConfigMessageFromBytes(message2.Bytes()) require.NoError(t, err) - message3, err := UpgradeConfigToNetworkMessage(config3) + message3, err := NewUpgradeConfigMessage(config3) require.NoError(t, err) require.Equal(t, config, config3) - require.Equal(t, message.Hash, message2.Hash) - require.Equal(t, message2.Hash, message3.Hash) + require.Equal(t, message.hash, message2.hash) + require.Equal(t, message2.hash, message3.hash) } From 9c954d5ce47965dfc71b6ba4657e489f3d9b0a20 Mon Sep 17 00:00:00 2001 From: Cesar Date: Mon, 20 Nov 2023 13:14:42 -0300 Subject: [PATCH 11/48] Update precompile template --- accounts/abi/bind/precompilebind/precompile_config_template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index 69c4fcbcc9..119054b448 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -26,7 +26,7 @@ var _ precompileconfig.Config = &Config{} // adds specific configuration for {{.Contract.Type}}. type Config struct { {{- if .Contract.AllowList}} - allowlist.AllowListConfig + allowlist.AllowListConfig ` + "`" + `serialize:"true"` + "`" + ` {{- end}} precompileconfig.Upgrade // CUSTOM CODE STARTS HERE From 771d5116a5a1385a8eaef1c45c480efbc5c2506a Mon Sep 17 00:00:00 2001 From: Cesar Date: Mon, 27 Nov 2023 13:02:04 -0300 Subject: [PATCH 12/48] Improve template --- .../abi/bind/precompilebind/precompile_config_template.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index 119054b448..dbb3a31b72 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -26,9 +26,13 @@ var _ precompileconfig.Config = &Config{} // adds specific configuration for {{.Contract.Type}}. type Config struct { {{- if .Contract.AllowList}} + // Serialize allowList to let nodes exchange information about their + // precompile configs allowlist.AllowListConfig ` + "`" + `serialize:"true"` + "`" + ` {{- end}} - precompileconfig.Upgrade + // Serialize the Upgrade config to let nodes exchange information about + // their precompile configs + precompileconfig.Upgrade ` + "`" + `serialize:"true"` + "`" + ` // CUSTOM CODE STARTS HERE // Add your own custom fields for Config here } From c261ce270d16db5351b1e1ec5e128a3d23fe6a9c Mon Sep 17 00:00:00 2001 From: Cesar Date: Mon, 27 Nov 2023 13:22:01 -0300 Subject: [PATCH 13/48] Add more test cases --- .../handshake/upgrade_config_message_test.go | 90 ++++++++++++++++--- 1 file changed, 77 insertions(+), 13 deletions(-) diff --git a/plugin/evm/message/handshake/upgrade_config_message_test.go b/plugin/evm/message/handshake/upgrade_config_message_test.go index e39ce8a51c..67bd604b4f 100644 --- a/plugin/evm/message/handshake/upgrade_config_message_test.go +++ b/plugin/evm/message/handshake/upgrade_config_message_test.go @@ -8,22 +8,21 @@ import ( "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/contracts/nativeminter" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/stretchr/testify/require" ) -func TestSerialize(t *testing.T) { - var t0 uint64 = 0 - var t1 uint64 = 1 - message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ - PrecompileUpgrades: []params.PrecompileUpgrade{ - { - Config: nativeminter.NewConfig(&t0, nil, nil, nil, nil), // enable at genesis - }, - { - Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 - }, - }, - }) +// Checks if messages have the same hash +// +// `message` is the simulation of a configuration being parsed from the local +// config. `message2` is parsing a message being exchanged through the network +// (a foreign config), and `message3` is the the deserialization and +// serialization of the foreign config. All 3 instances should have the same +// hashing, depite maybe not being identical (some configurations may be in a +// different order, but our hashing algorithm is resilient to those changes, +// thanks for our serialization library, which produces always the same output. +func assertConversions(t *testing.T, message *UpgradeConfigMessage, err error) { require.NoError(t, err) config, err := NewUpgradeConfigMessageFromBytes(message.Bytes()) @@ -42,3 +41,68 @@ func TestSerialize(t *testing.T) { require.Equal(t, message.hash, message2.hash) require.Equal(t, message2.hash, message3.hash) } + +func TestSerialize(t *testing.T) { + var t0 uint64 = 0 + var t1 uint64 = 1 + message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: nativeminter.NewConfig(&t0, nil, nil, nil, nil), // enable at genesis + }, + { + Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + }) + assertConversions(t, message, err) +} + +func TestWithAddress(t *testing.T) { + var t0 uint64 = 1 + var t1 uint64 = 11 + message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: nativeminter.NewConfig(&t0, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }, nil), // enable at genesis + }, + { + Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + }) + assertConversions(t, message, err) +} + +func TestWithAddressAndMint(t *testing.T) { + + var t0 uint64 = 2 + var t1 uint64 = 1001 + message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: nativeminter.NewConfig(&t0, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }, map[common.Address]*math.HexOrDecimal256{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000010")): math.NewHexOrDecimal256(64), + }), // enable at genesis + }, + { + Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + }) + assertConversions(t, message, err) +} From 6fff967a3d038123c9ee0e3b51470a975efb45a4 Mon Sep 17 00:00:00 2001 From: Cesar Date: Mon, 27 Nov 2023 14:01:16 -0300 Subject: [PATCH 14/48] Linting --- plugin/evm/message/handshake/upgrade_config_message_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/evm/message/handshake/upgrade_config_message_test.go b/plugin/evm/message/handshake/upgrade_config_message_test.go index 67bd604b4f..3545dad3f2 100644 --- a/plugin/evm/message/handshake/upgrade_config_message_test.go +++ b/plugin/evm/message/handshake/upgrade_config_message_test.go @@ -82,7 +82,6 @@ func TestWithAddress(t *testing.T) { } func TestWithAddressAndMint(t *testing.T) { - var t0 uint64 = 2 var t1 uint64 = 1001 message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ From e3601b0d40f66b01a7c0c070138a9e7b91c2ed5a Mon Sep 17 00:00:00 2001 From: Cesar Date: Mon, 27 Nov 2023 17:54:12 -0300 Subject: [PATCH 15/48] Remove Test config --- params/config_test.go | 14 -------------- params/network_upgrades.go | 25 ++++++++++++------------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/params/config_test.go b/params/config_test.go index 899bc0bd52..3e3c98ef32 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -330,8 +330,6 @@ func TestChainConfigMarshalWithUpgrades(t *testing.T) { } func TestChainConfigMarshalWithUpgradesAndOptionalUpgrade(t *testing.T) { - block := big.NewInt(0) - ts := uint64(102) config := ChainConfigWithUpgradesJSON{ ChainConfig: ChainConfig{ ChainID: big.NewInt(1), @@ -353,12 +351,6 @@ func TestChainConfigMarshalWithUpgradesAndOptionalUpgrade(t *testing.T) { GenesisPrecompiles: Precompiles{}, }, UpgradeConfig: UpgradeConfig{ - OptionalNetworkUpgrades: &OptionalNetworkUpgrades{ - Test: &OptionalFork{ - Block: block, - Timestamp: &ts, - }, - }, PrecompileUpgrades: []PrecompileUpgrade{ { Config: txallowlist.NewConfig(utils.NewUint64(100), nil, nil, nil), @@ -392,12 +384,6 @@ func TestChainConfigMarshalWithUpgradesAndOptionalUpgrade(t *testing.T) { "subnetEVMTimestamp": 0, "dUpgradeTimestamp": 0, "upgrades": { - "networkUpgrades": { - "test": { - "block": 0, - "timestamp": 102 - } - }, "precompileUpgrades": [ { "txAllowListConfig": { diff --git a/params/network_upgrades.go b/params/network_upgrades.go index 41f6a73bde..336b808fc6 100644 --- a/params/network_upgrades.go +++ b/params/network_upgrades.go @@ -4,8 +4,6 @@ package params import ( - "math/big" - "github.com/ava-labs/subnet-evm/utils" ) @@ -67,29 +65,25 @@ func (m *MandatoryNetworkUpgrades) mandatoryForkOrder() []fork { } type OptionalFork struct { - Block *big.Int `json:"block" serialize:"true"` - Timestamp *uint64 `json:"timestamp" serialize:"true"` + Timestamp *uint64 `json:"timestamp" serialize:"true"` } func (m *OptionalFork) ToFork(name string) fork { - var block *big.Int var timestamp *uint64 - if m.Block != nil { - block = m.Block - } if m.Timestamp != nil { timestamp = m.Timestamp } return fork{ name: name, - block: block, timestamp: timestamp, + block: nil, optional: true, } } type OptionalNetworkUpgrades struct { - Test *OptionalFork `json:"test,omitempty" serialize:"true,nullable"` + // This is an example of a configuration. + //FeatureConfig *OptionalFork `json:"test,omitempty" serialize:"true,nullable"` } func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetworkUpgrades, time uint64) *ConfigCompatError { @@ -98,8 +92,13 @@ func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetwor func (n *OptionalNetworkUpgrades) optionalForkOrder() []fork { forks := make([]fork, 0) - if n.Test != nil { - forks = append(forks, n.Test.ToFork("test")) - } + /* + // This block of code should be added for each property inside OptionalNetworkUpgrades + // Each property should have a test like https://github.com/ava-labs/subnet-evm/blob/c261ce270d16db5351b1e1ec5e128a3d23fe6a9c/params/config_test.go#L357-L360 + if n.FeatureConfig != nil { + forks = append(forks, FeatureConfig.ToFork("featureConfig")) + } + + */ return forks } From cade28fee2c82b32246dd9819cf909d336ccf1ac Mon Sep 17 00:00:00 2001 From: Cesar Date: Tue, 28 Nov 2023 02:04:56 -0300 Subject: [PATCH 16/48] Use whole hash instead of the first 8 bytes --- plugin/evm/message/handshake/upgrade_config_message.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugin/evm/message/handshake/upgrade_config_message.go b/plugin/evm/message/handshake/upgrade_config_message.go index 36c585452b..101dca5ec0 100644 --- a/plugin/evm/message/handshake/upgrade_config_message.go +++ b/plugin/evm/message/handshake/upgrade_config_message.go @@ -6,6 +6,7 @@ package handshake import ( "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/modules" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ) @@ -24,14 +25,14 @@ type networkUpgradeConfigMessage struct { type UpgradeConfigMessage struct { bytes []byte - hash []byte + hash common.Hash } func (u *UpgradeConfigMessage) Bytes() []byte { return u.bytes } -func (u *UpgradeConfigMessage) ID() []byte { +func (u *UpgradeConfigMessage) ID() common.Hash { return u.hash } @@ -109,9 +110,9 @@ func NewUpgradeConfigMessage(config *params.UpgradeConfig) (*UpgradeConfigMessag return nil, err } - hash := crypto.Keccak256(bytes) + hash := crypto.Keccak256Hash(bytes) return &UpgradeConfigMessage{ bytes: bytes, - hash: hash[:8], + hash: hash, }, nil } From d996f99e90c522b1dcb910d4795aa5d6a06af018 Mon Sep 17 00:00:00 2001 From: Cesar Date: Mon, 4 Dec 2023 10:50:20 -0300 Subject: [PATCH 17/48] Update how optional upgrades are going to be represented internally --- params/network_upgrades.go | 32 ++++---------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/params/network_upgrades.go b/params/network_upgrades.go index 336b808fc6..b7ced69ea1 100644 --- a/params/network_upgrades.go +++ b/params/network_upgrades.go @@ -64,26 +64,9 @@ func (m *MandatoryNetworkUpgrades) mandatoryForkOrder() []fork { } } -type OptionalFork struct { - Timestamp *uint64 `json:"timestamp" serialize:"true"` -} - -func (m *OptionalFork) ToFork(name string) fork { - var timestamp *uint64 - if m.Timestamp != nil { - timestamp = m.Timestamp - } - return fork{ - name: name, - timestamp: timestamp, - block: nil, - optional: true, - } -} - type OptionalNetworkUpgrades struct { // This is an example of a configuration. - //FeatureConfig *OptionalFork `json:"test,omitempty" serialize:"true,nullable"` + //FeatureConfig *uint64 `json:"test,omitempty" serialize:"true,nullable"` } func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetworkUpgrades, time uint64) *ConfigCompatError { @@ -91,14 +74,7 @@ func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetwor } func (n *OptionalNetworkUpgrades) optionalForkOrder() []fork { - forks := make([]fork, 0) - /* - // This block of code should be added for each property inside OptionalNetworkUpgrades - // Each property should have a test like https://github.com/ava-labs/subnet-evm/blob/c261ce270d16db5351b1e1ec5e128a3d23fe6a9c/params/config_test.go#L357-L360 - if n.FeatureConfig != nil { - forks = append(forks, FeatureConfig.ToFork("featureConfig")) - } - - */ - return forks + return []fork{ + // {name: "foo", timestamp: n.FooBar}, + } } From 634e9b5a96e12ce83457de1eb119e5af522b3cb9 Mon Sep 17 00:00:00 2001 From: Cesar Date: Tue, 12 Dec 2023 10:01:05 -0300 Subject: [PATCH 18/48] Add ToBytes() and FromBytes() to the Config interface This allows each precompile config to serialize and deserialize itself, removing the need to extend our codec to serialize / unserialize foreign structs. This PR will allow to hash configurations and to exchange it efficiently. --- commontype/fee_config.go | 52 ++++++++ .../handshake/upgrade_config_message.go | 7 +- .../handshake/upgrade_config_message_test.go | 116 ++++++++++++++++++ precompile/allowlist/allowlist_test.go | 8 ++ precompile/allowlist/config.go | 74 +++++++++++ .../contracts/deployerallowlist/config.go | 31 +++++ precompile/contracts/feemanager/config.go | 54 ++++++++ precompile/contracts/nativeminter/config.go | 67 ++++++++++ precompile/contracts/rewardmanager/config.go | 72 +++++++++++ precompile/contracts/txallowlist/config.go | 30 +++++ precompile/precompileconfig/config.go | 4 + precompile/precompileconfig/mocks.go | 9 ++ precompile/precompileconfig/upgradeable.go | 32 ++++- x/warp/config.go | 32 +++++ 14 files changed, 582 insertions(+), 6 deletions(-) diff --git a/commontype/fee_config.go b/commontype/fee_config.go index 3089df5d9c..aca3a5cd40 100644 --- a/commontype/fee_config.go +++ b/commontype/fee_config.go @@ -7,6 +7,7 @@ import ( "fmt" "math/big" + "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/utils" "github.com/ethereum/go-ethereum/common" ) @@ -144,6 +145,57 @@ func (f *FeeConfig) checkByteLens() error { return nil } +func (c *FeeConfig) getBigIntToSerialize() []**big.Int { + return []**big.Int{ + &c.GasLimit, &c.MinBaseFee, &c.TargetGas, &c.BaseFeeChangeDenominator, + &c.MinBlockGasCost, &c.MaxBlockGasCost, &c.BlockGasCostStep, + } +} + +func (c *FeeConfig) ToBytesWithPacker(p *wrappers.Packer) error { + for _, bigint := range c.getBigIntToSerialize() { + p.PackBool(*bigint == nil) + if p.Err != nil { + return p.Err + } + if bigint != nil { + p.PackBytes((*bigint).Bytes()) + if p.Err != nil { + return p.Err + } + } + } + p.PackLong(c.TargetBlockRate) + if p.Err != nil { + return p.Err + } + + return nil +} + +func (c *FeeConfig) FromBytesWithPacker(p *wrappers.Packer) error { + for _, bigint := range c.getBigIntToSerialize() { + isNil := p.UnpackBool() + if p.Err != nil { + return p.Err + } + if isNil { + continue + } + *bigint = big.NewInt(0).SetBytes(p.UnpackBytes()) + if p.Err != nil { + return p.Err + } + } + + c.TargetBlockRate = p.UnpackLong() + if p.Err != nil { + return p.Err + } + + return nil +} + func isBiggerThanHashLen(bigint *big.Int) bool { buf := bigint.Bytes() isBigger := len(buf) > common.HashLength diff --git a/plugin/evm/message/handshake/upgrade_config_message.go b/plugin/evm/message/handshake/upgrade_config_message.go index 101dca5ec0..240d65f0f7 100644 --- a/plugin/evm/message/handshake/upgrade_config_message.go +++ b/plugin/evm/message/handshake/upgrade_config_message.go @@ -60,10 +60,7 @@ func NewUpgradeConfigMessageFromBytes(bytes []byte) (*params.UpgradeConfig, erro return nil, ErrUnknowPrecompile } preCompile := module.MakeConfig() - version, err := Codec.Unmarshal(precompileUpgrade.Bytes, preCompile) - if version != Version { - return nil, ErrInvalidVersion - } + err := preCompile.FromBytes(precompileUpgrade.Bytes) if err != nil { return nil, err } @@ -89,7 +86,7 @@ func NewUpgradeConfigMessageFromBytes(bytes []byte) (*params.UpgradeConfig, erro func NewUpgradeConfigMessage(config *params.UpgradeConfig) (*UpgradeConfigMessage, error) { PrecompileUpgrades := make([]rawPrecompileUpgrade, 0) for _, precompileConfig := range config.PrecompileUpgrades { - bytes, err := Codec.Marshal(Version, precompileConfig.Config) + bytes, err := precompileConfig.Config.ToBytes() if err != nil { return nil, err } diff --git a/plugin/evm/message/handshake/upgrade_config_message_test.go b/plugin/evm/message/handshake/upgrade_config_message_test.go index 3545dad3f2..8e54ba47f9 100644 --- a/plugin/evm/message/handshake/upgrade_config_message_test.go +++ b/plugin/evm/message/handshake/upgrade_config_message_test.go @@ -4,10 +4,15 @@ package handshake import ( + "math/big" "testing" + "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/params" + "github.com/ava-labs/subnet-evm/precompile/contracts/deployerallowlist" + "github.com/ava-labs/subnet-evm/precompile/contracts/feemanager" "github.com/ava-labs/subnet-evm/precompile/contracts/nativeminter" + "github.com/ava-labs/subnet-evm/precompile/contracts/rewardmanager" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/stretchr/testify/require" @@ -96,6 +101,7 @@ func TestWithAddressAndMint(t *testing.T) { common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), }, map[common.Address]*math.HexOrDecimal256{ common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000010")): math.NewHexOrDecimal256(64), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000090")): math.NewHexOrDecimal256(6402100201021), }), // enable at genesis }, { @@ -105,3 +111,113 @@ func TestWithAddressAndMint(t *testing.T) { }) assertConversions(t, message, err) } + +func TestWithAddressFeeMinter(t *testing.T) { + var t0 uint64 = 2 + var t1 uint64 = 1001 + var validFeeConfig = commontype.FeeConfig{ + GasLimit: big.NewInt(8_000_000), + TargetBlockRate: 2, // in seconds + + MinBaseFee: big.NewInt(25_000_000_000), + TargetGas: big.NewInt(15_000_000), + BaseFeeChangeDenominator: big.NewInt(36), + + MinBlockGasCost: big.NewInt(0), + MaxBlockGasCost: big.NewInt(1_000_000), + BlockGasCostStep: big.NewInt(200_000), + } + + message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: feemanager.NewConfig(&t0, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }, &validFeeConfig), // enable at genesis + }, + { + Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + }) + assertConversions(t, message, err) +} + +func TestWithDepoyerAllowList(t *testing.T) { + var t0 uint64 = 2 + var t1 uint64 = 1001 + + message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: deployerallowlist.NewConfig(&t0, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }), // enable at genesis + }, + { + Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + }) + assertConversions(t, message, err) +} + +func TestWithRewardManager(t *testing.T) { + var t0 uint64 = 2 + var t1 uint64 = 1001 + + message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: rewardmanager.NewConfig(&t0, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }, nil), // enable at genesis + }, + { + Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + }) + assertConversions(t, message, err) +} + +func TestWithRewardManagerWithNil(t *testing.T) { + var t0 uint64 = 2 + var t1 uint64 = 1001 + + message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: rewardmanager.NewConfig(&t0, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }, &rewardmanager.InitialRewardConfig{ + AllowFeeRecipients: true, + }), + }, + { + Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + }) + assertConversions(t, message, err) +} diff --git a/precompile/allowlist/allowlist_test.go b/precompile/allowlist/allowlist_test.go index ebbcf6b69e..b63e8aea2e 100644 --- a/precompile/allowlist/allowlist_test.go +++ b/precompile/allowlist/allowlist_test.go @@ -39,6 +39,14 @@ func (d *dummyConfig) Equal(cfg precompileconfig.Config) bool { return d.AllowListConfig.Equal(&other.AllowListConfig) } +func (*dummyConfig) ToBytes() ([]byte, error) { + return nil, nil +} + +func (*dummyConfig) FromBytes([]byte) error { + return nil +} + type dummyConfigurator struct{} func (d *dummyConfigurator) MakeConfig() precompileconfig.Config { diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index 86e155fe28..7d0887c65f 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -4,8 +4,11 @@ package allowlist import ( + "bytes" "fmt" + "sort" + "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ethereum/go-ethereum/common" @@ -37,6 +40,43 @@ func (c *AllowListConfig) Configure(chainConfig precompileconfig.ChainConfig, pr return nil } +func (c *AllowListConfig) packAddresses(addresses []common.Address, p *wrappers.Packer) error { + sort.Slice(addresses, func(i, j int) bool { + return bytes.Compare(addresses[i][:], addresses[j][:]) < 0 + }) + + p.PackInt(uint32(len(addresses))) + if p.Err != nil { + return p.Err + } + + for _, address := range addresses { + p.PackBytes(address[:]) + if p.Err != nil { + return p.Err + } + } + return nil +} + +func (c *AllowListConfig) unpackAddresses(p *wrappers.Packer) ([]common.Address, error) { + length := p.UnpackInt() + if p.Err != nil { + return nil, p.Err + } + + addresses := make([]common.Address, length) + for i := uint32(0); i < length; i++ { + bytes := p.UnpackBytes() + addresses = append(addresses[:i], common.BytesToAddress(bytes)) + if p.Err != nil { + return nil, p.Err + } + } + + return addresses, nil +} + // Equal returns true iff [other] has the same admins in the same order in its allow list. func (c *AllowListConfig) Equal(other *AllowListConfig) bool { if other == nil { @@ -110,3 +150,37 @@ func (c *AllowListConfig) Verify(chainConfig precompileconfig.ChainConfig, upgra return nil } + +func (c *AllowListConfig) ToBytesWithPacker(p *wrappers.Packer) error { + if err := c.packAddresses(c.AdminAddresses, p); err != nil { + return err + } + if err := c.packAddresses(c.ManagerAddresses, p); err != nil { + return err + } + if err := c.packAddresses(c.EnabledAddresses, p); err != nil { + return err + } + return nil +} + +func (c *AllowListConfig) FromBytesWithPacker(p *wrappers.Packer) error { + admins, err := c.unpackAddresses(p) + if err != nil { + return err + } + managers, err := c.unpackAddresses(p) + if err != nil { + return err + } + enableds, err := c.unpackAddresses(p) + if err != nil { + return err + } + + c.AdminAddresses = admins + c.ManagerAddresses = managers + c.EnabledAddresses = enableds + + return nil +} diff --git a/precompile/contracts/deployerallowlist/config.go b/precompile/contracts/deployerallowlist/config.go index a588101dc3..3607a55da9 100644 --- a/precompile/contracts/deployerallowlist/config.go +++ b/precompile/contracts/deployerallowlist/config.go @@ -4,6 +4,7 @@ package deployerallowlist import ( + "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ethereum/go-ethereum/common" @@ -57,3 +58,33 @@ func (c *Config) Equal(cfg precompileconfig.Config) bool { func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { return c.AllowListConfig.Verify(chainConfig, c.Upgrade) } + +func (c *Config) ToBytes() ([]byte, error) { + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: 32 * 1024, + } + + if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { + return nil, err + } + + if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + return nil, err + } + + return p.Bytes, nil +} + +func (c *Config) FromBytes(bytes []byte) error { + p := wrappers.Packer{ + Bytes: bytes, + } + if err := c.AllowListConfig.FromBytesWithPacker(&p); err != nil { + return err + } + if err := c.Upgrade.FromBytesWithPacker(&p); err != nil { + return err + } + return nil +} diff --git a/precompile/contracts/feemanager/config.go b/precompile/contracts/feemanager/config.go index 0ab994a09a..ef4b986e3e 100644 --- a/precompile/contracts/feemanager/config.go +++ b/precompile/contracts/feemanager/config.go @@ -4,6 +4,7 @@ package feemanager import ( + "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" @@ -77,3 +78,56 @@ func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { return c.InitialFeeConfig.Verify() } + +func (c *Config) ToBytes() ([]byte, error) { + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: 32 * 1024, + } + + if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { + return nil, err + } + + if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + return nil, err + } + + if c.InitialFeeConfig == nil { + p.PackBool(true) + if p.Err != nil { + return nil, p.Err + } + } else { + p.PackBool(false) + if p.Err != nil { + return nil, p.Err + } + if err := c.InitialFeeConfig.ToBytesWithPacker(&p); err != nil { + return nil, err + } + } + + return p.Bytes, nil +} + +func (c *Config) FromBytes(bytes []byte) error { + p := wrappers.Packer{ + Bytes: bytes, + } + if err := c.AllowListConfig.FromBytesWithPacker(&p); err != nil { + return err + } + if err := c.Upgrade.FromBytesWithPacker(&p); err != nil { + return err + } + isNil := p.UnpackBool() + if !isNil { + c.InitialFeeConfig = &commontype.FeeConfig{} + if err := c.InitialFeeConfig.FromBytesWithPacker(&p); err != nil { + return err + } + } + + return nil +} diff --git a/precompile/contracts/nativeminter/config.go b/precompile/contracts/nativeminter/config.go index b02d780c8f..13164d3e8e 100644 --- a/precompile/contracts/nativeminter/config.go +++ b/precompile/contracts/nativeminter/config.go @@ -4,9 +4,12 @@ package nativeminter import ( + "bytes" "fmt" "math/big" + "sort" + "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/utils" @@ -95,3 +98,67 @@ func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { } return c.AllowListConfig.Verify(chainConfig, c.Upgrade) } + +func (c *Config) ToBytes() ([]byte, error) { + keys := make([]common.Address, 0) + for key := range c.InitialMint { + keys = append(keys, key) + } + + sort.Slice(keys, func(i, j int) bool { + return bytes.Compare(keys[i][:], keys[j][:]) < 0 + }) + + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: 32 * 1024, + } + + if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { + return nil, err + } + + if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + return nil, err + } + + p.PackInt(uint32(len(keys))) + if p.Err != nil { + return nil, p.Err + } + + for _, key := range keys { + p.PackBytes(key[:]) + if p.Err != nil { + return nil, p.Err + } + p.PackBytes((*big.Int)(c.InitialMint[key]).Bytes()) + if p.Err != nil { + return nil, p.Err + } + } + + return p.Bytes, nil +} + +func (c *Config) FromBytes(bytes []byte) error { + p := wrappers.Packer{ + Bytes: bytes, + } + if err := c.AllowListConfig.FromBytesWithPacker(&p); err != nil { + return err + } + if err := c.Upgrade.FromBytesWithPacker(&p); err != nil { + return err + } + len := p.UnpackInt() + c.InitialMint = make(map[common.Address]*math.HexOrDecimal256, len) + + for i := uint32(0); i < len; i++ { + key := common.BytesToAddress(p.UnpackBytes()) + value := p.UnpackBytes() + c.InitialMint[key] = (*math.HexOrDecimal256)(big.NewInt(0).SetBytes(value)) + } + + return nil +} diff --git a/precompile/contracts/rewardmanager/config.go b/precompile/contracts/rewardmanager/config.go index af947ff164..06a5caa22d 100644 --- a/precompile/contracts/rewardmanager/config.go +++ b/precompile/contracts/rewardmanager/config.go @@ -7,6 +7,7 @@ package rewardmanager import ( + "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" @@ -20,6 +21,27 @@ type InitialRewardConfig struct { RewardAddress common.Address `json:"rewardAddress,omitempty" serialize:"true"` } +func (u *InitialRewardConfig) ToBytesWithPacker(p *wrappers.Packer) error { + p.PackBool(u.AllowFeeRecipients) + if p.Err != nil { + return p.Err + } + p.PackBytes(u.RewardAddress[:]) + return p.Err +} + +func (u *InitialRewardConfig) FromBytesWithPacker(p *wrappers.Packer) error { + u.AllowFeeRecipients = p.UnpackBool() + if p.Err != nil { + return p.Err + } + u.RewardAddress = common.BytesToAddress(p.UnpackBytes()) + if p.Err != nil { + return p.Err + } + return nil +} + func (i *InitialRewardConfig) Equal(other *InitialRewardConfig) bool { if other == nil { return false @@ -115,3 +137,53 @@ func (c *Config) Equal(cfg precompileconfig.Config) bool { return c.Upgrade.Equal(&other.Upgrade) && c.AllowListConfig.Equal(&other.AllowListConfig) } + +func (c *Config) ToBytes() ([]byte, error) { + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: 32 * 1024, + } + + if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { + return nil, err + } + + if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + return nil, err + } + + p.PackBool(c.InitialRewardConfig == nil) + if p.Err != nil { + return nil, p.Err + } + + if c.InitialRewardConfig != nil { + if err := c.InitialRewardConfig.ToBytesWithPacker(&p); err != nil { + return nil, err + } + } + + return p.Bytes, nil +} + +func (c *Config) FromBytes(bytes []byte) error { + p := wrappers.Packer{ + Bytes: bytes, + } + if err := c.AllowListConfig.FromBytesWithPacker(&p); err != nil { + return err + } + if err := c.Upgrade.FromBytesWithPacker(&p); err != nil { + return err + } + + isNil := p.UnpackBool() + if !isNil { + c.InitialRewardConfig = &InitialRewardConfig{} + if err := c.InitialRewardConfig.FromBytesWithPacker(&p); err != nil { + return err + } + } + + return nil +} diff --git a/precompile/contracts/txallowlist/config.go b/precompile/contracts/txallowlist/config.go index f5656d9c78..2213f4fa1d 100644 --- a/precompile/contracts/txallowlist/config.go +++ b/precompile/contracts/txallowlist/config.go @@ -4,6 +4,7 @@ package txallowlist import ( + "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ethereum/go-ethereum/common" @@ -57,3 +58,32 @@ func (c *Config) Equal(cfg precompileconfig.Config) bool { func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { return c.AllowListConfig.Verify(chainConfig, c.Upgrade) } + +func (c *Config) ToBytes() ([]byte, error) { + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: 32 * 1024, + } + + if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { + return nil, err + } + + if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + return nil, err + } + + return p.Bytes, nil +} + +func (c *Config) FromBytes(bytes []byte) error { + p := wrappers.Packer{ + Bytes: bytes, + } + + if err := c.AllowListConfig.FromBytesWithPacker(&p); err != nil { + return err + } + + return c.Upgrade.FromBytesWithPacker(&p) +} diff --git a/precompile/precompileconfig/config.go b/precompile/precompileconfig/config.go index 52d4dda2ab..e8b186cd4b 100644 --- a/precompile/precompileconfig/config.go +++ b/precompile/precompileconfig/config.go @@ -30,6 +30,10 @@ type Config interface { Equal(Config) bool // Verify is called on startup and an error is treated as fatal. Configure can assume the Config has passed verification. Verify(ChainConfig) error + // Converts the current configuration to a vector of bytes. This vector of bytes is expected to be deterministic + ToBytes() ([]byte, error) + // Instantiates an object from a vector of bytes (the output of ToBytes()) + FromBytes([]byte) error } // PredicateContext is the context passed in to the Predicater interface to verify diff --git a/precompile/precompileconfig/mocks.go b/precompile/precompileconfig/mocks.go index df9c6ab031..c59998248c 100644 --- a/precompile/precompileconfig/mocks.go +++ b/precompile/precompileconfig/mocks.go @@ -87,6 +87,15 @@ func (m *MockConfig) EXPECT() *MockConfigMockRecorder { return m.recorder } +func (*MockConfig) ToBytes() ([]byte, error) { + return nil, nil +} + +func (*MockConfig) FromBytes([]byte) error { + return nil +} + + // Equal mocks base method. func (m *MockConfig) Equal(arg0 Config) bool { m.ctrl.T.Helper() diff --git a/precompile/precompileconfig/upgradeable.go b/precompile/precompileconfig/upgradeable.go index 9440f4573c..18fc63e96a 100644 --- a/precompile/precompileconfig/upgradeable.go +++ b/precompile/precompileconfig/upgradeable.go @@ -3,7 +3,10 @@ package precompileconfig -import "github.com/ava-labs/subnet-evm/utils" +import ( + "github.com/ava-labs/avalanchego/utils/wrappers" + "github.com/ava-labs/subnet-evm/utils" +) // Upgrade contains the timestamp for the upgrade along with // a boolean [Disable]. If [Disable] is set, the upgrade deactivates @@ -31,3 +34,30 @@ func (u *Upgrade) Equal(other *Upgrade) bool { } return u.Disable == other.Disable && utils.Uint64PtrEqual(u.BlockTimestamp, other.BlockTimestamp) } + +func (u *Upgrade) ToBytesWithPacker(p *wrappers.Packer) error { + if u.BlockTimestamp == nil { + p.PackBool(true) + } else { + p.PackBool(false) + if p.Err != nil { + return p.Err + } + p.PackLong(*u.BlockTimestamp) + } + if p.Err != nil { + return p.Err + } + p.PackBool(u.Disable) + return p.Err +} + +func (u *Upgrade) FromBytesWithPacker(p *wrappers.Packer) error { + isNil := p.UnpackBool() + if !isNil { + timestamp := p.UnpackLong() + u.BlockTimestamp = ×tamp + } + u.Disable = p.UnpackBool() + return nil +} diff --git a/x/warp/config.go b/x/warp/config.go index 60cd8336e7..8050cbc503 100644 --- a/x/warp/config.go +++ b/x/warp/config.go @@ -9,6 +9,7 @@ import ( "fmt" "github.com/ava-labs/avalanchego/utils/set" + "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/avalanchego/vms/platformvm/warp" "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload" "github.com/ava-labs/subnet-evm/params" @@ -225,3 +226,34 @@ func (c *Config) VerifyPredicate(predicateContext *precompileconfig.PredicateCon } return resultBitSet.Bytes() } + +func (c *Config) ToBytes() ([]byte, error) { + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: 32 * 1024, + } + + if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + return nil, err + } + + p.PackLong(c.QuorumNumerator) + if p.Err != nil { + return nil, p.Err + } + + return p.Bytes, nil +} + +func (c *Config) FromBytes(bytes []byte) error { + p := wrappers.Packer{ + Bytes: bytes, + } + if err := c.Upgrade.FromBytesWithPacker(&p); err != nil { + return err + } + + c.QuorumNumerator = p.UnpackLong() + + return p.Err +} From eef61ddb5844d86c5876f14c37ecb7f6bcba247b Mon Sep 17 00:00:00 2001 From: Cesar Date: Tue, 12 Dec 2023 20:14:09 -0300 Subject: [PATCH 19/48] Update template --- .../bind/precompilebind/precompile_config_template.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index dbb3a31b72..3793584e64 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -11,6 +11,8 @@ const tmplSourcePrecompileConfigGo = ` package {{.Package}} import ( + "errors" + "github.com/ava-labs/subnet-evm/precompile/precompileconfig" {{- if .Contract.AllowList}} "github.com/ava-labs/subnet-evm/precompile/allowlist" @@ -52,6 +54,14 @@ func NewConfig(blockTimestamp *uint64{{if .Contract.AllowList}}, admins []common } } +func (c * Config) ToBytes() ([]byte, error) { + return nil, errors.New("implement ToBytes() method") +} + +func (c * Config) FromBytes(bytes []byte) error { + return errors.New("implement FromBytes() method") +} + // NewDisableConfig returns config for a network upgrade at [blockTimestamp] // that disables {{.Contract.Type}}. func NewDisableConfig(blockTimestamp *uint64) *Config { From 541acd7045b88358dfa9e20c5f15404fe1373d20 Mon Sep 17 00:00:00 2001 From: Cesar Date: Tue, 12 Dec 2023 22:44:42 -0300 Subject: [PATCH 20/48] Update mocks --- precompile/precompileconfig/mocks.go | 38 +++++++++++++++++++++------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/precompile/precompileconfig/mocks.go b/precompile/precompileconfig/mocks.go index 90b43ebaf8..52219bf1eb 100644 --- a/precompile/precompileconfig/mocks.go +++ b/precompile/precompileconfig/mocks.go @@ -87,15 +87,6 @@ func (m *MockConfig) EXPECT() *MockConfigMockRecorder { return m.recorder } -func (*MockConfig) ToBytes() ([]byte, error) { - return nil, nil -} - -func (*MockConfig) FromBytes([]byte) error { - return nil -} - - // Equal mocks base method. func (m *MockConfig) Equal(arg0 Config) bool { m.ctrl.T.Helper() @@ -110,6 +101,20 @@ func (mr *MockConfigMockRecorder) Equal(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Equal", reflect.TypeOf((*MockConfig)(nil).Equal), arg0) } +// FromBytes mocks base method. +func (m *MockConfig) FromBytes(arg0 []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FromBytes", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// FromBytes indicates an expected call of FromBytes. +func (mr *MockConfigMockRecorder) FromBytes(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FromBytes", reflect.TypeOf((*MockConfig)(nil).FromBytes), arg0) +} + // IsDisabled mocks base method. func (m *MockConfig) IsDisabled() bool { m.ctrl.T.Helper() @@ -152,6 +157,21 @@ func (mr *MockConfigMockRecorder) Timestamp() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Timestamp", reflect.TypeOf((*MockConfig)(nil).Timestamp)) } +// ToBytes mocks base method. +func (m *MockConfig) ToBytes() ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ToBytes") + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ToBytes indicates an expected call of ToBytes. +func (mr *MockConfigMockRecorder) ToBytes() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ToBytes", reflect.TypeOf((*MockConfig)(nil).ToBytes)) +} + // Verify mocks base method. func (m *MockConfig) Verify(arg0 ChainConfig) error { m.ctrl.T.Helper() From 2309af50845d06d8030b296c477ebe9568cf74fa Mon Sep 17 00:00:00 2001 From: Cesar Date: Wed, 13 Dec 2023 17:59:37 -0300 Subject: [PATCH 21/48] Remove serialize tag --- .../abi/bind/precompilebind/precompile_config_template.go | 4 ++-- precompile/allowlist/config.go | 6 +++--- precompile/contracts/feemanager/config.go | 6 +++--- precompile/contracts/nativeminter/config.go | 6 +++--- precompile/contracts/rewardmanager/config.go | 4 ++-- precompile/precompileconfig/upgradeable.go | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index 3793584e64..2c714e879f 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -30,11 +30,11 @@ type Config struct { {{- if .Contract.AllowList}} // Serialize allowList to let nodes exchange information about their // precompile configs - allowlist.AllowListConfig ` + "`" + `serialize:"true"` + "`" + ` + allowlist.AllowListConfig {{- end}} // Serialize the Upgrade config to let nodes exchange information about // their precompile configs - precompileconfig.Upgrade ` + "`" + `serialize:"true"` + "`" + ` + precompileconfig.Upgrade // CUSTOM CODE STARTS HERE // Add your own custom fields for Config here } diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index 7d0887c65f..b8dc5d36c1 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -18,9 +18,9 @@ var ErrCannotAddManagersBeforeDUpgrade = fmt.Errorf("cannot add managers before // AllowListConfig specifies the initial set of addresses with Admin or Enabled roles. type AllowListConfig struct { - AdminAddresses []common.Address `json:"adminAddresses,omitempty" serialize:"true"` // initial admin addresses - ManagerAddresses []common.Address `json:"managerAddresses,omitempty" serialize:"true"` // initial manager addresses - EnabledAddresses []common.Address `json:"enabledAddresses,omitempty" serialize:"true"` // initial enabled addresses + AdminAddresses []common.Address `json:"adminAddresses,omitempty"` // initial admin addresses + ManagerAddresses []common.Address `json:"managerAddresses,omitempty"` // initial manager addresses + EnabledAddresses []common.Address `json:"enabledAddresses,omitempty"` // initial enabled addresses } // Configure initializes the address space of [precompileAddr] by initializing the role of each of diff --git a/precompile/contracts/feemanager/config.go b/precompile/contracts/feemanager/config.go index ef4b986e3e..3097c1ba4e 100644 --- a/precompile/contracts/feemanager/config.go +++ b/precompile/contracts/feemanager/config.go @@ -16,9 +16,9 @@ var _ precompileconfig.Config = &Config{} // Config implements the StatefulPrecompileConfig interface while adding in the // FeeManager specific precompile config. type Config struct { - allowlist.AllowListConfig `serialize:"true"` - precompileconfig.Upgrade `serialize:"true"` - InitialFeeConfig *commontype.FeeConfig `json:"initialFeeConfig,omitempty" serialize:"true"` // initial fee config to be immediately activated + allowlist.AllowListConfig + precompileconfig.Upgrade + InitialFeeConfig *commontype.FeeConfig `json:"initialFeeConfig,omitempty" ` // initial fee config to be immediately activated } // NewConfig returns a config for a network upgrade at [blockTimestamp] that enables diff --git a/precompile/contracts/nativeminter/config.go b/precompile/contracts/nativeminter/config.go index 13164d3e8e..e97a7e71fc 100644 --- a/precompile/contracts/nativeminter/config.go +++ b/precompile/contracts/nativeminter/config.go @@ -22,9 +22,9 @@ var _ precompileconfig.Config = &Config{} // Config implements the StatefulPrecompileConfig interface while adding in the // ContractNativeMinter specific precompile config. type Config struct { - allowlist.AllowListConfig `serialize:"true"` - precompileconfig.Upgrade `serialize:"true"` - InitialMint map[common.Address]*math.HexOrDecimal256 `json:"initialMint,omitempty" serialize:"true"` // addresses to receive the initial mint mapped to the amount to mint + allowlist.AllowListConfig + precompileconfig.Upgrade + InitialMint map[common.Address]*math.HexOrDecimal256 `json:"initialMint,omitempty"` } // NewConfig returns a config for a network upgrade at [blockTimestamp] that enables diff --git a/precompile/contracts/rewardmanager/config.go b/precompile/contracts/rewardmanager/config.go index 06a5caa22d..99952ff475 100644 --- a/precompile/contracts/rewardmanager/config.go +++ b/precompile/contracts/rewardmanager/config.go @@ -17,8 +17,8 @@ import ( var _ precompileconfig.Config = &Config{} type InitialRewardConfig struct { - AllowFeeRecipients bool `json:"allowFeeRecipients" serialize:"true"` - RewardAddress common.Address `json:"rewardAddress,omitempty" serialize:"true"` + AllowFeeRecipients bool `json:"allowFeeRecipients"` + RewardAddress common.Address `json:"rewardAddress,omitempty"` } func (u *InitialRewardConfig) ToBytesWithPacker(p *wrappers.Packer) error { diff --git a/precompile/precompileconfig/upgradeable.go b/precompile/precompileconfig/upgradeable.go index 18fc63e96a..8ae28860cd 100644 --- a/precompile/precompileconfig/upgradeable.go +++ b/precompile/precompileconfig/upgradeable.go @@ -12,8 +12,8 @@ import ( // a boolean [Disable]. If [Disable] is set, the upgrade deactivates // the precompile and clears its storage. type Upgrade struct { - BlockTimestamp *uint64 `json:"blockTimestamp" serialize:"true"` - Disable bool `json:"disable,omitempty" serialize:"true"` + BlockTimestamp *uint64 `json:"blockTimestamp"` + Disable bool `json:"disable,omitempty"` } // Timestamp returns the timestamp this network upgrade goes into effect. From 74e25d5f65a16a4ad5939702d921c2b958f23c85 Mon Sep 17 00:00:00 2001 From: Cesar Date: Wed, 13 Dec 2023 19:52:16 -0300 Subject: [PATCH 22/48] Implement custom marshal/unmarshal for all types Remove all reference to the codec and nullable (which is not longer supported). --- params/state_upgrade.go | 163 +++++++++++++++++- .../handshake/upgrade_config_message.go | 38 ++-- .../handshake/upgrade_config_message_test.go | 43 ++++- precompile/allowlist/config.go | 4 +- precompile/contracts/nativeminter/config.go | 6 + 5 files changed, 233 insertions(+), 21 deletions(-) diff --git a/params/state_upgrade.go b/params/state_upgrade.go index efcd32838d..02321905fa 100644 --- a/params/state_upgrade.go +++ b/params/state_upgrade.go @@ -4,9 +4,13 @@ package params import ( + "bytes" "fmt" + "math/big" "reflect" + "sort" + "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -16,18 +20,167 @@ import ( // StateUpgrade describes the modifications to be made to the state during // a state upgrade. type StateUpgrade struct { - BlockTimestamp *uint64 `json:"blockTimestamp,omitempty" serialize:"true"` + BlockTimestamp *uint64 `json:"blockTimestamp,omitempty"` // map from account address to the modification to be made to the account. - StateUpgradeAccounts map[common.Address]StateUpgradeAccount `json:"accounts" serialize:"true"` + StateUpgradeAccounts map[common.Address]StateUpgradeAccount `json:"accounts"` } // StateUpgradeAccount describes the modifications to be made to an account during // a state upgrade. type StateUpgradeAccount struct { - Code hexutil.Bytes `json:"code,omitempty" serialize:"true"` - Storage map[common.Hash]common.Hash `json:"storage,omitempty" serialize:"true"` - BalanceChange *math.HexOrDecimal256 `json:"balanceChange,omitempty" serialize:"true"` + Code hexutil.Bytes `json:"code,omitempty"` + Storage map[common.Hash]common.Hash `json:"storage,omitempty"` + BalanceChange *math.HexOrDecimal256 `json:"balanceChange,omitempty"` +} + +func (s *StateUpgrade) FromBytes(bytes []byte) error { + p := wrappers.Packer{ + Bytes: bytes, + } + + isNil := p.UnpackBool() + if p.Err != nil { + return p.Err + } + if !isNil { + blockTimestamp := p.UnpackLong() + if p.Err != nil { + return p.Err + } + s.BlockTimestamp = &blockTimestamp + } + + elements := p.UnpackInt() + if p.Err != nil { + return p.Err + } + s.StateUpgradeAccounts = make(map[common.Address]StateUpgradeAccount, elements) + for i := uint32(0); i < elements; i++ { + address := common.BytesToAddress(p.UnpackFixedBytes(common.AddressLength)) + if p.Err != nil { + return p.Err + } + + stateUpgradeAccount := StateUpgradeAccount{} + stateUpgradeAccount.Code = p.UnpackBytes() + if p.Err != nil { + return p.Err + } + isNil := p.UnpackBool() + if p.Err != nil { + return p.Err + } + if !isNil { + value := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + stateUpgradeAccount.BalanceChange = (*math.HexOrDecimal256)(big.NewInt(0).SetBytes(value)) + } + + storageElements := p.UnpackInt() + if p.Err != nil { + return p.Err + } + storage := make(map[common.Hash]common.Hash, storageElements) + for e := uint32(0); e < storageElements; e++ { + key := common.BytesToHash(p.UnpackFixedBytes(common.HashLength)) + if p.Err != nil { + return p.Err + } + value := common.BytesToHash(p.UnpackFixedBytes(common.HashLength)) + if p.Err != nil { + return p.Err + } + storage[key] = value + } + + stateUpgradeAccount.Storage = storage + s.StateUpgradeAccounts[address] = stateUpgradeAccount + } + + return nil +} + +func (s *StateUpgrade) ToBytes() ([]byte, error) { + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: 32 * 1024, + } + p.PackBool(s.BlockTimestamp == nil) + if p.Err != nil { + return nil, p.Err + } + if s.BlockTimestamp != nil { + p.PackLong(*s.BlockTimestamp) + if p.Err != nil { + return nil, p.Err + } + } + + p.PackInt(uint32(len(s.StateUpgradeAccounts))) + if p.Err != nil { + return nil, p.Err + } + + var addresses []common.Address + + for address := range s.StateUpgradeAccounts { + addresses = append(addresses, address) + } + + sort.Slice(addresses, func(i, j int) bool { + return bytes.Compare(addresses[i][:], addresses[j][:]) < 0 + }) + + for _, address := range addresses { + p.PackFixedBytes(address[:]) + if p.Err != nil { + return nil, p.Err + } + p.PackBytes(s.StateUpgradeAccounts[address].Code) + if p.Err != nil { + return nil, p.Err + } + p.PackBool(s.StateUpgradeAccounts[address].BalanceChange == nil) + if p.Err != nil { + return nil, p.Err + } + if s.StateUpgradeAccounts[address].BalanceChange != nil { + p.PackBytes((*big.Int)(s.StateUpgradeAccounts[address].BalanceChange).Bytes()) + if p.Err != nil { + return nil, p.Err + } + } + + p.PackInt(uint32(len(s.StateUpgradeAccounts[address].Storage))) + if p.Err != nil { + return nil, p.Err + } + + var hashes []common.Hash + for hash := range s.StateUpgradeAccounts[address].Storage { + hashes = append(hashes, hash) + } + sort.Slice(hashes, func(i, j int) bool { + return bytes.Compare(hashes[i][:], hashes[j][:]) < 0 + }) + + for _, hash := range hashes { + p.PackFixedBytes(hash[:]) + if p.Err != nil { + return nil, p.Err + } + bytes := s.StateUpgradeAccounts[address].Storage[hash] + p.PackFixedBytes(bytes[:]) + if p.Err != nil { + return nil, p.Err + } + } + } + + return p.Bytes, nil } func (s *StateUpgrade) Equal(other *StateUpgrade) bool { diff --git a/plugin/evm/message/handshake/upgrade_config_message.go b/plugin/evm/message/handshake/upgrade_config_message.go index 240d65f0f7..768880e9ea 100644 --- a/plugin/evm/message/handshake/upgrade_config_message.go +++ b/plugin/evm/message/handshake/upgrade_config_message.go @@ -16,9 +16,9 @@ type rawPrecompileUpgrade struct { } type networkUpgradeConfigMessage struct { - OptionalNetworkUpgrades *params.OptionalNetworkUpgrades `serialize:"true,nullable"` + OptionalNetworkUpgrades *params.OptionalNetworkUpgrades // Config for modifying state as a network upgrade. - StateUpgrades []params.StateUpgrade `serialize:"true"` + StateUpgrades [][]byte `serialize:"true"` // Config for enabling and disabling precompiles as network upgrades. PrecompileUpgrades []rawPrecompileUpgrade `serialize:"true"` } @@ -36,14 +36,8 @@ func (u *UpgradeConfigMessage) ID() common.Hash { return u.hash } -// Attempts to parse a networkUpgradeConfigMessage from a []byte -// -// This function attempts to parse a stream of bytes as a -// networkUpgradeConfigMessage (as serialized from -// UpgradeConfigToNetworkMessage). -// -// The function returns a reference of *params.UpgradeConfig -func NewUpgradeConfigMessageFromBytes(bytes []byte) (*params.UpgradeConfig, error) { +// Attempts to parse a `*params.UpgradeConfig` from a []byte +func NewUpgradeConfigFromBytes(bytes []byte) (*params.UpgradeConfig, error) { var config networkUpgradeConfigMessage version, err := Codec.Unmarshal(bytes, &config) if err != nil { @@ -67,9 +61,19 @@ func NewUpgradeConfigMessageFromBytes(bytes []byte) (*params.UpgradeConfig, erro PrecompileUpgrades = append(PrecompileUpgrades, params.PrecompileUpgrade{Config: preCompile}) } + var stateUpgrades []params.StateUpgrade + + for _, bytes := range config.StateUpgrades { + stateUpgrade := params.StateUpgrade{} + if err := stateUpgrade.FromBytes(bytes); err != nil { + return nil, err + } + stateUpgrades = append(stateUpgrades, stateUpgrade) + } + return ¶ms.UpgradeConfig{ OptionalNetworkUpgrades: config.OptionalNetworkUpgrades, - StateUpgrades: config.StateUpgrades, + StateUpgrades: stateUpgrades, PrecompileUpgrades: PrecompileUpgrades, }, nil } @@ -96,9 +100,19 @@ func NewUpgradeConfigMessage(config *params.UpgradeConfig) (*UpgradeConfigMessag }) } + stateUpgrades := make([][]byte, 0) + + for _, config := range config.StateUpgrades { + bytes, err := config.ToBytes() + if err != nil { + return nil, err + } + stateUpgrades = append(stateUpgrades, bytes) + } + wrappedConfig := networkUpgradeConfigMessage{ OptionalNetworkUpgrades: config.OptionalNetworkUpgrades, - StateUpgrades: config.StateUpgrades, + StateUpgrades: stateUpgrades, PrecompileUpgrades: PrecompileUpgrades, } diff --git a/plugin/evm/message/handshake/upgrade_config_message_test.go b/plugin/evm/message/handshake/upgrade_config_message_test.go index 8e54ba47f9..82d37be183 100644 --- a/plugin/evm/message/handshake/upgrade_config_message_test.go +++ b/plugin/evm/message/handshake/upgrade_config_message_test.go @@ -30,13 +30,13 @@ import ( func assertConversions(t *testing.T, message *UpgradeConfigMessage, err error) { require.NoError(t, err) - config, err := NewUpgradeConfigMessageFromBytes(message.Bytes()) + config, err := NewUpgradeConfigFromBytes(message.Bytes()) require.NoError(t, err) message2, err := NewUpgradeConfigMessage(config) require.NoError(t, err) - config3, err := NewUpgradeConfigMessageFromBytes(message2.Bytes()) + config3, err := NewUpgradeConfigFromBytes(message2.Bytes()) require.NoError(t, err) message3, err := NewUpgradeConfigMessage(config3) @@ -221,3 +221,42 @@ func TestWithRewardManagerWithNil(t *testing.T) { }) assertConversions(t, message, err) } + +func TestStateUpgrades(t *testing.T) { + var t0 uint64 = 2 + var t1 uint64 = 1001 + message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ + StateUpgrades: []params.StateUpgrade{ + { + BlockTimestamp: &t0, + StateUpgradeAccounts: map[common.Address]params.StateUpgradeAccount{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")): params.StateUpgradeAccount{ + Code: []byte{1, 2, 3, 4, 5, 6}, + BalanceChange: math.NewHexOrDecimal256(99), + Storage: map[common.Hash]common.Hash{ + common.BytesToHash([]byte{1, 2, 4, 5}): common.BytesToHash([]byte{1, 2, 3}), + }, + }, + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001000")): params.StateUpgradeAccount{ + Code: []byte{1, 2, 9, 93, 4, 5, 6}, + BalanceChange: math.NewHexOrDecimal256(92312319), + Storage: map[common.Hash]common.Hash{ + common.BytesToHash([]byte{11, 21, 99, 5}): common.BytesToHash([]byte{1, 2, 3}), + common.BytesToHash([]byte{1, 21, 99, 5}): common.BytesToHash([]byte{1, 2, 3}), + common.BytesToHash([]byte{1, 2, 99, 5}): common.BytesToHash([]byte{1, 2, 3}), + common.BytesToHash([]byte{1, 2, 4, 5}): common.BytesToHash([]byte{1, 2, 3}), + }, + }, + }, + }, + { + BlockTimestamp: &t1, + StateUpgradeAccounts: map[common.Address]params.StateUpgradeAccount{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001000")): params.StateUpgradeAccount{}, + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")): params.StateUpgradeAccount{}, + }, + }, + }, + }) + assertConversions(t, message, err) +} diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index b8dc5d36c1..b81b955306 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -51,7 +51,7 @@ func (c *AllowListConfig) packAddresses(addresses []common.Address, p *wrappers. } for _, address := range addresses { - p.PackBytes(address[:]) + p.PackFixedBytes(address[:]) if p.Err != nil { return p.Err } @@ -67,7 +67,7 @@ func (c *AllowListConfig) unpackAddresses(p *wrappers.Packer) ([]common.Address, addresses := make([]common.Address, length) for i := uint32(0); i < length; i++ { - bytes := p.UnpackBytes() + bytes := p.UnpackFixedBytes(common.AddressLength) addresses = append(addresses[:i], common.BytesToAddress(bytes)) if p.Err != nil { return nil, p.Err diff --git a/precompile/contracts/nativeminter/config.go b/precompile/contracts/nativeminter/config.go index e97a7e71fc..6ab1f23e33 100644 --- a/precompile/contracts/nativeminter/config.go +++ b/precompile/contracts/nativeminter/config.go @@ -156,7 +156,13 @@ func (c *Config) FromBytes(bytes []byte) error { for i := uint32(0); i < len; i++ { key := common.BytesToAddress(p.UnpackBytes()) + if p.Err != nil { + return p.Err + } value := p.UnpackBytes() + if p.Err != nil { + return p.Err + } c.InitialMint[key] = (*math.HexOrDecimal256)(big.NewInt(0).SetBytes(value)) } From f1d3d0755b7c0cc105d87e84592bbd668877e3ef Mon Sep 17 00:00:00 2001 From: Cesar Date: Wed, 13 Dec 2023 21:55:52 -0300 Subject: [PATCH 23/48] Use standard Marshal/Unmarshaller --- .../precompile_config_template.go | 6 +-- params/network_upgrades.go | 2 +- params/state_upgrade.go | 4 +- .../handshake/upgrade_config_message.go | 8 ++-- precompile/allowlist/allowlist_test.go | 4 +- .../contracts/deployerallowlist/config.go | 4 +- precompile/contracts/feemanager/config.go | 4 +- precompile/contracts/nativeminter/config.go | 4 +- precompile/contracts/rewardmanager/config.go | 4 +- precompile/contracts/txallowlist/config.go | 4 +- precompile/precompileconfig/config.go | 9 ++-- precompile/precompileconfig/mocks.go | 46 +++++++++---------- x/warp/config.go | 4 +- 13 files changed, 52 insertions(+), 51 deletions(-) diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index 2c714e879f..2fdb95df93 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -54,12 +54,12 @@ func NewConfig(blockTimestamp *uint64{{if .Contract.AllowList}}, admins []common } } -func (c * Config) ToBytes() ([]byte, error) { +func (c * Config) MarshalBinary() ([]byte, error) { return nil, errors.New("implement ToBytes() method") } -func (c * Config) FromBytes(bytes []byte) error { - return errors.New("implement FromBytes() method") +func (c * Config) UnmarshalBinary(bytes []byte) error { + return errors.New("implement UnmarshalBinary() method") } // NewDisableConfig returns config for a network upgrade at [blockTimestamp] diff --git a/params/network_upgrades.go b/params/network_upgrades.go index b7ced69ea1..607c2c6b57 100644 --- a/params/network_upgrades.go +++ b/params/network_upgrades.go @@ -66,7 +66,7 @@ func (m *MandatoryNetworkUpgrades) mandatoryForkOrder() []fork { type OptionalNetworkUpgrades struct { // This is an example of a configuration. - //FeatureConfig *uint64 `json:"test,omitempty" serialize:"true,nullable"` + //FeatureConfig *uint64 `json:"test,omitempty"` } func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetworkUpgrades, time uint64) *ConfigCompatError { diff --git a/params/state_upgrade.go b/params/state_upgrade.go index 02321905fa..93ace85e6f 100644 --- a/params/state_upgrade.go +++ b/params/state_upgrade.go @@ -34,7 +34,7 @@ type StateUpgradeAccount struct { BalanceChange *math.HexOrDecimal256 `json:"balanceChange,omitempty"` } -func (s *StateUpgrade) FromBytes(bytes []byte) error { +func (s *StateUpgrade) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } @@ -103,7 +103,7 @@ func (s *StateUpgrade) FromBytes(bytes []byte) error { return nil } -func (s *StateUpgrade) ToBytes() ([]byte, error) { +func (s *StateUpgrade) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, MaxSize: 32 * 1024, diff --git a/plugin/evm/message/handshake/upgrade_config_message.go b/plugin/evm/message/handshake/upgrade_config_message.go index 768880e9ea..278cbccfcf 100644 --- a/plugin/evm/message/handshake/upgrade_config_message.go +++ b/plugin/evm/message/handshake/upgrade_config_message.go @@ -54,7 +54,7 @@ func NewUpgradeConfigFromBytes(bytes []byte) (*params.UpgradeConfig, error) { return nil, ErrUnknowPrecompile } preCompile := module.MakeConfig() - err := preCompile.FromBytes(precompileUpgrade.Bytes) + err := preCompile.UnmarshalBinary(precompileUpgrade.Bytes) if err != nil { return nil, err } @@ -65,7 +65,7 @@ func NewUpgradeConfigFromBytes(bytes []byte) (*params.UpgradeConfig, error) { for _, bytes := range config.StateUpgrades { stateUpgrade := params.StateUpgrade{} - if err := stateUpgrade.FromBytes(bytes); err != nil { + if err := stateUpgrade.UnmarshalBinary(bytes); err != nil { return nil, err } stateUpgrades = append(stateUpgrades, stateUpgrade) @@ -90,7 +90,7 @@ func NewUpgradeConfigFromBytes(bytes []byte) (*params.UpgradeConfig, error) { func NewUpgradeConfigMessage(config *params.UpgradeConfig) (*UpgradeConfigMessage, error) { PrecompileUpgrades := make([]rawPrecompileUpgrade, 0) for _, precompileConfig := range config.PrecompileUpgrades { - bytes, err := precompileConfig.Config.ToBytes() + bytes, err := precompileConfig.Config.MarshalBinary() if err != nil { return nil, err } @@ -103,7 +103,7 @@ func NewUpgradeConfigMessage(config *params.UpgradeConfig) (*UpgradeConfigMessag stateUpgrades := make([][]byte, 0) for _, config := range config.StateUpgrades { - bytes, err := config.ToBytes() + bytes, err := config.MarshalBinary() if err != nil { return nil, err } diff --git a/precompile/allowlist/allowlist_test.go b/precompile/allowlist/allowlist_test.go index b63e8aea2e..ced0700149 100644 --- a/precompile/allowlist/allowlist_test.go +++ b/precompile/allowlist/allowlist_test.go @@ -39,11 +39,11 @@ func (d *dummyConfig) Equal(cfg precompileconfig.Config) bool { return d.AllowListConfig.Equal(&other.AllowListConfig) } -func (*dummyConfig) ToBytes() ([]byte, error) { +func (*dummyConfig) MarshalBinary() ([]byte, error) { return nil, nil } -func (*dummyConfig) FromBytes([]byte) error { +func (*dummyConfig) UnmarshalBinary([]byte) error { return nil } diff --git a/precompile/contracts/deployerallowlist/config.go b/precompile/contracts/deployerallowlist/config.go index 3607a55da9..a8b45e620d 100644 --- a/precompile/contracts/deployerallowlist/config.go +++ b/precompile/contracts/deployerallowlist/config.go @@ -59,7 +59,7 @@ func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { return c.AllowListConfig.Verify(chainConfig, c.Upgrade) } -func (c *Config) ToBytes() ([]byte, error) { +func (c *Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, MaxSize: 32 * 1024, @@ -76,7 +76,7 @@ func (c *Config) ToBytes() ([]byte, error) { return p.Bytes, nil } -func (c *Config) FromBytes(bytes []byte) error { +func (c *Config) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } diff --git a/precompile/contracts/feemanager/config.go b/precompile/contracts/feemanager/config.go index 3097c1ba4e..14a92b4a45 100644 --- a/precompile/contracts/feemanager/config.go +++ b/precompile/contracts/feemanager/config.go @@ -79,7 +79,7 @@ func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { return c.InitialFeeConfig.Verify() } -func (c *Config) ToBytes() ([]byte, error) { +func (c *Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, MaxSize: 32 * 1024, @@ -111,7 +111,7 @@ func (c *Config) ToBytes() ([]byte, error) { return p.Bytes, nil } -func (c *Config) FromBytes(bytes []byte) error { +func (c *Config) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } diff --git a/precompile/contracts/nativeminter/config.go b/precompile/contracts/nativeminter/config.go index 6ab1f23e33..1441d8927e 100644 --- a/precompile/contracts/nativeminter/config.go +++ b/precompile/contracts/nativeminter/config.go @@ -99,7 +99,7 @@ func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { return c.AllowListConfig.Verify(chainConfig, c.Upgrade) } -func (c *Config) ToBytes() ([]byte, error) { +func (c *Config) MarshalBinary() ([]byte, error) { keys := make([]common.Address, 0) for key := range c.InitialMint { keys = append(keys, key) @@ -141,7 +141,7 @@ func (c *Config) ToBytes() ([]byte, error) { return p.Bytes, nil } -func (c *Config) FromBytes(bytes []byte) error { +func (c *Config) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } diff --git a/precompile/contracts/rewardmanager/config.go b/precompile/contracts/rewardmanager/config.go index 99952ff475..1f89bb6659 100644 --- a/precompile/contracts/rewardmanager/config.go +++ b/precompile/contracts/rewardmanager/config.go @@ -138,7 +138,7 @@ func (c *Config) Equal(cfg precompileconfig.Config) bool { return c.Upgrade.Equal(&other.Upgrade) && c.AllowListConfig.Equal(&other.AllowListConfig) } -func (c *Config) ToBytes() ([]byte, error) { +func (c *Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, MaxSize: 32 * 1024, @@ -166,7 +166,7 @@ func (c *Config) ToBytes() ([]byte, error) { return p.Bytes, nil } -func (c *Config) FromBytes(bytes []byte) error { +func (c *Config) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } diff --git a/precompile/contracts/txallowlist/config.go b/precompile/contracts/txallowlist/config.go index 2213f4fa1d..48c823ca13 100644 --- a/precompile/contracts/txallowlist/config.go +++ b/precompile/contracts/txallowlist/config.go @@ -59,7 +59,7 @@ func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { return c.AllowListConfig.Verify(chainConfig, c.Upgrade) } -func (c *Config) ToBytes() ([]byte, error) { +func (c *Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, MaxSize: 32 * 1024, @@ -76,7 +76,7 @@ func (c *Config) ToBytes() ([]byte, error) { return p.Bytes, nil } -func (c *Config) FromBytes(bytes []byte) error { +func (c *Config) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } diff --git a/precompile/precompileconfig/config.go b/precompile/precompileconfig/config.go index a7da00ddaf..a87087597f 100644 --- a/precompile/precompileconfig/config.go +++ b/precompile/precompileconfig/config.go @@ -5,6 +5,8 @@ package precompileconfig import ( + "encoding" + "github.com/ava-labs/avalanchego/chains/atomic" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow" @@ -17,6 +19,9 @@ import ( // StatefulPrecompileConfig defines the interface for a stateful precompile to // be enabled via a network upgrade. type Config interface { + encoding.BinaryMarshaler + encoding.BinaryUnmarshaler + // Key returns the unique key for the stateful precompile. Key() string // Timestamp returns the timestamp at which this stateful precompile should be enabled. @@ -30,10 +35,6 @@ type Config interface { Equal(Config) bool // Verify is called on startup and an error is treated as fatal. Configure can assume the Config has passed verification. Verify(ChainConfig) error - // Converts the current configuration to a vector of bytes. This vector of bytes is expected to be deterministic - ToBytes() ([]byte, error) - // Instantiates an object from a vector of bytes (the output of ToBytes()) - FromBytes([]byte) error } // PredicateContext is the context passed in to the Predicater interface to verify diff --git a/precompile/precompileconfig/mocks.go b/precompile/precompileconfig/mocks.go index 52219bf1eb..ec82bdbe69 100644 --- a/precompile/precompileconfig/mocks.go +++ b/precompile/precompileconfig/mocks.go @@ -101,20 +101,6 @@ func (mr *MockConfigMockRecorder) Equal(arg0 interface{}) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Equal", reflect.TypeOf((*MockConfig)(nil).Equal), arg0) } -// FromBytes mocks base method. -func (m *MockConfig) FromBytes(arg0 []byte) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FromBytes", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// FromBytes indicates an expected call of FromBytes. -func (mr *MockConfigMockRecorder) FromBytes(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FromBytes", reflect.TypeOf((*MockConfig)(nil).FromBytes), arg0) -} - // IsDisabled mocks base method. func (m *MockConfig) IsDisabled() bool { m.ctrl.T.Helper() @@ -143,6 +129,21 @@ func (mr *MockConfigMockRecorder) Key() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Key", reflect.TypeOf((*MockConfig)(nil).Key)) } +// MarshalBinary mocks base method. +func (m *MockConfig) MarshalBinary() ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MarshalBinary") + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// MarshalBinary indicates an expected call of MarshalBinary. +func (mr *MockConfigMockRecorder) MarshalBinary() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MarshalBinary", reflect.TypeOf((*MockConfig)(nil).MarshalBinary)) +} + // Timestamp mocks base method. func (m *MockConfig) Timestamp() *uint64 { m.ctrl.T.Helper() @@ -157,19 +158,18 @@ func (mr *MockConfigMockRecorder) Timestamp() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Timestamp", reflect.TypeOf((*MockConfig)(nil).Timestamp)) } -// ToBytes mocks base method. -func (m *MockConfig) ToBytes() ([]byte, error) { +// UnmarshalBinary mocks base method. +func (m *MockConfig) UnmarshalBinary(arg0 []byte) error { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ToBytes") - ret0, _ := ret[0].([]byte) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret := m.ctrl.Call(m, "UnmarshalBinary", arg0) + ret0, _ := ret[0].(error) + return ret0 } -// ToBytes indicates an expected call of ToBytes. -func (mr *MockConfigMockRecorder) ToBytes() *gomock.Call { +// UnmarshalBinary indicates an expected call of UnmarshalBinary. +func (mr *MockConfigMockRecorder) UnmarshalBinary(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ToBytes", reflect.TypeOf((*MockConfig)(nil).ToBytes)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnmarshalBinary", reflect.TypeOf((*MockConfig)(nil).UnmarshalBinary), arg0) } // Verify mocks base method. diff --git a/x/warp/config.go b/x/warp/config.go index 18feda7a01..b8b1947c3f 100644 --- a/x/warp/config.go +++ b/x/warp/config.go @@ -212,7 +212,7 @@ func (c *Config) VerifyPredicate(predicateContext *precompileconfig.PredicateCon return nil } -func (c *Config) ToBytes() ([]byte, error) { +func (c *Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, MaxSize: 32 * 1024, @@ -230,7 +230,7 @@ func (c *Config) ToBytes() ([]byte, error) { return p.Bytes, nil } -func (c *Config) FromBytes(bytes []byte) error { +func (c *Config) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } From 55f4b956c11a2aad4b6b460843cba8c662ea75ca Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 14 Dec 2023 00:39:57 -0300 Subject: [PATCH 24/48] Implement UpgradeConfig Marshal/Unmarshal All code that was relying on the reflection codec is gone --- params/config.go | 124 +++++++++++++++++ .../config_marshal_unmarshal_test.go | 130 +++++++++++------- params/state_upgrade.go | 3 +- plugin/evm/message/handshake/codec.go | 43 ------ .../handshake/upgrade_config_message.go | 129 ----------------- .../contracts/deployerallowlist/config.go | 3 +- precompile/contracts/feemanager/config.go | 3 +- precompile/contracts/nativeminter/config.go | 3 +- precompile/contracts/rewardmanager/config.go | 3 +- precompile/contracts/txallowlist/config.go | 3 +- x/warp/config.go | 3 +- 11 files changed, 216 insertions(+), 231 deletions(-) rename plugin/evm/message/handshake/upgrade_config_message_test.go => params/config_marshal_unmarshal_test.go (73%) delete mode 100644 plugin/evm/message/handshake/codec.go delete mode 100644 plugin/evm/message/handshake/upgrade_config_message.go diff --git a/params/config.go b/params/config.go index 734b247e8f..f6e05b4f20 100644 --- a/params/config.go +++ b/params/config.go @@ -27,17 +27,21 @@ package params import ( + "bytes" "encoding/json" "errors" "fmt" "math/big" "github.com/ava-labs/avalanchego/snow" + "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/precompile/modules" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/utils" + "github.com/docker/docker/pkg/units" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" ) const maxJSONLen = 64 * 1024 * 1024 // 64MB @@ -67,6 +71,17 @@ var ( MaxBlockGasCost: big.NewInt(1_000_000), BlockGasCostStep: big.NewInt(200_000), } + + // For UpgradeConfig Marshal/Unmarshal + magicHeader = []byte{0xff} + sectionHeaderSizes = 1 + precompileHeader = []byte{0xaa} + stateUpdateHeader = []byte{0xc8} + endHeader = []byte{0} + ErrIncorrectHeader = errors.New("invalid magic header") + ErrMalformedConfigHeader = errors.New("malformed config header") + ErrUnknowPrecompile = errors.New("unknown precompile config") + MaxMessageSize = 1 * units.MiB ) var ( @@ -171,6 +186,115 @@ type UpgradeConfig struct { PrecompileUpgrades []PrecompileUpgrade `json:"precompileUpgrades,omitempty"` } +func (c *UpgradeConfig) Hash() (common.Hash, error) { + bytes, err := c.MarshalBinary() + if err != nil { + return common.Hash{}, err + } + return crypto.Keccak256Hash(bytes), nil +} + +func (c *UpgradeConfig) MarshalBinary() ([]byte, error) { + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: MaxMessageSize, + } + p.PackFixedBytes(magicHeader) + if p.Err != nil { + return nil, p.Err + } + + for _, precompileConfig := range c.PrecompileUpgrades { + bytes, err := precompileConfig.Config.MarshalBinary() + if err != nil { + return nil, err + } + p.PackFixedBytes(precompileHeader) + if p.Err != nil { + return nil, p.Err + } + p.PackStr(precompileConfig.Key()) + if p.Err != nil { + return nil, p.Err + } + p.PackBytes(bytes) + if p.Err != nil { + return nil, p.Err + } + } + + for _, config := range c.StateUpgrades { + bytes, err := config.MarshalBinary() + if err != nil { + return nil, err + } + p.PackFixedBytes(stateUpdateHeader) + if p.Err != nil { + return nil, p.Err + } + p.PackBytes(bytes) + if p.Err != nil { + return nil, p.Err + } + } + + p.PackFixedBytes(endHeader) + + return p.Bytes, nil +} + +func (c *UpgradeConfig) UnmarshalBinary(data []byte) error { + p := wrappers.Packer{ + Bytes: data, + } + if !bytes.Equal(p.UnpackFixedBytes(sectionHeaderSizes), magicHeader) { + return ErrIncorrectHeader + } + if p.Err != nil { + return p.Err + } + + for { + header := p.UnpackFixedBytes(sectionHeaderSizes) + if p.Err != nil { + return p.Err + } + if bytes.Equal(header, precompileHeader) { + key := p.UnpackStr() + if p.Err != nil { + return p.Err + } + config := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + module, ok := modules.GetPrecompileModule(key) + if !ok { + return ErrUnknowPrecompile + } + preCompile := module.MakeConfig() + err := preCompile.UnmarshalBinary(config) + if err != nil { + return err + } + c.PrecompileUpgrades = append(c.PrecompileUpgrades, PrecompileUpgrade{Config: preCompile}) + } else if bytes.Equal(header, stateUpdateHeader) { + config := p.UnpackBytes() + stateUpgrade := StateUpgrade{} + if err := stateUpgrade.UnmarshalBinary(config); err != nil { + return err + } + c.StateUpgrades = append(c.StateUpgrades, stateUpgrade) + } else if bytes.Equal(header, endHeader) { + break + } else { + return ErrMalformedConfigHeader + } + } + + return nil +} + // AvalancheContext provides Avalanche specific context directly into the EVM. type AvalancheContext struct { SnowCtx *snow.Context diff --git a/plugin/evm/message/handshake/upgrade_config_message_test.go b/params/config_marshal_unmarshal_test.go similarity index 73% rename from plugin/evm/message/handshake/upgrade_config_message_test.go rename to params/config_marshal_unmarshal_test.go index 82d37be183..0cfb34c034 100644 --- a/plugin/evm/message/handshake/upgrade_config_message_test.go +++ b/params/config_marshal_unmarshal_test.go @@ -1,14 +1,36 @@ -// (c) 2019-2020, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. +// (c) 2019-2020, Ava Labs, Inc. +// +// This file is a derived work, based on the go-ethereum library whose original +// notices appear below. +// +// It is distributed under a license compatible with the licensing terms of the +// original code from which it is derived. +// +// Much love to the original authors for their work. +// ********** +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . -package handshake +package params import ( "math/big" "testing" "github.com/ava-labs/subnet-evm/commontype" - "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/contracts/deployerallowlist" "github.com/ava-labs/subnet-evm/precompile/contracts/feemanager" "github.com/ava-labs/subnet-evm/precompile/contracts/nativeminter" @@ -27,31 +49,35 @@ import ( // hashing, depite maybe not being identical (some configurations may be in a // different order, but our hashing algorithm is resilient to those changes, // thanks for our serialization library, which produces always the same output. -func assertConversions(t *testing.T, message *UpgradeConfigMessage, err error) { +func assertConversions(t *testing.T, originalConfig *UpgradeConfig) { + bytes, err := originalConfig.MarshalBinary() require.NoError(t, err) - config, err := NewUpgradeConfigFromBytes(message.Bytes()) - require.NoError(t, err) + deserializedConfig := UpgradeConfig{} + require.NoError(t, deserializedConfig.UnmarshalBinary(bytes)) - message2, err := NewUpgradeConfigMessage(config) + twiceDeserialized := UpgradeConfig{} + newBytes, err := deserializedConfig.MarshalBinary() require.NoError(t, err) + require.NoError(t, twiceDeserialized.UnmarshalBinary(newBytes)) - config3, err := NewUpgradeConfigFromBytes(message2.Bytes()) + hash1, err := originalConfig.Hash() require.NoError(t, err) - - message3, err := NewUpgradeConfigMessage(config3) + hash2, err := deserializedConfig.Hash() + require.NoError(t, err) + hash3, err := twiceDeserialized.Hash() require.NoError(t, err) - require.Equal(t, config, config3) - require.Equal(t, message.hash, message2.hash) - require.Equal(t, message2.hash, message3.hash) + require.Equal(t, deserializedConfig, twiceDeserialized) + require.Equal(t, hash1, hash2) + require.Equal(t, hash2, hash3) } func TestSerialize(t *testing.T) { var t0 uint64 = 0 var t1 uint64 = 1 - message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ - PrecompileUpgrades: []params.PrecompileUpgrade{ + config := UpgradeConfig{ + PrecompileUpgrades: []PrecompileUpgrade{ { Config: nativeminter.NewConfig(&t0, nil, nil, nil, nil), // enable at genesis }, @@ -59,15 +85,15 @@ func TestSerialize(t *testing.T) { Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 }, }, - }) - assertConversions(t, message, err) + } + assertConversions(t, &config) } func TestWithAddress(t *testing.T) { var t0 uint64 = 1 var t1 uint64 = 11 - message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ - PrecompileUpgrades: []params.PrecompileUpgrade{ + config := UpgradeConfig{ + PrecompileUpgrades: []PrecompileUpgrade{ { Config: nativeminter.NewConfig(&t0, []common.Address{ common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), @@ -82,15 +108,15 @@ func TestWithAddress(t *testing.T) { Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 }, }, - }) - assertConversions(t, message, err) + } + assertConversions(t, &config) } func TestWithAddressAndMint(t *testing.T) { var t0 uint64 = 2 var t1 uint64 = 1001 - message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ - PrecompileUpgrades: []params.PrecompileUpgrade{ + config := UpgradeConfig{ + PrecompileUpgrades: []PrecompileUpgrade{ { Config: nativeminter.NewConfig(&t0, []common.Address{ common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), @@ -108,8 +134,8 @@ func TestWithAddressAndMint(t *testing.T) { Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 }, }, - }) - assertConversions(t, message, err) + } + assertConversions(t, &config) } func TestWithAddressFeeMinter(t *testing.T) { @@ -128,8 +154,8 @@ func TestWithAddressFeeMinter(t *testing.T) { BlockGasCostStep: big.NewInt(200_000), } - message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ - PrecompileUpgrades: []params.PrecompileUpgrade{ + config := UpgradeConfig{ + PrecompileUpgrades: []PrecompileUpgrade{ { Config: feemanager.NewConfig(&t0, []common.Address{ common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), @@ -144,16 +170,16 @@ func TestWithAddressFeeMinter(t *testing.T) { Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 }, }, - }) - assertConversions(t, message, err) + } + assertConversions(t, &config) } func TestWithDepoyerAllowList(t *testing.T) { var t0 uint64 = 2 var t1 uint64 = 1001 - message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ - PrecompileUpgrades: []params.PrecompileUpgrade{ + config := UpgradeConfig{ + PrecompileUpgrades: []PrecompileUpgrade{ { Config: deployerallowlist.NewConfig(&t0, []common.Address{ common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), @@ -168,16 +194,16 @@ func TestWithDepoyerAllowList(t *testing.T) { Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 }, }, - }) - assertConversions(t, message, err) + } + assertConversions(t, &config) } func TestWithRewardManager(t *testing.T) { var t0 uint64 = 2 var t1 uint64 = 1001 - message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ - PrecompileUpgrades: []params.PrecompileUpgrade{ + config := UpgradeConfig{ + PrecompileUpgrades: []PrecompileUpgrade{ { Config: rewardmanager.NewConfig(&t0, []common.Address{ common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), @@ -192,16 +218,16 @@ func TestWithRewardManager(t *testing.T) { Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 }, }, - }) - assertConversions(t, message, err) + } + assertConversions(t, &config) } func TestWithRewardManagerWithNil(t *testing.T) { var t0 uint64 = 2 var t1 uint64 = 1001 - message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ - PrecompileUpgrades: []params.PrecompileUpgrade{ + config := UpgradeConfig{ + PrecompileUpgrades: []PrecompileUpgrade{ { Config: rewardmanager.NewConfig(&t0, []common.Address{ common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), @@ -218,26 +244,26 @@ func TestWithRewardManagerWithNil(t *testing.T) { Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 }, }, - }) - assertConversions(t, message, err) + } + assertConversions(t, &config) } func TestStateUpgrades(t *testing.T) { var t0 uint64 = 2 var t1 uint64 = 1001 - message, err := NewUpgradeConfigMessage(¶ms.UpgradeConfig{ - StateUpgrades: []params.StateUpgrade{ + config := UpgradeConfig{ + StateUpgrades: []StateUpgrade{ { BlockTimestamp: &t0, - StateUpgradeAccounts: map[common.Address]params.StateUpgradeAccount{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")): params.StateUpgradeAccount{ + StateUpgradeAccounts: map[common.Address]StateUpgradeAccount{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")): StateUpgradeAccount{ Code: []byte{1, 2, 3, 4, 5, 6}, BalanceChange: math.NewHexOrDecimal256(99), Storage: map[common.Hash]common.Hash{ common.BytesToHash([]byte{1, 2, 4, 5}): common.BytesToHash([]byte{1, 2, 3}), }, }, - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001000")): params.StateUpgradeAccount{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001000")): StateUpgradeAccount{ Code: []byte{1, 2, 9, 93, 4, 5, 6}, BalanceChange: math.NewHexOrDecimal256(92312319), Storage: map[common.Hash]common.Hash{ @@ -251,12 +277,12 @@ func TestStateUpgrades(t *testing.T) { }, { BlockTimestamp: &t1, - StateUpgradeAccounts: map[common.Address]params.StateUpgradeAccount{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001000")): params.StateUpgradeAccount{}, - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")): params.StateUpgradeAccount{}, + StateUpgradeAccounts: map[common.Address]StateUpgradeAccount{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001000")): StateUpgradeAccount{}, + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")): StateUpgradeAccount{}, }, }, }, - }) - assertConversions(t, message, err) + } + assertConversions(t, &config) } diff --git a/params/state_upgrade.go b/params/state_upgrade.go index 93ace85e6f..06dd4a35b9 100644 --- a/params/state_upgrade.go +++ b/params/state_upgrade.go @@ -10,6 +10,7 @@ import ( "reflect" "sort" + "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/utils" "github.com/ethereum/go-ethereum/common" @@ -106,7 +107,7 @@ func (s *StateUpgrade) UnmarshalBinary(bytes []byte) error { func (s *StateUpgrade) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, - MaxSize: 32 * 1024, + MaxSize: 1 * units.MiB, } p.PackBool(s.BlockTimestamp == nil) if p.Err != nil { diff --git a/plugin/evm/message/handshake/codec.go b/plugin/evm/message/handshake/codec.go deleted file mode 100644 index f1943cc2fd..0000000000 --- a/plugin/evm/message/handshake/codec.go +++ /dev/null @@ -1,43 +0,0 @@ -// (c) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -// (c) 2019-2020, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package handshake - -import ( - "errors" - - "github.com/ava-labs/avalanchego/codec" - "github.com/ava-labs/avalanchego/codec/linearcodec" - "github.com/ava-labs/avalanchego/utils/units" - "github.com/ava-labs/avalanchego/utils/wrappers" -) - -const ( - Version = uint16(0) - maxMessageSize = 1 * units.MiB -) - -var ( - ErrInvalidVersion = errors.New("invalid version") - ErrUnknowPrecompile = errors.New("unknown precompile config") - Codec codec.Manager -) - -func init() { - Codec = codec.NewManager(maxMessageSize) - c := linearcodec.NewDefault() - - errs := wrappers.Errs{} - errs.Add( - c.RegisterType(networkUpgradeConfigMessage{}), - - Codec.RegisterCodec(Version, c), - ) - - if errs.Errored() { - panic(errs.Err) - } -} diff --git a/plugin/evm/message/handshake/upgrade_config_message.go b/plugin/evm/message/handshake/upgrade_config_message.go deleted file mode 100644 index 278cbccfcf..0000000000 --- a/plugin/evm/message/handshake/upgrade_config_message.go +++ /dev/null @@ -1,129 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package handshake - -import ( - "github.com/ava-labs/subnet-evm/params" - "github.com/ava-labs/subnet-evm/precompile/modules" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -type rawPrecompileUpgrade struct { - Key string `serialize:"true"` - Bytes []byte `serialize:"true"` -} - -type networkUpgradeConfigMessage struct { - OptionalNetworkUpgrades *params.OptionalNetworkUpgrades - // Config for modifying state as a network upgrade. - StateUpgrades [][]byte `serialize:"true"` - // Config for enabling and disabling precompiles as network upgrades. - PrecompileUpgrades []rawPrecompileUpgrade `serialize:"true"` -} - -type UpgradeConfigMessage struct { - bytes []byte - hash common.Hash -} - -func (u *UpgradeConfigMessage) Bytes() []byte { - return u.bytes -} - -func (u *UpgradeConfigMessage) ID() common.Hash { - return u.hash -} - -// Attempts to parse a `*params.UpgradeConfig` from a []byte -func NewUpgradeConfigFromBytes(bytes []byte) (*params.UpgradeConfig, error) { - var config networkUpgradeConfigMessage - version, err := Codec.Unmarshal(bytes, &config) - if err != nil { - return nil, err - } - if version != Version { - return nil, ErrInvalidVersion - } - - var PrecompileUpgrades []params.PrecompileUpgrade - for _, precompileUpgrade := range config.PrecompileUpgrades { - module, ok := modules.GetPrecompileModule(precompileUpgrade.Key) - if !ok { - return nil, ErrUnknowPrecompile - } - preCompile := module.MakeConfig() - err := preCompile.UnmarshalBinary(precompileUpgrade.Bytes) - if err != nil { - return nil, err - } - PrecompileUpgrades = append(PrecompileUpgrades, params.PrecompileUpgrade{Config: preCompile}) - } - - var stateUpgrades []params.StateUpgrade - - for _, bytes := range config.StateUpgrades { - stateUpgrade := params.StateUpgrade{} - if err := stateUpgrade.UnmarshalBinary(bytes); err != nil { - return nil, err - } - stateUpgrades = append(stateUpgrades, stateUpgrade) - } - - return ¶ms.UpgradeConfig{ - OptionalNetworkUpgrades: config.OptionalNetworkUpgrades, - StateUpgrades: stateUpgrades, - PrecompileUpgrades: PrecompileUpgrades, - }, nil -} - -// Wraps an instance of *params.UpgradeConfig -// -// This function returns the serialized UpgradeConfig, ready to be send over to -// other peers. The struct also includes a hash of the content, ready to be used -// as part of the handshake protocol. -// -// Since params.UpgradeConfig should never change without a node reloading, it -// is safe to call this function once and store its output globally to re-use -// multiple times -func NewUpgradeConfigMessage(config *params.UpgradeConfig) (*UpgradeConfigMessage, error) { - PrecompileUpgrades := make([]rawPrecompileUpgrade, 0) - for _, precompileConfig := range config.PrecompileUpgrades { - bytes, err := precompileConfig.Config.MarshalBinary() - if err != nil { - return nil, err - } - PrecompileUpgrades = append(PrecompileUpgrades, rawPrecompileUpgrade{ - Key: precompileConfig.Key(), - Bytes: bytes, - }) - } - - stateUpgrades := make([][]byte, 0) - - for _, config := range config.StateUpgrades { - bytes, err := config.MarshalBinary() - if err != nil { - return nil, err - } - stateUpgrades = append(stateUpgrades, bytes) - } - - wrappedConfig := networkUpgradeConfigMessage{ - OptionalNetworkUpgrades: config.OptionalNetworkUpgrades, - StateUpgrades: stateUpgrades, - PrecompileUpgrades: PrecompileUpgrades, - } - - bytes, err := Codec.Marshal(Version, wrappedConfig) - if err != nil { - return nil, err - } - - hash := crypto.Keccak256Hash(bytes) - return &UpgradeConfigMessage{ - bytes: bytes, - hash: hash, - }, nil -} diff --git a/precompile/contracts/deployerallowlist/config.go b/precompile/contracts/deployerallowlist/config.go index a8b45e620d..061d99ace5 100644 --- a/precompile/contracts/deployerallowlist/config.go +++ b/precompile/contracts/deployerallowlist/config.go @@ -7,6 +7,7 @@ import ( "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/docker/docker/pkg/units" "github.com/ethereum/go-ethereum/common" ) @@ -62,7 +63,7 @@ func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { func (c *Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, - MaxSize: 32 * 1024, + MaxSize: 1 * units.MiB, } if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { diff --git a/precompile/contracts/feemanager/config.go b/precompile/contracts/feemanager/config.go index 14a92b4a45..f047f693fe 100644 --- a/precompile/contracts/feemanager/config.go +++ b/precompile/contracts/feemanager/config.go @@ -8,6 +8,7 @@ import ( "github.com/ava-labs/subnet-evm/commontype" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/docker/docker/pkg/units" "github.com/ethereum/go-ethereum/common" ) @@ -82,7 +83,7 @@ func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { func (c *Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, - MaxSize: 32 * 1024, + MaxSize: 1 * units.MiB, } if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { diff --git a/precompile/contracts/nativeminter/config.go b/precompile/contracts/nativeminter/config.go index 1441d8927e..99703a8469 100644 --- a/precompile/contracts/nativeminter/config.go +++ b/precompile/contracts/nativeminter/config.go @@ -13,6 +13,7 @@ import ( "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/utils" + "github.com/docker/docker/pkg/units" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" ) @@ -111,7 +112,7 @@ func (c *Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, - MaxSize: 32 * 1024, + MaxSize: 1 * units.MiB, } if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { diff --git a/precompile/contracts/rewardmanager/config.go b/precompile/contracts/rewardmanager/config.go index 1f89bb6659..0d3a6bf914 100644 --- a/precompile/contracts/rewardmanager/config.go +++ b/precompile/contracts/rewardmanager/config.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/docker/docker/pkg/units" "github.com/ethereum/go-ethereum/common" ) @@ -141,7 +142,7 @@ func (c *Config) Equal(cfg precompileconfig.Config) bool { func (c *Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, - MaxSize: 32 * 1024, + MaxSize: 1 * units.MiB, } if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { diff --git a/precompile/contracts/txallowlist/config.go b/precompile/contracts/txallowlist/config.go index 48c823ca13..859d61db34 100644 --- a/precompile/contracts/txallowlist/config.go +++ b/precompile/contracts/txallowlist/config.go @@ -7,6 +7,7 @@ import ( "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/docker/docker/pkg/units" "github.com/ethereum/go-ethereum/common" ) @@ -62,7 +63,7 @@ func (c *Config) Verify(chainConfig precompileconfig.ChainConfig) error { func (c *Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, - MaxSize: 32 * 1024, + MaxSize: 1 * units.MiB, } if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { diff --git a/x/warp/config.go b/x/warp/config.go index b8b1947c3f..53731132e3 100644 --- a/x/warp/config.go +++ b/x/warp/config.go @@ -15,6 +15,7 @@ import ( "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/predicate" warpValidators "github.com/ava-labs/subnet-evm/warp/validators" + "github.com/docker/docker/pkg/units" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/log" @@ -215,7 +216,7 @@ func (c *Config) VerifyPredicate(predicateContext *precompileconfig.PredicateCon func (c *Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, - MaxSize: 32 * 1024, + MaxSize: 1 * units.MiB, } if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { From d9851ca302aa3a1bb9548dcbe76b5e588a25c8bf Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 14 Dec 2023 10:15:22 -0300 Subject: [PATCH 25/48] Added Marshal / Unmarshal to OptionalNetworkUpgrades --- params/config.go | 27 +++++++++++++++++++++++++++ params/network_upgrades.go | 10 ++++++++++ 2 files changed, 37 insertions(+) diff --git a/params/config.go b/params/config.go index f6e05b4f20..224863264f 100644 --- a/params/config.go +++ b/params/config.go @@ -204,6 +204,21 @@ func (c *UpgradeConfig) MarshalBinary() ([]byte, error) { return nil, p.Err } + p.PackBool(c.OptionalNetworkUpgrades == nil) + if p.Err != nil { + return nil, p.Err + } + if c.OptionalNetworkUpgrades != nil { + bytes, err := c.OptionalNetworkUpgrades.MarshalBinary() + if err != nil { + return nil, err + } + p.PackBytes(bytes) + if p.Err != nil { + return nil, p.Err + } + } + for _, precompileConfig := range c.PrecompileUpgrades { bytes, err := precompileConfig.Config.MarshalBinary() if err != nil { @@ -254,6 +269,18 @@ func (c *UpgradeConfig) UnmarshalBinary(data []byte) error { return p.Err } + isNil := p.UnpackBool() + if !isNil { + c.OptionalNetworkUpgrades = &OptionalNetworkUpgrades{} + bytes := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + if err := c.OptionalNetworkUpgrades.UnmarshalBinary(bytes); err != nil { + return nil + } + } + for { header := p.UnpackFixedBytes(sectionHeaderSizes) if p.Err != nil { diff --git a/params/network_upgrades.go b/params/network_upgrades.go index 607c2c6b57..466e3e31c8 100644 --- a/params/network_upgrades.go +++ b/params/network_upgrades.go @@ -4,6 +4,8 @@ package params import ( + "errors" + "github.com/ava-labs/subnet-evm/utils" ) @@ -69,6 +71,14 @@ type OptionalNetworkUpgrades struct { //FeatureConfig *uint64 `json:"test,omitempty"` } +func (m *OptionalNetworkUpgrades) MarshalBinary() ([]byte, error) { + return nil, errors.New("implement MarshalBinary() for OptionalNetworkUpgrades") +} + +func (m *OptionalNetworkUpgrades) UnmarshalBinary(data []byte) error { + return errors.New("implement UnmarshalBinary() for OptionalNetworkUpgrades") +} + func (n *OptionalNetworkUpgrades) CheckOptionalCompatible(newcfg *OptionalNetworkUpgrades, time uint64) *ConfigCompatError { return nil } From 1946de42fbc6c23b9087e0b3bfd41b187a9548d7 Mon Sep 17 00:00:00 2001 From: Cesar Date: Fri, 15 Dec 2023 10:40:17 -0300 Subject: [PATCH 26/48] Remove sorting from AllowListConfig Although a list of address is identical the same to the system regardless of their sorting as long as the contain the same values (`["addr1", "addr2"]` is identical as `["addr2", "addr1"]`). The first iteration of this PR would have sorted the slice of addresses before serializing to produce a canonical slice of bytes and the same hash It is decided copy JSON and honour the definition from the config JSON. Most users should copying a JSON file instead of trying to manually edit them. At this time it is preferred to be strict about the JSON. If it is ever decided otherwise, bring back this behaviour, this commit can be rolled back without any side effect. --- precompile/allowlist/config.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index b81b955306..6487b9f47d 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -4,9 +4,7 @@ package allowlist import ( - "bytes" "fmt" - "sort" "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/precompile/contract" @@ -41,10 +39,6 @@ func (c *AllowListConfig) Configure(chainConfig precompileconfig.ChainConfig, pr } func (c *AllowListConfig) packAddresses(addresses []common.Address, p *wrappers.Packer) error { - sort.Slice(addresses, func(i, j int) bool { - return bytes.Compare(addresses[i][:], addresses[j][:]) < 0 - }) - p.PackInt(uint32(len(addresses))) if p.Err != nil { return p.Err From 2efae3d89260bdf214af82e680ad281ee9c2a4d7 Mon Sep 17 00:00:00 2001 From: Cesar Date: Fri, 15 Dec 2023 15:12:23 -0300 Subject: [PATCH 27/48] Move tests to their own file --- .../precompile_config_template.go | 2 +- .../precompile_config_test_template.go | 31 ++ params/config.go | 35 +++ params/config_marshal_unmarshal_test.go | 288 ------------------ params/state_upgrade_test.go | 39 +++ .../contracts/feemanager/config_test.go | 37 +++ .../contracts/nativeminter/config_test.go | 65 ++++ .../contracts/rewardmanager/config_test.go | 51 ++++ 8 files changed, 259 insertions(+), 289 deletions(-) delete mode 100644 params/config_marshal_unmarshal_test.go diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index 2fdb95df93..a510c1cf9e 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -55,7 +55,7 @@ func NewConfig(blockTimestamp *uint64{{if .Contract.AllowList}}, admins []common } func (c * Config) MarshalBinary() ([]byte, error) { - return nil, errors.New("implement ToBytes() method") + return nil, errors.New("implement MarshalBinary() method") } func (c * Config) UnmarshalBinary(bytes []byte) error { diff --git a/accounts/abi/bind/precompilebind/precompile_config_test_template.go b/accounts/abi/bind/precompilebind/precompile_config_test_template.go index 9d09c8fb83..08ab6ff13c 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_test_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_test_template.go @@ -13,6 +13,7 @@ package {{.Package}} import ( "testing" + "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/precompile/testutils" "github.com/ava-labs/subnet-evm/utils" @@ -22,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" {{- end}} "go.uber.org/mock/gomock" + "github.com/stretchr/testify/require" ) // TestVerify tests the verification of Config. @@ -61,6 +63,35 @@ func TestVerify(t *testing.T) { {{- end}} } +func TestSerialize(t *testing.T) { + var t0 uint64 = 2 + var t1 uint64 = 1001 + + config := params.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: NewConfig(&t0, + {{- if .Contract.AllowList}} + []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }, + {{- end}} + ), // enable at genesis + }, + { + Config: NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + } + require.NotNil(t, config) + //params.AssertConfigHashesAndSerialization(t, &config) +} + // TestEqual tests the equality of Config with other precompile configs. func TestEqual(t *testing.T) { {{- if .Contract.AllowList}} diff --git a/params/config.go b/params/config.go index 224863264f..6765cd1fd0 100644 --- a/params/config.go +++ b/params/config.go @@ -32,6 +32,7 @@ import ( "errors" "fmt" "math/big" + "testing" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/utils/wrappers" @@ -42,6 +43,7 @@ import ( "github.com/docker/docker/pkg/units" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/stretchr/testify/require" ) const maxJSONLen = 64 * 1024 * 1024 // 64MB @@ -1016,3 +1018,36 @@ func (c *ChainConfig) ToWithUpgradesJSON() *ChainConfigWithUpgradesJSON { UpgradeConfig: c.UpgradeConfig, } } + +// Checks if messages have the same hash +// +// `message` is the simulation of a configuration being parsed from the local +// config. `message2` is parsing a message being exchanged through the network +// (a foreign config), and `message3` is the the deserialization and +// serialization of the foreign config. All 3 instances should have the same +// hashing, depite maybe not being identical (some configurations may be in a +// different order, but our hashing algorithm is resilient to those changes, +// thanks for our serialization library, which produces always the same output. +func AssertConfigHashesAndSerialization(t *testing.T, originalConfig *UpgradeConfig) { + bytes, err := originalConfig.MarshalBinary() + require.NoError(t, err) + + deserializedConfig := UpgradeConfig{} + require.NoError(t, deserializedConfig.UnmarshalBinary(bytes)) + + twiceDeserialized := UpgradeConfig{} + newBytes, err := deserializedConfig.MarshalBinary() + require.NoError(t, err) + require.NoError(t, twiceDeserialized.UnmarshalBinary(newBytes)) + + hash1, err := originalConfig.Hash() + require.NoError(t, err) + hash2, err := deserializedConfig.Hash() + require.NoError(t, err) + hash3, err := twiceDeserialized.Hash() + require.NoError(t, err) + + require.Equal(t, deserializedConfig, twiceDeserialized) + require.Equal(t, hash1, hash2) + require.Equal(t, hash2, hash3) +} diff --git a/params/config_marshal_unmarshal_test.go b/params/config_marshal_unmarshal_test.go deleted file mode 100644 index 0cfb34c034..0000000000 --- a/params/config_marshal_unmarshal_test.go +++ /dev/null @@ -1,288 +0,0 @@ -// (c) 2019-2020, Ava Labs, Inc. -// -// This file is a derived work, based on the go-ethereum library whose original -// notices appear below. -// -// It is distributed under a license compatible with the licensing terms of the -// original code from which it is derived. -// -// Much love to the original authors for their work. -// ********** -// Copyright 2017 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package params - -import ( - "math/big" - "testing" - - "github.com/ava-labs/subnet-evm/commontype" - "github.com/ava-labs/subnet-evm/precompile/contracts/deployerallowlist" - "github.com/ava-labs/subnet-evm/precompile/contracts/feemanager" - "github.com/ava-labs/subnet-evm/precompile/contracts/nativeminter" - "github.com/ava-labs/subnet-evm/precompile/contracts/rewardmanager" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/math" - "github.com/stretchr/testify/require" -) - -// Checks if messages have the same hash -// -// `message` is the simulation of a configuration being parsed from the local -// config. `message2` is parsing a message being exchanged through the network -// (a foreign config), and `message3` is the the deserialization and -// serialization of the foreign config. All 3 instances should have the same -// hashing, depite maybe not being identical (some configurations may be in a -// different order, but our hashing algorithm is resilient to those changes, -// thanks for our serialization library, which produces always the same output. -func assertConversions(t *testing.T, originalConfig *UpgradeConfig) { - bytes, err := originalConfig.MarshalBinary() - require.NoError(t, err) - - deserializedConfig := UpgradeConfig{} - require.NoError(t, deserializedConfig.UnmarshalBinary(bytes)) - - twiceDeserialized := UpgradeConfig{} - newBytes, err := deserializedConfig.MarshalBinary() - require.NoError(t, err) - require.NoError(t, twiceDeserialized.UnmarshalBinary(newBytes)) - - hash1, err := originalConfig.Hash() - require.NoError(t, err) - hash2, err := deserializedConfig.Hash() - require.NoError(t, err) - hash3, err := twiceDeserialized.Hash() - require.NoError(t, err) - - require.Equal(t, deserializedConfig, twiceDeserialized) - require.Equal(t, hash1, hash2) - require.Equal(t, hash2, hash3) -} - -func TestSerialize(t *testing.T) { - var t0 uint64 = 0 - var t1 uint64 = 1 - config := UpgradeConfig{ - PrecompileUpgrades: []PrecompileUpgrade{ - { - Config: nativeminter.NewConfig(&t0, nil, nil, nil, nil), // enable at genesis - }, - { - Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 - }, - }, - } - assertConversions(t, &config) -} - -func TestWithAddress(t *testing.T) { - var t0 uint64 = 1 - var t1 uint64 = 11 - config := UpgradeConfig{ - PrecompileUpgrades: []PrecompileUpgrade{ - { - Config: nativeminter.NewConfig(&t0, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), - }, nil), // enable at genesis - }, - { - Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 - }, - }, - } - assertConversions(t, &config) -} - -func TestWithAddressAndMint(t *testing.T) { - var t0 uint64 = 2 - var t1 uint64 = 1001 - config := UpgradeConfig{ - PrecompileUpgrades: []PrecompileUpgrade{ - { - Config: nativeminter.NewConfig(&t0, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), - }, map[common.Address]*math.HexOrDecimal256{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000010")): math.NewHexOrDecimal256(64), - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000090")): math.NewHexOrDecimal256(6402100201021), - }), // enable at genesis - }, - { - Config: nativeminter.NewDisableConfig(&t1), // disable at timestamp 1 - }, - }, - } - assertConversions(t, &config) -} - -func TestWithAddressFeeMinter(t *testing.T) { - var t0 uint64 = 2 - var t1 uint64 = 1001 - var validFeeConfig = commontype.FeeConfig{ - GasLimit: big.NewInt(8_000_000), - TargetBlockRate: 2, // in seconds - - MinBaseFee: big.NewInt(25_000_000_000), - TargetGas: big.NewInt(15_000_000), - BaseFeeChangeDenominator: big.NewInt(36), - - MinBlockGasCost: big.NewInt(0), - MaxBlockGasCost: big.NewInt(1_000_000), - BlockGasCostStep: big.NewInt(200_000), - } - - config := UpgradeConfig{ - PrecompileUpgrades: []PrecompileUpgrade{ - { - Config: feemanager.NewConfig(&t0, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), - }, &validFeeConfig), // enable at genesis - }, - { - Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 - }, - }, - } - assertConversions(t, &config) -} - -func TestWithDepoyerAllowList(t *testing.T) { - var t0 uint64 = 2 - var t1 uint64 = 1001 - - config := UpgradeConfig{ - PrecompileUpgrades: []PrecompileUpgrade{ - { - Config: deployerallowlist.NewConfig(&t0, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), - }), // enable at genesis - }, - { - Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 - }, - }, - } - assertConversions(t, &config) -} - -func TestWithRewardManager(t *testing.T) { - var t0 uint64 = 2 - var t1 uint64 = 1001 - - config := UpgradeConfig{ - PrecompileUpgrades: []PrecompileUpgrade{ - { - Config: rewardmanager.NewConfig(&t0, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), - }, nil), // enable at genesis - }, - { - Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 - }, - }, - } - assertConversions(t, &config) -} - -func TestWithRewardManagerWithNil(t *testing.T) { - var t0 uint64 = 2 - var t1 uint64 = 1001 - - config := UpgradeConfig{ - PrecompileUpgrades: []PrecompileUpgrade{ - { - Config: rewardmanager.NewConfig(&t0, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), - }, []common.Address{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), - }, &rewardmanager.InitialRewardConfig{ - AllowFeeRecipients: true, - }), - }, - { - Config: feemanager.NewDisableConfig(&t1), // disable at timestamp 1 - }, - }, - } - assertConversions(t, &config) -} - -func TestStateUpgrades(t *testing.T) { - var t0 uint64 = 2 - var t1 uint64 = 1001 - config := UpgradeConfig{ - StateUpgrades: []StateUpgrade{ - { - BlockTimestamp: &t0, - StateUpgradeAccounts: map[common.Address]StateUpgradeAccount{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")): StateUpgradeAccount{ - Code: []byte{1, 2, 3, 4, 5, 6}, - BalanceChange: math.NewHexOrDecimal256(99), - Storage: map[common.Hash]common.Hash{ - common.BytesToHash([]byte{1, 2, 4, 5}): common.BytesToHash([]byte{1, 2, 3}), - }, - }, - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001000")): StateUpgradeAccount{ - Code: []byte{1, 2, 9, 93, 4, 5, 6}, - BalanceChange: math.NewHexOrDecimal256(92312319), - Storage: map[common.Hash]common.Hash{ - common.BytesToHash([]byte{11, 21, 99, 5}): common.BytesToHash([]byte{1, 2, 3}), - common.BytesToHash([]byte{1, 21, 99, 5}): common.BytesToHash([]byte{1, 2, 3}), - common.BytesToHash([]byte{1, 2, 99, 5}): common.BytesToHash([]byte{1, 2, 3}), - common.BytesToHash([]byte{1, 2, 4, 5}): common.BytesToHash([]byte{1, 2, 3}), - }, - }, - }, - }, - { - BlockTimestamp: &t1, - StateUpgradeAccounts: map[common.Address]StateUpgradeAccount{ - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001000")): StateUpgradeAccount{}, - common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")): StateUpgradeAccount{}, - }, - }, - }, - } - assertConversions(t, &config) -} diff --git a/params/state_upgrade_test.go b/params/state_upgrade_test.go index 6ee4094fc0..a3c2264535 100644 --- a/params/state_upgrade_test.go +++ b/params/state_upgrade_test.go @@ -185,3 +185,42 @@ func TestUnmarshalStateUpgradeJSON(t *testing.T) { require.NoError(t, err) require.Equal(t, upgradeConfig, unmarshaledConfig) } + +func TestSerialize(t *testing.T) { + var t0 uint64 = 2 + var t1 uint64 = 1001 + config := UpgradeConfig{ + StateUpgrades: []StateUpgrade{ + { + BlockTimestamp: &t0, + StateUpgradeAccounts: map[common.Address]StateUpgradeAccount{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")): StateUpgradeAccount{ + Code: []byte{1, 2, 3, 4, 5, 6}, + BalanceChange: math.NewHexOrDecimal256(99), + Storage: map[common.Hash]common.Hash{ + common.BytesToHash([]byte{1, 2, 4, 5}): common.BytesToHash([]byte{1, 2, 3}), + }, + }, + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001000")): StateUpgradeAccount{ + Code: []byte{1, 2, 9, 93, 4, 5, 6}, + BalanceChange: math.NewHexOrDecimal256(92312319), + Storage: map[common.Hash]common.Hash{ + common.BytesToHash([]byte{11, 21, 99, 5}): common.BytesToHash([]byte{1, 2, 3}), + common.BytesToHash([]byte{1, 21, 99, 5}): common.BytesToHash([]byte{1, 2, 3}), + common.BytesToHash([]byte{1, 2, 99, 5}): common.BytesToHash([]byte{1, 2, 3}), + common.BytesToHash([]byte{1, 2, 4, 5}): common.BytesToHash([]byte{1, 2, 3}), + }, + }, + }, + }, + { + BlockTimestamp: &t1, + StateUpgradeAccounts: map[common.Address]StateUpgradeAccount{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000001000")): StateUpgradeAccount{}, + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")): StateUpgradeAccount{}, + }, + }, + }, + } + AssertConfigHashesAndSerialization(t, &config) +} diff --git a/precompile/contracts/feemanager/config_test.go b/precompile/contracts/feemanager/config_test.go index 4182ec4716..4f187eba80 100644 --- a/precompile/contracts/feemanager/config_test.go +++ b/precompile/contracts/feemanager/config_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/ava-labs/subnet-evm/commontype" + "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/precompile/testutils" @@ -88,3 +89,39 @@ func TestEqual(t *testing.T) { } allowlist.EqualPrecompileWithAllowListTests(t, Module, tests) } + +func TestSerialize(t *testing.T) { + var t0 uint64 = 2 + var t1 uint64 = 1001 + var validFeeConfig = commontype.FeeConfig{ + GasLimit: big.NewInt(8_000_000), + TargetBlockRate: 2, // in seconds + + MinBaseFee: big.NewInt(25_000_000_000), + TargetGas: big.NewInt(15_000_000), + BaseFeeChangeDenominator: big.NewInt(36), + + MinBlockGasCost: big.NewInt(0), + MaxBlockGasCost: big.NewInt(1_000_000), + BlockGasCostStep: big.NewInt(200_000), + } + + config := params.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: NewConfig(&t0, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }, &validFeeConfig), // enable at genesis + }, + { + Config: NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + } + params.AssertConfigHashesAndSerialization(t, &config) +} diff --git a/precompile/contracts/nativeminter/config_test.go b/precompile/contracts/nativeminter/config_test.go index c0f9958e36..d8b5d461ba 100644 --- a/precompile/contracts/nativeminter/config_test.go +++ b/precompile/contracts/nativeminter/config_test.go @@ -6,6 +6,7 @@ package nativeminter import ( "testing" + "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/precompile/testutils" @@ -52,6 +53,70 @@ func TestVerify(t *testing.T) { allowlist.VerifyPrecompileWithAllowListTests(t, Module, tests) } +func TestSerialize(t *testing.T) { + var t0 uint64 = 0 + var t1 uint64 = 1 + config := params.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: NewConfig(&t0, nil, nil, nil, nil), // enable at genesis + }, + { + Config: NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + } + params.AssertConfigHashesAndSerialization(t, &config) +} +func TestSerializeWithAddresses(t *testing.T) { + var t0 uint64 = 1 + var t1 uint64 = 11 + config := params.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: NewConfig(&t0, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }, nil), // enable at genesis + }, + { + Config: NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + } + params.AssertConfigHashesAndSerialization(t, &config) +} + +func TestSerializeWithAddressAndMint(t *testing.T) { + var t0 uint64 = 2 + var t1 uint64 = 1001 + config := params.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: NewConfig(&t0, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }, map[common.Address]*math.HexOrDecimal256{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000010")): math.NewHexOrDecimal256(64), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000090")): math.NewHexOrDecimal256(6402100201021), + }), // enable at genesis + }, + { + Config: NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + } + params.AssertConfigHashesAndSerialization(t, &config) +} + func TestEqual(t *testing.T) { admins := []common.Address{allowlist.TestAdminAddr} enableds := []common.Address{allowlist.TestEnabledAddr} diff --git a/precompile/contracts/rewardmanager/config_test.go b/precompile/contracts/rewardmanager/config_test.go index 958eb000d9..a2b9768565 100644 --- a/precompile/contracts/rewardmanager/config_test.go +++ b/precompile/contracts/rewardmanager/config_test.go @@ -6,6 +6,7 @@ package rewardmanager import ( "testing" + "github.com/ava-labs/subnet-evm/params" "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/precompile/testutils" @@ -79,3 +80,53 @@ func TestEqual(t *testing.T) { } allowlist.EqualPrecompileWithAllowListTests(t, Module, tests) } + +func TestSerialize(t *testing.T) { + var t0 uint64 = 2 + var t1 uint64 = 1001 + + config := params.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: NewConfig(&t0, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }, nil), // enable at genesis + }, + { + Config: NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + } + params.AssertConfigHashesAndSerialization(t, &config) +} + +func TestSerializeWithNil(t *testing.T) { + var t0 uint64 = 2 + var t1 uint64 = 1001 + + config := params.UpgradeConfig{ + PrecompileUpgrades: []params.PrecompileUpgrade{ + { + Config: NewConfig(&t0, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000020")), + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000030")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")), + }, []common.Address{ + common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), + }, &InitialRewardConfig{ + AllowFeeRecipients: true, + }), + }, + { + Config: NewDisableConfig(&t1), // disable at timestamp 1 + }, + }, + } + params.AssertConfigHashesAndSerialization(t, &config) +} From 6785dd9c9a6a49017f736a798b23420460763a9e Mon Sep 17 00:00:00 2001 From: Cesar Date: Fri, 15 Dec 2023 18:02:45 -0300 Subject: [PATCH 28/48] Remove all custom serializers Use MarshalBinary and UnmarshalBinary --- commontype/fee_config.go | 21 +++++-- precompile/allowlist/config.go | 32 ++++++---- .../contracts/deployerallowlist/config.go | 30 ++++++++-- precompile/contracts/feemanager/config.go | 39 ++++++++++--- precompile/contracts/nativeminter/config.go | 25 ++++++-- precompile/contracts/rewardmanager/config.go | 58 ++++++++++++++----- precompile/contracts/txallowlist/config.go | 26 +++++++-- precompile/precompileconfig/upgradeable.go | 18 ++++-- x/warp/config.go | 13 ++++- 9 files changed, 203 insertions(+), 59 deletions(-) diff --git a/commontype/fee_config.go b/commontype/fee_config.go index aca3a5cd40..cf1867d385 100644 --- a/commontype/fee_config.go +++ b/commontype/fee_config.go @@ -9,6 +9,7 @@ import ( "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/utils" + "github.com/docker/docker/pkg/units" "github.com/ethereum/go-ethereum/common" ) @@ -152,28 +153,36 @@ func (c *FeeConfig) getBigIntToSerialize() []**big.Int { } } -func (c *FeeConfig) ToBytesWithPacker(p *wrappers.Packer) error { +func (c *FeeConfig) MarshalBinary() ([]byte, error) { + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: 1 * units.MiB, + } + for _, bigint := range c.getBigIntToSerialize() { p.PackBool(*bigint == nil) if p.Err != nil { - return p.Err + return nil, p.Err } if bigint != nil { p.PackBytes((*bigint).Bytes()) if p.Err != nil { - return p.Err + return nil, p.Err } } } p.PackLong(c.TargetBlockRate) if p.Err != nil { - return p.Err + return nil, p.Err } - return nil + return p.Bytes, nil } -func (c *FeeConfig) FromBytesWithPacker(p *wrappers.Packer) error { +func (c *FeeConfig) UnmarshalBinary(data []byte) error { + p := wrappers.Packer{ + Bytes: data, + } for _, bigint := range c.getBigIntToSerialize() { isNil := p.UnpackBool() if p.Err != nil { diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index 6487b9f47d..044e8650ba 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -9,6 +9,7 @@ import ( "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/docker/docker/pkg/units" "github.com/ethereum/go-ethereum/common" ) @@ -145,29 +146,36 @@ func (c *AllowListConfig) Verify(chainConfig precompileconfig.ChainConfig, upgra return nil } -func (c *AllowListConfig) ToBytesWithPacker(p *wrappers.Packer) error { - if err := c.packAddresses(c.AdminAddresses, p); err != nil { - return err +func (c *AllowListConfig) MarshalBinary() ([]byte, error) { + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: 1 * units.MiB, } - if err := c.packAddresses(c.ManagerAddresses, p); err != nil { - return err + if err := c.packAddresses(c.AdminAddresses, &p); err != nil { + return nil, err } - if err := c.packAddresses(c.EnabledAddresses, p); err != nil { - return err + if err := c.packAddresses(c.ManagerAddresses, &p); err != nil { + return nil, err } - return nil + if err := c.packAddresses(c.EnabledAddresses, &p); err != nil { + return nil, err + } + return p.Bytes, nil } -func (c *AllowListConfig) FromBytesWithPacker(p *wrappers.Packer) error { - admins, err := c.unpackAddresses(p) +func (c *AllowListConfig) UnmarshalBinary(data []byte) error { + p := wrappers.Packer{ + Bytes: data, + } + admins, err := c.unpackAddresses(&p) if err != nil { return err } - managers, err := c.unpackAddresses(p) + managers, err := c.unpackAddresses(&p) if err != nil { return err } - enableds, err := c.unpackAddresses(p) + enableds, err := c.unpackAddresses(&p) if err != nil { return err } diff --git a/precompile/contracts/deployerallowlist/config.go b/precompile/contracts/deployerallowlist/config.go index 061d99ace5..288cc16de9 100644 --- a/precompile/contracts/deployerallowlist/config.go +++ b/precompile/contracts/deployerallowlist/config.go @@ -66,14 +66,26 @@ func (c *Config) MarshalBinary() ([]byte, error) { MaxSize: 1 * units.MiB, } - if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { + bytes, err := c.AllowListConfig.MarshalBinary() + if err != nil { return nil, err } - if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + p.PackBytes(bytes) + if p.Err != nil { + return nil, p.Err + } + + bytes, err = c.Upgrade.MarshalBinary() + if err != nil { return nil, err } + p.PackBytes(bytes) + if p.Err != nil { + return nil, p.Err + } + return p.Bytes, nil } @@ -81,10 +93,20 @@ func (c *Config) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } - if err := c.AllowListConfig.FromBytesWithPacker(&p); err != nil { + + allowList := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + upgrade := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + + if err := c.AllowListConfig.UnmarshalBinary(allowList); err != nil { return err } - if err := c.Upgrade.FromBytesWithPacker(&p); err != nil { + if err := c.Upgrade.UnmarshalBinary(upgrade); err != nil { return err } return nil diff --git a/precompile/contracts/feemanager/config.go b/precompile/contracts/feemanager/config.go index f047f693fe..feca7cf377 100644 --- a/precompile/contracts/feemanager/config.go +++ b/precompile/contracts/feemanager/config.go @@ -86,14 +86,25 @@ func (c *Config) MarshalBinary() ([]byte, error) { MaxSize: 1 * units.MiB, } - if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { + allowList, err := c.AllowListConfig.MarshalBinary() + if err != nil { return nil, err } - if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + upgrade, err := c.Upgrade.MarshalBinary() + if err != nil { return nil, err } + p.PackBytes(allowList) + if p.Err != nil { + return nil, p.Err + } + p.PackBytes(upgrade) + if p.Err != nil { + return nil, p.Err + } + if c.InitialFeeConfig == nil { p.PackBool(true) if p.Err != nil { @@ -104,28 +115,42 @@ func (c *Config) MarshalBinary() ([]byte, error) { if p.Err != nil { return nil, p.Err } - if err := c.InitialFeeConfig.ToBytesWithPacker(&p); err != nil { + bytes, err := c.InitialFeeConfig.MarshalBinary() + if err != nil { return nil, err } + p.PackBytes(bytes) } - return p.Bytes, nil + return p.Bytes, p.Err } func (c *Config) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } - if err := c.AllowListConfig.FromBytesWithPacker(&p); err != nil { + allowList := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + upgrade := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + if err := c.AllowListConfig.UnmarshalBinary(allowList); err != nil { return err } - if err := c.Upgrade.FromBytesWithPacker(&p); err != nil { + if err := c.Upgrade.UnmarshalBinary(upgrade); err != nil { return err } isNil := p.UnpackBool() if !isNil { c.InitialFeeConfig = &commontype.FeeConfig{} - if err := c.InitialFeeConfig.FromBytesWithPacker(&p); err != nil { + bytes := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + if err := c.InitialFeeConfig.UnmarshalBinary(bytes); err != nil { return err } } diff --git a/precompile/contracts/nativeminter/config.go b/precompile/contracts/nativeminter/config.go index 99703a8469..8dc92435c7 100644 --- a/precompile/contracts/nativeminter/config.go +++ b/precompile/contracts/nativeminter/config.go @@ -115,14 +115,23 @@ func (c *Config) MarshalBinary() ([]byte, error) { MaxSize: 1 * units.MiB, } - if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { + bytes, err := c.AllowListConfig.MarshalBinary() + if err != nil { return nil, err } - if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + p.PackBytes(bytes) + if p.Err != nil { + return nil, p.Err + } + + bytes, err = c.Upgrade.MarshalBinary() + if err != nil { return nil, err } + p.PackBytes(bytes) + p.PackInt(uint32(len(keys))) if p.Err != nil { return nil, p.Err @@ -146,10 +155,18 @@ func (c *Config) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } - if err := c.AllowListConfig.FromBytesWithPacker(&p); err != nil { + allowList := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + upgrade := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + if err := c.AllowListConfig.UnmarshalBinary(allowList); err != nil { return err } - if err := c.Upgrade.FromBytesWithPacker(&p); err != nil { + if err := c.Upgrade.UnmarshalBinary(upgrade); err != nil { return err } len := p.UnpackInt() diff --git a/precompile/contracts/rewardmanager/config.go b/precompile/contracts/rewardmanager/config.go index 0d3a6bf914..d10897cc3a 100644 --- a/precompile/contracts/rewardmanager/config.go +++ b/precompile/contracts/rewardmanager/config.go @@ -22,16 +22,23 @@ type InitialRewardConfig struct { RewardAddress common.Address `json:"rewardAddress,omitempty"` } -func (u *InitialRewardConfig) ToBytesWithPacker(p *wrappers.Packer) error { +func (u *InitialRewardConfig) MarshalBinary() ([]byte, error) { + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: 1 * units.MiB, + } p.PackBool(u.AllowFeeRecipients) if p.Err != nil { - return p.Err + return nil, p.Err } p.PackBytes(u.RewardAddress[:]) - return p.Err + return p.Bytes, p.Err } -func (u *InitialRewardConfig) FromBytesWithPacker(p *wrappers.Packer) error { +func (u *InitialRewardConfig) UnmarshalBinary(data []byte) error { + p := wrappers.Packer{ + Bytes: data, + } u.AllowFeeRecipients = p.UnpackBool() if p.Err != nil { return p.Err @@ -145,13 +152,24 @@ func (c *Config) MarshalBinary() ([]byte, error) { MaxSize: 1 * units.MiB, } - if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { + bytes, err := c.AllowListConfig.MarshalBinary() + if err != nil { return nil, err } - if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + p.PackBytes(bytes) + if p.Err != nil { + return nil, p.Err + } + + bytes, err = c.Upgrade.MarshalBinary() + if err != nil { return nil, err } + p.PackBytes(bytes) + if p.Err != nil { + return nil, p.Err + } p.PackBool(c.InitialRewardConfig == nil) if p.Err != nil { @@ -159,32 +177,44 @@ func (c *Config) MarshalBinary() ([]byte, error) { } if c.InitialRewardConfig != nil { - if err := c.InitialRewardConfig.ToBytesWithPacker(&p); err != nil { + bytes, err := c.InitialRewardConfig.MarshalBinary() + if err != nil { return nil, err } + p.PackBytes(bytes) } - return p.Bytes, nil + return p.Bytes, p.Err } func (c *Config) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } - if err := c.AllowListConfig.FromBytesWithPacker(&p); err != nil { + allowList := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + upgrade := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + if err := c.AllowListConfig.UnmarshalBinary(allowList); err != nil { return err } - if err := c.Upgrade.FromBytesWithPacker(&p); err != nil { + if err := c.Upgrade.UnmarshalBinary(upgrade); err != nil { return err } isNil := p.UnpackBool() - if !isNil { + if p.Err == nil && !isNil { c.InitialRewardConfig = &InitialRewardConfig{} - if err := c.InitialRewardConfig.FromBytesWithPacker(&p); err != nil { - return err + bytes := p.UnpackBytes() + if p.Err != nil { + return p.Err } + return c.InitialRewardConfig.UnmarshalBinary(bytes) } - return nil + return p.Err } diff --git a/precompile/contracts/txallowlist/config.go b/precompile/contracts/txallowlist/config.go index 859d61db34..89acb47af7 100644 --- a/precompile/contracts/txallowlist/config.go +++ b/precompile/contracts/txallowlist/config.go @@ -66,14 +66,23 @@ func (c *Config) MarshalBinary() ([]byte, error) { MaxSize: 1 * units.MiB, } - if err := c.AllowListConfig.ToBytesWithPacker(&p); err != nil { + bytes, err := c.AllowListConfig.MarshalBinary() + if err != nil { return nil, err } - if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + p.PackBytes(bytes) + if p.Err != nil { + return nil, p.Err + } + + bytes, err = c.Upgrade.MarshalBinary() + if err != nil { return nil, err } + p.PackBytes(bytes) + return p.Bytes, nil } @@ -82,9 +91,16 @@ func (c *Config) UnmarshalBinary(bytes []byte) error { Bytes: bytes, } - if err := c.AllowListConfig.FromBytesWithPacker(&p); err != nil { + allowList := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + upgrade := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + if err := c.AllowListConfig.UnmarshalBinary(allowList); err != nil { return err } - - return c.Upgrade.FromBytesWithPacker(&p) + return c.Upgrade.UnmarshalBinary(upgrade) } diff --git a/precompile/precompileconfig/upgradeable.go b/precompile/precompileconfig/upgradeable.go index 8ae28860cd..a2e005592d 100644 --- a/precompile/precompileconfig/upgradeable.go +++ b/precompile/precompileconfig/upgradeable.go @@ -6,6 +6,7 @@ package precompileconfig import ( "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/utils" + "github.com/docker/docker/pkg/units" ) // Upgrade contains the timestamp for the upgrade along with @@ -35,24 +36,31 @@ func (u *Upgrade) Equal(other *Upgrade) bool { return u.Disable == other.Disable && utils.Uint64PtrEqual(u.BlockTimestamp, other.BlockTimestamp) } -func (u *Upgrade) ToBytesWithPacker(p *wrappers.Packer) error { +func (u *Upgrade) MarshalBinary() ([]byte, error) { + p := wrappers.Packer{ + Bytes: []byte{}, + MaxSize: 1 * units.MiB, + } if u.BlockTimestamp == nil { p.PackBool(true) } else { p.PackBool(false) if p.Err != nil { - return p.Err + return nil, p.Err } p.PackLong(*u.BlockTimestamp) } if p.Err != nil { - return p.Err + return nil, p.Err } p.PackBool(u.Disable) - return p.Err + return p.Bytes, p.Err } -func (u *Upgrade) FromBytesWithPacker(p *wrappers.Packer) error { +func (u *Upgrade) UnmarshalBinary(data []byte) error { + p := wrappers.Packer{ + Bytes: data, + } isNil := p.UnpackBool() if !isNil { timestamp := p.UnpackLong() diff --git a/x/warp/config.go b/x/warp/config.go index 53731132e3..4e92c1e64c 100644 --- a/x/warp/config.go +++ b/x/warp/config.go @@ -219,9 +219,14 @@ func (c *Config) MarshalBinary() ([]byte, error) { MaxSize: 1 * units.MiB, } - if err := c.Upgrade.ToBytesWithPacker(&p); err != nil { + bytes, err := c.Upgrade.MarshalBinary() + if err != nil { return nil, err } + p.PackBytes(bytes) + if p.Err != nil { + return nil, p.Err + } p.PackLong(c.QuorumNumerator) if p.Err != nil { @@ -235,7 +240,11 @@ func (c *Config) UnmarshalBinary(bytes []byte) error { p := wrappers.Packer{ Bytes: bytes, } - if err := c.Upgrade.FromBytesWithPacker(&p); err != nil { + upgrade := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + if err := c.Upgrade.UnmarshalBinary(upgrade); err != nil { return err } From 32486fe0171ac3a913f25bebb67d318a9874d810 Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 28 Dec 2023 17:24:17 -0300 Subject: [PATCH 29/48] WIP --- .../precompile_config_template.go | 21 ++++++++++++++++++- .../precompile_config_test_template.go | 2 +- params/config.go | 5 +++++ precompile/allowlist/config.go | 1 - 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index a510c1cf9e..066d17c1fd 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -55,7 +55,26 @@ func NewConfig(blockTimestamp *uint64{{if .Contract.AllowList}}, admins []common } func (c * Config) MarshalBinary() ([]byte, error) { - return nil, errors.New("implement MarshalBinary() method") + p := wrappers.Packer { + Bytes: []byte{}, + MaxSize: 1 * units.MiB + } + {{- if .Contract.AllowList}} + allowBytes, err := c.AllowListConfig.MarshalBinary() + if err != nil { + return nil, err + } + p.PackBytes(allowBytes) + if p.Err != nil { + return ni, p.Err + } + {{- end}} + upgradeBytes, err := c.Upgrade.MarshalBinary() + if err != nil { + return nil, err + } + p.PackBytes(upgradeBytes) + return p.Bytes, p.Err } func (c * Config) UnmarshalBinary(bytes []byte) error { diff --git a/accounts/abi/bind/precompilebind/precompile_config_test_template.go b/accounts/abi/bind/precompilebind/precompile_config_test_template.go index 08ab6ff13c..89209c64e0 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_test_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_test_template.go @@ -89,7 +89,7 @@ func TestSerialize(t *testing.T) { }, } require.NotNil(t, config) - //params.AssertConfigHashesAndSerialization(t, &config) + params.AssertConfigHashesAndSerialization(t, &config) } // TestEqual tests the equality of Config with other precompile configs. diff --git a/params/config.go b/params/config.go index 6765cd1fd0..67f28af937 100644 --- a/params/config.go +++ b/params/config.go @@ -261,6 +261,11 @@ func (c *UpgradeConfig) MarshalBinary() ([]byte, error) { } func (c *UpgradeConfig) UnmarshalBinary(data []byte) error { + // Add protection and reject any slice of bytes which is bigger than the maxSize. + if byteLen := len(data); byteLen > m.maxSize { + return 0, fmt.Errorf("%w: %d > %d", ErrUnmarshalTooBig, byteLen, m.maxSize) + } + p := wrappers.Packer{ Bytes: data, } diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index 044e8650ba..843377e54b 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -44,7 +44,6 @@ func (c *AllowListConfig) packAddresses(addresses []common.Address, p *wrappers. if p.Err != nil { return p.Err } - for _, address := range addresses { p.PackFixedBytes(address[:]) if p.Err != nil { From 2de90955940a692448c1b3fca111b0a93b3db238 Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 00:12:35 -0300 Subject: [PATCH 30/48] Do not use double pointers --- commontype/fee_config.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/commontype/fee_config.go b/commontype/fee_config.go index cf1867d385..a1f8dc2b3a 100644 --- a/commontype/fee_config.go +++ b/commontype/fee_config.go @@ -146,10 +146,10 @@ func (f *FeeConfig) checkByteLens() error { return nil } -func (c *FeeConfig) getBigIntToSerialize() []**big.Int { - return []**big.Int{ - &c.GasLimit, &c.MinBaseFee, &c.TargetGas, &c.BaseFeeChangeDenominator, - &c.MinBlockGasCost, &c.MaxBlockGasCost, &c.BlockGasCostStep, +func (c *FeeConfig) getBigIntToSerialize() []*big.Int { + return []*big.Int{ + c.GasLimit, c.MinBaseFee, c.TargetGas, c.BaseFeeChangeDenominator, + c.MinBlockGasCost, c.MaxBlockGasCost, c.BlockGasCostStep, } } @@ -160,7 +160,7 @@ func (c *FeeConfig) MarshalBinary() ([]byte, error) { } for _, bigint := range c.getBigIntToSerialize() { - p.PackBool(*bigint == nil) + p.PackBool(bigint == nil) if p.Err != nil { return nil, p.Err } @@ -191,7 +191,7 @@ func (c *FeeConfig) UnmarshalBinary(data []byte) error { if isNil { continue } - *bigint = big.NewInt(0).SetBytes(p.UnpackBytes()) + *bigint = *big.NewInt(0).SetBytes(p.UnpackBytes()) if p.Err != nil { return p.Err } From 3a1bd287ce77cfe734ae20ed9962e14be24a22e9 Mon Sep 17 00:00:00 2001 From: Cesar <137245636+nytzuga@users.noreply.github.com> Date: Thu, 4 Jan 2024 00:54:16 -0300 Subject: [PATCH 31/48] Apply suggestions from code review Co-authored-by: Ceyhun Onur Signed-off-by: Cesar <137245636+nytzuga@users.noreply.github.com> --- .../abi/bind/precompilebind/precompile_config_template.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index 066d17c1fd..875900555b 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -28,12 +28,8 @@ var _ precompileconfig.Config = &Config{} // adds specific configuration for {{.Contract.Type}}. type Config struct { {{- if .Contract.AllowList}} - // Serialize allowList to let nodes exchange information about their - // precompile configs allowlist.AllowListConfig {{- end}} - // Serialize the Upgrade config to let nodes exchange information about - // their precompile configs precompileconfig.Upgrade // CUSTOM CODE STARTS HERE // Add your own custom fields for Config here From b2020cbefb24815bc02f1da88e310cd1272500ab Mon Sep 17 00:00:00 2001 From: Cesar <137245636+nytzuga@users.noreply.github.com> Date: Thu, 4 Jan 2024 00:57:46 -0300 Subject: [PATCH 32/48] Update precompile/allowlist/config.go Co-authored-by: aaronbuchwald Signed-off-by: Cesar <137245636+nytzuga@users.noreply.github.com> --- precompile/allowlist/config.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index 843377e54b..928a9772ce 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -163,18 +163,18 @@ func (c *AllowListConfig) MarshalBinary() ([]byte, error) { } func (c *AllowListConfig) UnmarshalBinary(data []byte) error { - p := wrappers.Packer{ + p := &wrappers.Packer{ Bytes: data, } - admins, err := c.unpackAddresses(&p) + admins, err := c.unpackAddresses(p) if err != nil { return err } - managers, err := c.unpackAddresses(&p) + managers, err := c.unpackAddresses(p) if err != nil { return err } - enableds, err := c.unpackAddresses(&p) + enableds, err := c.unpackAddresses(p) if err != nil { return err } From beb7ab8ae81f1fd911ef3085897cbe6d985d7474 Mon Sep 17 00:00:00 2001 From: Cesar <137245636+nytzuga@users.noreply.github.com> Date: Thu, 4 Jan 2024 01:11:52 -0300 Subject: [PATCH 33/48] Update precompile/allowlist/config.go Co-authored-by: aaronbuchwald Signed-off-by: Cesar <137245636+nytzuga@users.noreply.github.com> --- precompile/allowlist/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index 928a9772ce..68450b821b 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -59,10 +59,10 @@ func (c *AllowListConfig) unpackAddresses(p *wrappers.Packer) ([]common.Address, return nil, p.Err } - addresses := make([]common.Address, length) + addresses := make([]common.Address, 0, length) for i := uint32(0); i < length; i++ { bytes := p.UnpackFixedBytes(common.AddressLength) - addresses = append(addresses[:i], common.BytesToAddress(bytes)) + addresses = append(addresses, common.BytesToAddress(bytes)) if p.Err != nil { return nil, p.Err } From 8192cb2eb60918fb9be4db349808457406e160be Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 01:12:13 -0300 Subject: [PATCH 34/48] Bring back getBigIntToSerialize() until a better solution can be found --- commontype/fee_config.go | 12 ++++++------ params/config.go | 13 ------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/commontype/fee_config.go b/commontype/fee_config.go index a1f8dc2b3a..cf1867d385 100644 --- a/commontype/fee_config.go +++ b/commontype/fee_config.go @@ -146,10 +146,10 @@ func (f *FeeConfig) checkByteLens() error { return nil } -func (c *FeeConfig) getBigIntToSerialize() []*big.Int { - return []*big.Int{ - c.GasLimit, c.MinBaseFee, c.TargetGas, c.BaseFeeChangeDenominator, - c.MinBlockGasCost, c.MaxBlockGasCost, c.BlockGasCostStep, +func (c *FeeConfig) getBigIntToSerialize() []**big.Int { + return []**big.Int{ + &c.GasLimit, &c.MinBaseFee, &c.TargetGas, &c.BaseFeeChangeDenominator, + &c.MinBlockGasCost, &c.MaxBlockGasCost, &c.BlockGasCostStep, } } @@ -160,7 +160,7 @@ func (c *FeeConfig) MarshalBinary() ([]byte, error) { } for _, bigint := range c.getBigIntToSerialize() { - p.PackBool(bigint == nil) + p.PackBool(*bigint == nil) if p.Err != nil { return nil, p.Err } @@ -191,7 +191,7 @@ func (c *FeeConfig) UnmarshalBinary(data []byte) error { if isNil { continue } - *bigint = *big.NewInt(0).SetBytes(p.UnpackBytes()) + *bigint = big.NewInt(0).SetBytes(p.UnpackBytes()) if p.Err != nil { return p.Err } diff --git a/params/config.go b/params/config.go index 4490d4c21b..d1746bc35f 100644 --- a/params/config.go +++ b/params/config.go @@ -75,12 +75,10 @@ var ( } // For UpgradeConfig Marshal/Unmarshal - magicHeader = []byte{0xff} sectionHeaderSizes = 1 precompileHeader = []byte{0xaa} stateUpdateHeader = []byte{0xc8} endHeader = []byte{0} - ErrIncorrectHeader = errors.New("invalid magic header") ErrMalformedConfigHeader = errors.New("malformed config header") ErrUnknowPrecompile = errors.New("unknown precompile config") MaxMessageSize = 1 * units.MiB @@ -201,10 +199,6 @@ func (c *UpgradeConfig) MarshalBinary() ([]byte, error) { Bytes: []byte{}, MaxSize: MaxMessageSize, } - p.PackFixedBytes(magicHeader) - if p.Err != nil { - return nil, p.Err - } p.PackBool(c.OptionalNetworkUpgrades == nil) if p.Err != nil { @@ -264,13 +258,6 @@ func (c *UpgradeConfig) UnmarshalBinary(data []byte) error { p := wrappers.Packer{ Bytes: data, } - if !bytes.Equal(p.UnpackFixedBytes(sectionHeaderSizes), magicHeader) { - return ErrIncorrectHeader - } - if p.Err != nil { - return p.Err - } - isNil := p.UnpackBool() if !isNil { c.OptionalNetworkUpgrades = &OptionalNetworkUpgrades{} From 8935259f2fb457440c72d75e9f5a9539172522aa Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 01:21:02 -0300 Subject: [PATCH 35/48] Remove all magic bytes Instead loop them together --- params/config.go | 88 +++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 50 deletions(-) diff --git a/params/config.go b/params/config.go index d1746bc35f..4f1263a990 100644 --- a/params/config.go +++ b/params/config.go @@ -27,7 +27,6 @@ package params import ( - "bytes" "encoding/json" "errors" "fmt" @@ -75,13 +74,8 @@ var ( } // For UpgradeConfig Marshal/Unmarshal - sectionHeaderSizes = 1 - precompileHeader = []byte{0xaa} - stateUpdateHeader = []byte{0xc8} - endHeader = []byte{0} - ErrMalformedConfigHeader = errors.New("malformed config header") - ErrUnknowPrecompile = errors.New("unknown precompile config") - MaxMessageSize = 1 * units.MiB + ErrUnknowPrecompile = errors.New("unknown precompile config") + MaxMessageSize = 1 * units.MiB ) var ( @@ -215,15 +209,12 @@ func (c *UpgradeConfig) MarshalBinary() ([]byte, error) { } } + p.PackInt(uint32(len(c.PrecompileUpgrades))) for _, precompileConfig := range c.PrecompileUpgrades { bytes, err := precompileConfig.Config.MarshalBinary() if err != nil { return nil, err } - p.PackFixedBytes(precompileHeader) - if p.Err != nil { - return nil, p.Err - } p.PackStr(precompileConfig.Key()) if p.Err != nil { return nil, p.Err @@ -234,23 +225,18 @@ func (c *UpgradeConfig) MarshalBinary() ([]byte, error) { } } + p.PackInt(uint32(len(c.StateUpgrades))) for _, config := range c.StateUpgrades { bytes, err := config.MarshalBinary() if err != nil { return nil, err } - p.PackFixedBytes(stateUpdateHeader) - if p.Err != nil { - return nil, p.Err - } p.PackBytes(bytes) if p.Err != nil { return nil, p.Err } } - p.PackFixedBytes(endHeader) - return p.Bytes, nil } @@ -270,42 +256,44 @@ func (c *UpgradeConfig) UnmarshalBinary(data []byte) error { } } - for { - header := p.UnpackFixedBytes(sectionHeaderSizes) + len := p.UnpackInt() + if p.Err != nil { + return p.Err + } + + for i := uint32(0); i < len; i++ { + key := p.UnpackStr() if p.Err != nil { return p.Err } - if bytes.Equal(header, precompileHeader) { - key := p.UnpackStr() - if p.Err != nil { - return p.Err - } - config := p.UnpackBytes() - if p.Err != nil { - return p.Err - } - module, ok := modules.GetPrecompileModule(key) - if !ok { - return ErrUnknowPrecompile - } - preCompile := module.MakeConfig() - err := preCompile.UnmarshalBinary(config) - if err != nil { - return err - } - c.PrecompileUpgrades = append(c.PrecompileUpgrades, PrecompileUpgrade{Config: preCompile}) - } else if bytes.Equal(header, stateUpdateHeader) { - config := p.UnpackBytes() - stateUpgrade := StateUpgrade{} - if err := stateUpgrade.UnmarshalBinary(config); err != nil { - return err - } - c.StateUpgrades = append(c.StateUpgrades, stateUpgrade) - } else if bytes.Equal(header, endHeader) { - break - } else { - return ErrMalformedConfigHeader + config := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + module, ok := modules.GetPrecompileModule(key) + if !ok { + return ErrUnknowPrecompile + } + preCompile := module.MakeConfig() + err := preCompile.UnmarshalBinary(config) + if err != nil { + return err + } + c.PrecompileUpgrades = append(c.PrecompileUpgrades, PrecompileUpgrade{Config: preCompile}) + } + + len = p.UnpackInt() + if p.Err != nil { + return p.Err + } + + for i := uint32(0); i < len; i++ { + config := p.UnpackBytes() + stateUpgrade := StateUpgrade{} + if err := stateUpgrade.UnmarshalBinary(config); err != nil { + return err } + c.StateUpgrades = append(c.StateUpgrades, stateUpgrade) } return nil From 5c88c087747d677f00d185c2a0e85ee4964d8ebc Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 01:26:33 -0300 Subject: [PATCH 36/48] Use fixed bytes for addresses --- precompile/contracts/nativeminter/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/precompile/contracts/nativeminter/config.go b/precompile/contracts/nativeminter/config.go index 9e3f660bdd..4e6b77fafa 100644 --- a/precompile/contracts/nativeminter/config.go +++ b/precompile/contracts/nativeminter/config.go @@ -141,7 +141,7 @@ func (c *Config) MarshalBinary() ([]byte, error) { } for _, key := range keys { - p.PackBytes(key[:]) + p.PackFixedBytes(key[:]) if p.Err != nil { return nil, p.Err } @@ -176,7 +176,7 @@ func (c *Config) UnmarshalBinary(bytes []byte) error { c.InitialMint = make(map[common.Address]*math.HexOrDecimal256, len) for i := uint32(0); i < len; i++ { - key := common.BytesToAddress(p.UnpackBytes()) + key := common.BytesToAddress(p.UnpackFixedBytes(common.AddressLength)) if p.Err != nil { return p.Err } From 1819327a5c44921e08214f7439f49b4ed48ef00c Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 02:03:31 -0300 Subject: [PATCH 37/48] Improve serialization and testing --- params/config.go | 28 ++++++++-------------------- precompile/allowlist/config.go | 8 ++++++++ 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/params/config.go b/params/config.go index 4f1263a990..1d24ad2ff0 100644 --- a/params/config.go +++ b/params/config.go @@ -994,35 +994,23 @@ func (c *ChainConfig) ToWithUpgradesJSON() *ChainConfigWithUpgradesJSON { } } -// Checks if messages have the same hash +// Take a config and serialize / deserialize it. // -// `message` is the simulation of a configuration being parsed from the local -// config. `message2` is parsing a message being exchanged through the network -// (a foreign config), and `message3` is the the deserialization and -// serialization of the foreign config. All 3 instances should have the same -// hashing, depite maybe not being identical (some configurations may be in a -// different order, but our hashing algorithm is resilient to those changes, -// thanks for our serialization library, which produces always the same output. +// `originalConfig` is a config given to this function. This function then will +// serialize it to bytes and create a new object from the bytes +// (`newConfigFromBytes`). func AssertConfigHashesAndSerialization(t *testing.T, originalConfig *UpgradeConfig) { bytes, err := originalConfig.MarshalBinary() require.NoError(t, err) - deserializedConfig := UpgradeConfig{} - require.NoError(t, deserializedConfig.UnmarshalBinary(bytes)) - - twiceDeserialized := UpgradeConfig{} - newBytes, err := deserializedConfig.MarshalBinary() - require.NoError(t, err) - require.NoError(t, twiceDeserialized.UnmarshalBinary(newBytes)) + newConfigFromBytes := UpgradeConfig{} + require.NoError(t, newConfigFromBytes.UnmarshalBinary(bytes)) hash1, err := originalConfig.Hash() require.NoError(t, err) - hash2, err := deserializedConfig.Hash() - require.NoError(t, err) - hash3, err := twiceDeserialized.Hash() + hash2, err := newConfigFromBytes.Hash() require.NoError(t, err) - require.Equal(t, deserializedConfig, twiceDeserialized) + //require.Equal(t, newConfigFromBytes, originalConfig) require.Equal(t, hash1, hash2) - require.Equal(t, hash2, hash3) } diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index 68450b821b..a7bf0645f5 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -40,6 +40,10 @@ func (c *AllowListConfig) Configure(chainConfig precompileconfig.ChainConfig, pr } func (c *AllowListConfig) packAddresses(addresses []common.Address, p *wrappers.Packer) error { + p.PackBool(addresses == nil) + if addresses == nil { + return nil + } p.PackInt(uint32(len(addresses))) if p.Err != nil { return p.Err @@ -54,6 +58,10 @@ func (c *AllowListConfig) packAddresses(addresses []common.Address, p *wrappers. } func (c *AllowListConfig) unpackAddresses(p *wrappers.Packer) ([]common.Address, error) { + isNil := p.UnpackBool() + if isNil || p.Err != nil { + return nil, p.Err + } length := p.UnpackInt() if p.Err != nil { return nil, p.Err From e079719cf2fddfcb5426b57c7832f520414d370c Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 02:09:17 -0300 Subject: [PATCH 38/48] Use fixed bytes for addresses --- precompile/contracts/rewardmanager/config.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/precompile/contracts/rewardmanager/config.go b/precompile/contracts/rewardmanager/config.go index 6c0d892f28..9bf53a0242 100644 --- a/precompile/contracts/rewardmanager/config.go +++ b/precompile/contracts/rewardmanager/config.go @@ -31,7 +31,7 @@ func (u *InitialRewardConfig) MarshalBinary() ([]byte, error) { if p.Err != nil { return nil, p.Err } - p.PackBytes(u.RewardAddress[:]) + p.PackFixedBytes(u.RewardAddress[:]) return p.Bytes, p.Err } @@ -43,7 +43,7 @@ func (u *InitialRewardConfig) UnmarshalBinary(data []byte) error { if p.Err != nil { return p.Err } - u.RewardAddress = common.BytesToAddress(p.UnpackBytes()) + u.RewardAddress = common.BytesToAddress(p.UnpackFixedBytes(common.AddressLength)) if p.Err != nil { return p.Err } From 17bf11e4d5f3c62a9abc5611b6ef0efdda153722 Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 02:14:15 -0300 Subject: [PATCH 39/48] Minor changes --- accounts/abi/bind/precompilebind/precompile_config_template.go | 2 +- .../abi/bind/precompilebind/precompile_config_test_template.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index 875900555b..1751b2c293 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -74,7 +74,7 @@ func (c * Config) MarshalBinary() ([]byte, error) { } func (c * Config) UnmarshalBinary(bytes []byte) error { - return errors.New("implement UnmarshalBinary() method") + panic("implement UnmarshalBinary() method") } // NewDisableConfig returns config for a network upgrade at [blockTimestamp] diff --git a/accounts/abi/bind/precompilebind/precompile_config_test_template.go b/accounts/abi/bind/precompilebind/precompile_config_test_template.go index 89209c64e0..9a44a47ab3 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_test_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_test_template.go @@ -81,7 +81,7 @@ func TestSerialize(t *testing.T) { common.BytesToAddress(common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000050")), }, {{- end}} - ), // enable at genesis + ), }, { Config: NewDisableConfig(&t1), // disable at timestamp 1 From 91bdff519e8514703328c908b475038ea449dbde Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 02:18:23 -0300 Subject: [PATCH 40/48] Move UnpackAddresses/PackAddresses to utils --- precompile/allowlist/config.go | 52 ++++------------------------------ precompile/contract/utils.go | 42 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index a7bf0645f5..6f68563848 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -39,46 +39,6 @@ func (c *AllowListConfig) Configure(chainConfig precompileconfig.ChainConfig, pr return nil } -func (c *AllowListConfig) packAddresses(addresses []common.Address, p *wrappers.Packer) error { - p.PackBool(addresses == nil) - if addresses == nil { - return nil - } - p.PackInt(uint32(len(addresses))) - if p.Err != nil { - return p.Err - } - for _, address := range addresses { - p.PackFixedBytes(address[:]) - if p.Err != nil { - return p.Err - } - } - return nil -} - -func (c *AllowListConfig) unpackAddresses(p *wrappers.Packer) ([]common.Address, error) { - isNil := p.UnpackBool() - if isNil || p.Err != nil { - return nil, p.Err - } - length := p.UnpackInt() - if p.Err != nil { - return nil, p.Err - } - - addresses := make([]common.Address, 0, length) - for i := uint32(0); i < length; i++ { - bytes := p.UnpackFixedBytes(common.AddressLength) - addresses = append(addresses, common.BytesToAddress(bytes)) - if p.Err != nil { - return nil, p.Err - } - } - - return addresses, nil -} - // Equal returns true iff [other] has the same admins in the same order in its allow list. func (c *AllowListConfig) Equal(other *AllowListConfig) bool { if other == nil { @@ -158,13 +118,13 @@ func (c *AllowListConfig) MarshalBinary() ([]byte, error) { Bytes: []byte{}, MaxSize: 1 * units.MiB, } - if err := c.packAddresses(c.AdminAddresses, &p); err != nil { + if err := contract.PackAddresses(c.AdminAddresses, &p); err != nil { return nil, err } - if err := c.packAddresses(c.ManagerAddresses, &p); err != nil { + if err := contract.PackAddresses(c.ManagerAddresses, &p); err != nil { return nil, err } - if err := c.packAddresses(c.EnabledAddresses, &p); err != nil { + if err := contract.PackAddresses(c.EnabledAddresses, &p); err != nil { return nil, err } return p.Bytes, nil @@ -174,15 +134,15 @@ func (c *AllowListConfig) UnmarshalBinary(data []byte) error { p := &wrappers.Packer{ Bytes: data, } - admins, err := c.unpackAddresses(p) + admins, err := contract.UnpackAddresses(p) if err != nil { return err } - managers, err := c.unpackAddresses(p) + managers, err := contract.UnpackAddresses(p) if err != nil { return err } - enableds, err := c.unpackAddresses(p) + enableds, err := contract.UnpackAddresses(p) if err != nil { return err } diff --git a/precompile/contract/utils.go b/precompile/contract/utils.go index f0a760dfbc..15f36b8df6 100644 --- a/precompile/contract/utils.go +++ b/precompile/contract/utils.go @@ -8,8 +8,10 @@ import ( "regexp" "strings" + "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/vmerrs" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ) @@ -62,3 +64,43 @@ func ParseABI(rawABI string) abi.ABI { func IsDUpgradeActivated(evm AccessibleState) bool { return evm.GetChainConfig().IsDUpgrade(evm.GetBlockContext().Timestamp()) } + +func PackAddresses(addresses []common.Address, p *wrappers.Packer) error { + p.PackBool(addresses == nil) + if addresses == nil { + return nil + } + p.PackInt(uint32(len(addresses))) + if p.Err != nil { + return p.Err + } + for _, address := range addresses { + p.PackFixedBytes(address[:]) + if p.Err != nil { + return p.Err + } + } + return nil +} + +func UnpackAddresses(p *wrappers.Packer) ([]common.Address, error) { + isNil := p.UnpackBool() + if isNil || p.Err != nil { + return nil, p.Err + } + length := p.UnpackInt() + if p.Err != nil { + return nil, p.Err + } + + addresses := make([]common.Address, 0, length) + for i := uint32(0); i < length; i++ { + bytes := p.UnpackFixedBytes(common.AddressLength) + addresses = append(addresses, common.BytesToAddress(bytes)) + if p.Err != nil { + return nil, p.Err + } + } + + return addresses, nil +} From a593a68e42794e572fc4ea75286894cb7a7e8d71 Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 02:20:13 -0300 Subject: [PATCH 41/48] Fix typo --- params/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/params/config.go b/params/config.go index 1d24ad2ff0..b8437b3227 100644 --- a/params/config.go +++ b/params/config.go @@ -252,7 +252,7 @@ func (c *UpgradeConfig) UnmarshalBinary(data []byte) error { return p.Err } if err := c.OptionalNetworkUpgrades.UnmarshalBinary(bytes); err != nil { - return nil + return err } } From 987017bd6abd0819c99ff8163a3262f897089f02 Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 03:12:15 -0300 Subject: [PATCH 42/48] Update template It generates valid marshal/unmarshal t# Please enter the commit message for your changes. Lines starting --- .../precompile_config_template.go | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index 1751b2c293..fe164b4762 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -11,9 +11,10 @@ const tmplSourcePrecompileConfigGo = ` package {{.Package}} import ( - "errors" - "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/ava-labs/avalanchego/utils/wrappers" + "github.com/docker/docker/pkg/units" + {{- if .Contract.AllowList}} "github.com/ava-labs/subnet-evm/precompile/allowlist" @@ -53,7 +54,7 @@ func NewConfig(blockTimestamp *uint64{{if .Contract.AllowList}}, admins []common func (c * Config) MarshalBinary() ([]byte, error) { p := wrappers.Packer { Bytes: []byte{}, - MaxSize: 1 * units.MiB + MaxSize: 1 * units.MiB, } {{- if .Contract.AllowList}} allowBytes, err := c.AllowListConfig.MarshalBinary() @@ -74,7 +75,24 @@ func (c * Config) MarshalBinary() ([]byte, error) { } func (c * Config) UnmarshalBinary(bytes []byte) error { - panic("implement UnmarshalBinary() method") + p := wrappers.Packer { + Bytes: bytes, + } + {{- if .Contract.AllowList}} + allowList := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + if err := c.AllowListConfig.UnmarshalBinary(allowList); err != nil { + return err + } + {{- end}} + upgrade := p.UnpackBytes() + if p.Err != nil { + return p.Err + } + + return c.Upgrade.UnmarshalBinary(upgrade) } // NewDisableConfig returns config for a network upgrade at [blockTimestamp] From 19b3073e7c9cdca1c7b7b55d09cfb446988244d8 Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 15:09:18 -0300 Subject: [PATCH 43/48] Move serialization to utils --- commontype/fee_config.go | 98 +++++++++++++++++++++++----------- precompile/allowlist/config.go | 13 ++--- precompile/contract/utils.go | 44 +-------------- utils/bytes.go | 69 +++++++++++++++++++++++- 4 files changed, 144 insertions(+), 80 deletions(-) diff --git a/commontype/fee_config.go b/commontype/fee_config.go index cf1867d385..4a22645e46 100644 --- a/commontype/fee_config.go +++ b/commontype/fee_config.go @@ -146,31 +146,40 @@ func (f *FeeConfig) checkByteLens() error { return nil } -func (c *FeeConfig) getBigIntToSerialize() []**big.Int { - return []**big.Int{ - &c.GasLimit, &c.MinBaseFee, &c.TargetGas, &c.BaseFeeChangeDenominator, - &c.MinBlockGasCost, &c.MaxBlockGasCost, &c.BlockGasCostStep, - } -} - func (c *FeeConfig) MarshalBinary() ([]byte, error) { p := wrappers.Packer{ Bytes: []byte{}, MaxSize: 1 * units.MiB, } - for _, bigint := range c.getBigIntToSerialize() { - p.PackBool(*bigint == nil) - if p.Err != nil { - return nil, p.Err - } - if bigint != nil { - p.PackBytes((*bigint).Bytes()) - if p.Err != nil { - return nil, p.Err - } - } + if err := utils.PackBigInt(&p, c.GasLimit); err != nil { + return nil, err + } + + if err := utils.PackBigInt(&p, c.MinBaseFee); err != nil { + return nil, err + } + + if err := utils.PackBigInt(&p, c.TargetGas); err != nil { + return nil, err + } + + if err := utils.PackBigInt(&p, c.BaseFeeChangeDenominator); err != nil { + return nil, err + } + + if err := utils.PackBigInt(&p, c.MinBlockGasCost); err != nil { + return nil, err + } + + if err := utils.PackBigInt(&p, c.MaxBlockGasCost); err != nil { + return nil, err + } + + if err := utils.PackBigInt(&p, c.BlockGasCostStep); err != nil { + return nil, err } + p.PackLong(c.TargetBlockRate) if p.Err != nil { return nil, p.Err @@ -183,18 +192,47 @@ func (c *FeeConfig) UnmarshalBinary(data []byte) error { p := wrappers.Packer{ Bytes: data, } - for _, bigint := range c.getBigIntToSerialize() { - isNil := p.UnpackBool() - if p.Err != nil { - return p.Err - } - if isNil { - continue - } - *bigint = big.NewInt(0).SetBytes(p.UnpackBytes()) - if p.Err != nil { - return p.Err - } + + var err error + + c.GasLimit, err = utils.UnpackBigInt(&p) + if err != nil { + return err + } + + c.MinBaseFee, err = utils.UnpackBigInt(&p) + if err != nil { + return err + } + + c.MinBaseFee, err = utils.UnpackBigInt(&p) + if err != nil { + return err + } + + c.TargetGas, err = utils.UnpackBigInt(&p) + if err != nil { + return err + } + + c.BaseFeeChangeDenominator, err = utils.UnpackBigInt(&p) + if err != nil { + return err + } + + c.MinBlockGasCost, err = utils.UnpackBigInt(&p) + if err != nil { + return err + } + + c.MaxBlockGasCost, err = utils.UnpackBigInt(&p) + if err != nil { + return err + } + + c.BlockGasCostStep, err = utils.UnpackBigInt(&p) + if err != nil { + return err } c.TargetBlockRate = p.UnpackLong() diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index 6f68563848..f98b34f0f9 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -9,6 +9,7 @@ import ( "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/ava-labs/subnet-evm/utils" "github.com/docker/docker/pkg/units" "github.com/ethereum/go-ethereum/common" ) @@ -118,13 +119,13 @@ func (c *AllowListConfig) MarshalBinary() ([]byte, error) { Bytes: []byte{}, MaxSize: 1 * units.MiB, } - if err := contract.PackAddresses(c.AdminAddresses, &p); err != nil { + if err := utils.PackAddresses(&p, c.AdminAddresses); err != nil { return nil, err } - if err := contract.PackAddresses(c.ManagerAddresses, &p); err != nil { + if err := utils.PackAddresses(&p, c.ManagerAddresses); err != nil { return nil, err } - if err := contract.PackAddresses(c.EnabledAddresses, &p); err != nil { + if err := utils.PackAddresses(&p, c.EnabledAddresses); err != nil { return nil, err } return p.Bytes, nil @@ -134,15 +135,15 @@ func (c *AllowListConfig) UnmarshalBinary(data []byte) error { p := &wrappers.Packer{ Bytes: data, } - admins, err := contract.UnpackAddresses(p) + admins, err := utils.UnpackAddresses(p) if err != nil { return err } - managers, err := contract.UnpackAddresses(p) + managers, err := utils.UnpackAddresses(p) if err != nil { return err } - enableds, err := contract.UnpackAddresses(p) + enableds, err := utils.UnpackAddresses(p) if err != nil { return err } diff --git a/precompile/contract/utils.go b/precompile/contract/utils.go index 15f36b8df6..15e6f292cc 100644 --- a/precompile/contract/utils.go +++ b/precompile/contract/utils.go @@ -8,10 +8,8 @@ import ( "regexp" "strings" - "github.com/ava-labs/avalanchego/utils/wrappers" "github.com/ava-labs/subnet-evm/accounts/abi" "github.com/ava-labs/subnet-evm/vmerrs" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ) @@ -63,44 +61,4 @@ func ParseABI(rawABI string) abi.ABI { func IsDUpgradeActivated(evm AccessibleState) bool { return evm.GetChainConfig().IsDUpgrade(evm.GetBlockContext().Timestamp()) -} - -func PackAddresses(addresses []common.Address, p *wrappers.Packer) error { - p.PackBool(addresses == nil) - if addresses == nil { - return nil - } - p.PackInt(uint32(len(addresses))) - if p.Err != nil { - return p.Err - } - for _, address := range addresses { - p.PackFixedBytes(address[:]) - if p.Err != nil { - return p.Err - } - } - return nil -} - -func UnpackAddresses(p *wrappers.Packer) ([]common.Address, error) { - isNil := p.UnpackBool() - if isNil || p.Err != nil { - return nil, p.Err - } - length := p.UnpackInt() - if p.Err != nil { - return nil, p.Err - } - - addresses := make([]common.Address, 0, length) - for i := uint32(0); i < length; i++ { - bytes := p.UnpackFixedBytes(common.AddressLength) - addresses = append(addresses, common.BytesToAddress(bytes)) - if p.Err != nil { - return nil, p.Err - } - } - - return addresses, nil -} +} \ No newline at end of file diff --git a/utils/bytes.go b/utils/bytes.go index 54258b20f4..aca98ac76c 100644 --- a/utils/bytes.go +++ b/utils/bytes.go @@ -3,7 +3,12 @@ package utils -import "github.com/ethereum/go-ethereum/common" +import ( + "math/big" + + "github.com/ava-labs/avalanchego/utils/wrappers" + "github.com/ethereum/go-ethereum/common" +) // IncrOne increments bytes value by one func IncrOne(bytes []byte) { @@ -42,3 +47,65 @@ func BytesToHashSlice(b []byte) []common.Hash { } return hashes } + +func PackBigInt(p *wrappers.Packer, number *big.Int) error { + p.PackBool(number == nil) + if p.Err != nil { + return p.Err + } + if number != nil { + p.PackBytes(number.Bytes()) + } + + return p.Err +} + +func UnpackBigInt(p *wrappers.Packer) (*big.Int, error) { + isNil := p.UnpackBool() + if p.Err != nil || isNil { + return nil, p.Err + } + + number := big.NewInt(0).SetBytes(p.UnpackBytes()) + return number, p.Err +} + +func PackAddresses(p *wrappers.Packer, addresses []common.Address) error { + p.PackBool(addresses == nil) + if addresses == nil { + return nil + } + p.PackInt(uint32(len(addresses))) + if p.Err != nil { + return p.Err + } + for _, address := range addresses { + p.PackFixedBytes(address[:]) + if p.Err != nil { + return p.Err + } + } + return nil +} + +func UnpackAddresses(p *wrappers.Packer) ([]common.Address, error) { + isNil := p.UnpackBool() + if isNil || p.Err != nil { + return nil, p.Err + } + length := p.UnpackInt() + if p.Err != nil { + return nil, p.Err + } + + addresses := make([]common.Address, 0, length) + for i := uint32(0); i < length; i++ { + bytes := p.UnpackFixedBytes(common.AddressLength) + addresses = append(addresses, common.BytesToAddress(bytes)) + if p.Err != nil { + return nil, p.Err + } + } + + return addresses, nil +} From e8ffb133b060d8af1532fdbbf8c8878e1657d3a7 Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 15:20:42 -0300 Subject: [PATCH 44/48] Fixed typo --- commontype/fee_config.go | 5 ----- utils/bytes.go | 11 +++++------ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/commontype/fee_config.go b/commontype/fee_config.go index 4a22645e46..81b54a9a4a 100644 --- a/commontype/fee_config.go +++ b/commontype/fee_config.go @@ -205,11 +205,6 @@ func (c *FeeConfig) UnmarshalBinary(data []byte) error { return err } - c.MinBaseFee, err = utils.UnpackBigInt(&p) - if err != nil { - return err - } - c.TargetGas, err = utils.UnpackBigInt(&p) if err != nil { return err diff --git a/utils/bytes.go b/utils/bytes.go index aca98ac76c..18c20084c0 100644 --- a/utils/bytes.go +++ b/utils/bytes.go @@ -10,6 +10,8 @@ import ( "github.com/ethereum/go-ethereum/common" ) +const BigIntBytesLength = 32 + // IncrOne increments bytes value by one func IncrOne(bytes []byte) { index := len(bytes) - 1 @@ -50,11 +52,8 @@ func BytesToHashSlice(b []byte) []common.Hash { func PackBigInt(p *wrappers.Packer, number *big.Int) error { p.PackBool(number == nil) - if p.Err != nil { - return p.Err - } - if number != nil { - p.PackBytes(number.Bytes()) + if p.Err == nil && number != nil { + p.PackFixedBytes(number.FillBytes(make([]byte, BigIntBytesLength))) } return p.Err @@ -66,7 +65,7 @@ func UnpackBigInt(p *wrappers.Packer) (*big.Int, error) { return nil, p.Err } - number := big.NewInt(0).SetBytes(p.UnpackBytes()) + number := big.NewInt(0).SetBytes(p.UnpackFixedBytes(BigIntBytesLength)) return number, p.Err } From 550f7c0161a5695ba765733a060140d12ee12512 Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 15:24:02 -0300 Subject: [PATCH 45/48] Fixed typo --- precompile/contract/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/precompile/contract/utils.go b/precompile/contract/utils.go index 15e6f292cc..f0a760dfbc 100644 --- a/precompile/contract/utils.go +++ b/precompile/contract/utils.go @@ -61,4 +61,4 @@ func ParseABI(rawABI string) abi.ABI { func IsDUpgradeActivated(evm AccessibleState) bool { return evm.GetChainConfig().IsDUpgrade(evm.GetBlockContext().Timestamp()) -} \ No newline at end of file +} From a08d7461c1a9677d3de3324ba13645da4952687f Mon Sep 17 00:00:00 2001 From: Cesar Date: Thu, 4 Jan 2024 15:50:04 -0300 Subject: [PATCH 46/48] Fix typo --- accounts/abi/bind/precompilebind/precompile_config_template.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accounts/abi/bind/precompilebind/precompile_config_template.go b/accounts/abi/bind/precompilebind/precompile_config_template.go index fe164b4762..ffb6679d81 100644 --- a/accounts/abi/bind/precompilebind/precompile_config_template.go +++ b/accounts/abi/bind/precompilebind/precompile_config_template.go @@ -63,7 +63,7 @@ func (c * Config) MarshalBinary() ([]byte, error) { } p.PackBytes(allowBytes) if p.Err != nil { - return ni, p.Err + return nil, p.Err } {{- end}} upgradeBytes, err := c.Upgrade.MarshalBinary() From 1bf46648e171a1ab9cea39a9b57bf95a35fcfbc1 Mon Sep 17 00:00:00 2001 From: Cesar Date: Fri, 5 Jan 2024 01:56:59 -0300 Subject: [PATCH 47/48] Rebase with master --- params/config_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/params/config_test.go b/params/config_test.go index afc5588212..7612e9dfce 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -346,7 +346,6 @@ func TestChainConfigMarshalWithUpgradesAndOptionalUpgrade(t *testing.T) { MuirGlacierBlock: big.NewInt(0), MandatoryNetworkUpgrades: MandatoryNetworkUpgrades{ SubnetEVMTimestamp: utils.NewUint64(0), - DUpgradeTimestamp: utils.NewUint64(0), }, GenesisPrecompiles: Precompiles{}, }, @@ -382,7 +381,6 @@ func TestChainConfigMarshalWithUpgradesAndOptionalUpgrade(t *testing.T) { "istanbulBlock": 0, "muirGlacierBlock": 0, "subnetEVMTimestamp": 0, - "dUpgradeTimestamp": 0, "upgrades": { "precompileUpgrades": [ { From ac0e945691ad39dac3ed0fc16f5238a68e879c99 Mon Sep 17 00:00:00 2001 From: Cesar Date: Fri, 5 Jan 2024 02:03:58 -0300 Subject: [PATCH 48/48] Add comments back --- precompile/contracts/feemanager/config.go | 4 ++-- precompile/contracts/nativeminter/config.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/precompile/contracts/feemanager/config.go b/precompile/contracts/feemanager/config.go index 83dbe27b31..77ed5802fd 100644 --- a/precompile/contracts/feemanager/config.go +++ b/precompile/contracts/feemanager/config.go @@ -17,9 +17,9 @@ var _ precompileconfig.Config = &Config{} // Config implements the StatefulPrecompileConfig interface while adding in the // FeeManager specific precompile config. type Config struct { - allowlist.AllowListConfig + allowlist.AllowListConfig // Config for the fee config manager allow list precompileconfig.Upgrade - InitialFeeConfig *commontype.FeeConfig `json:"initialFeeConfig,omitempty" ` // initial fee config to be immediately activated + InitialFeeConfig *commontype.FeeConfig `json:"initialFeeConfig,omitempty"` // initial fee config to be immediately activated } // NewConfig returns a config for a network upgrade at [blockTimestamp] that enables diff --git a/precompile/contracts/nativeminter/config.go b/precompile/contracts/nativeminter/config.go index 4e6b77fafa..bc474fb013 100644 --- a/precompile/contracts/nativeminter/config.go +++ b/precompile/contracts/nativeminter/config.go @@ -25,7 +25,7 @@ var _ precompileconfig.Config = &Config{} type Config struct { allowlist.AllowListConfig precompileconfig.Upgrade - InitialMint map[common.Address]*math.HexOrDecimal256 `json:"initialMint,omitempty"` + InitialMint map[common.Address]*math.HexOrDecimal256 `json:"initialMint,omitempty"` // addresses to receive the initial mint mapped to the amount to mint } // NewConfig returns a config for a network upgrade at [blockTimestamp] that enables