From 0722f97af59839ac0811b54578b57065f96f5eb5 Mon Sep 17 00:00:00 2001 From: Ceyhun Onur Date: Tue, 4 Apr 2023 18:00:22 +0300 Subject: [PATCH 01/10] Config test suites (#557) * add verify allow list tests * use new verify allow list suite in precompiles * add equal test suite * nits * nits --- precompile/allowlist/allowlist_test.go | 10 +- precompile/allowlist/config.go | 6 +- precompile/allowlist/config_test.go | 93 ++---------- precompile/allowlist/test_allowlist.go | 19 --- precompile/allowlist/test_allowlist_config.go | 133 ++++++++++++++++++ .../deployerallowlist/config_test.go | 95 +++---------- .../contracts/feemanager/config_test.go | 118 +++++----------- .../contracts/nativeminter/config_test.go | 126 ++++++----------- .../contracts/rewardmanager/config_test.go | 107 +++++--------- .../contracts/txallowlist/config_test.go | 111 ++++----------- precompile/testutils/test_config.go | 21 +++ 11 files changed, 334 insertions(+), 505 deletions(-) create mode 100644 precompile/allowlist/test_allowlist_config.go create mode 100644 precompile/testutils/test_config.go diff --git a/precompile/allowlist/allowlist_test.go b/precompile/allowlist/allowlist_test.go index f4c0f5fc21..4f0eeb3b51 100644 --- a/precompile/allowlist/allowlist_test.go +++ b/precompile/allowlist/allowlist_test.go @@ -22,14 +22,18 @@ var ( ) type dummyConfig struct { - *AllowListConfig + AllowListConfig } func (d *dummyConfig) Key() string { return "dummy" } func (d *dummyConfig) Timestamp() *big.Int { return common.Big0 } func (d *dummyConfig) IsDisabled() bool { return false } -func (d *dummyConfig) Equal(other precompileconfig.Config) bool { - return d.AllowListConfig.Equal(other.(*dummyConfig).AllowListConfig) +func (d *dummyConfig) Equal(cfg precompileconfig.Config) bool { + other, ok := (cfg).(*dummyConfig) + if !ok { + return false + } + return d.AllowListConfig.Equal(&other.AllowListConfig) } type dummyConfigurator struct{} diff --git a/precompile/allowlist/config.go b/precompile/allowlist/config.go index 90ef49a811..7c20841c78 100644 --- a/precompile/allowlist/config.go +++ b/precompile/allowlist/config.go @@ -58,7 +58,7 @@ func (c *AllowListConfig) Verify() error { // check for duplicates in enabled list for _, enabledAddr := range c.EnabledAddresses { if _, ok := addressMap[enabledAddr]; ok { - return fmt.Errorf("duplicate address %s in enabled list", enabledAddr) + return fmt.Errorf("duplicate address in enabled list: %s", enabledAddr) } addressMap[enabledAddr] = EnabledRole } @@ -67,9 +67,9 @@ func (c *AllowListConfig) Verify() error { for _, adminAddr := range c.AdminAddresses { if role, ok := addressMap[adminAddr]; ok { if role == AdminRole { - return fmt.Errorf("duplicate address %s in admin list", adminAddr) + return fmt.Errorf("duplicate address in admin list: %s", adminAddr) } else { - return fmt.Errorf("cannot set address %s as both admin and enabled", adminAddr) + return fmt.Errorf("cannot set address as both admin and enabled: %s", adminAddr) } } addressMap[adminAddr] = AdminRole diff --git a/precompile/allowlist/config_test.go b/precompile/allowlist/config_test.go index bc3a3d9d26..a4dbaeec71 100644 --- a/precompile/allowlist/config_test.go +++ b/precompile/allowlist/config_test.go @@ -6,92 +6,19 @@ package allowlist import ( "testing" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" + "github.com/ava-labs/subnet-evm/precompile/modules" ) -func TestVerifyAllowlistAllowList(t *testing.T) { - admins := []common.Address{{1}} - enableds := []common.Address{{2}} - tests := []struct { - name string - config AllowListConfig - expectedError string - }{ - { - name: "invalid allow list config in allowlist", - config: AllowListConfig{admins, admins}, - expectedError: "cannot set address", - }, - { - name: "nil member allow list config in allowlist", - config: AllowListConfig{nil, nil}, - expectedError: "", - }, - { - name: "empty member allow list config in allowlist", - config: AllowListConfig{[]common.Address{}, []common.Address{}}, - expectedError: "", - }, - { - name: "valid allow list config in allowlist", - config: AllowListConfig{admins, enableds}, - expectedError: "", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) - - err := tt.config.Verify() - if tt.expectedError == "" { - require.NoError(err) - } else { - require.ErrorContains(err, tt.expectedError) - } - }) - } +var testModule = modules.Module{ + Address: dummyAddr, + Contract: CreateAllowListPrecompile(dummyAddr), + Configurator: &dummyConfigurator{}, } -func TestEqualAllowListAllowList(t *testing.T) { - admins := []common.Address{{1}} - enableds := []common.Address{{2}} - tests := []struct { - name string - config *AllowListConfig - other *AllowListConfig - expected bool - }{ - { - name: "non-nil config and nil other", - config: &AllowListConfig{admins, enableds}, - other: nil, - expected: false, - }, - { - name: "different admin", - config: &AllowListConfig{admins, enableds}, - other: &AllowListConfig{[]common.Address{{3}}, enableds}, - expected: false, - }, - { - name: "different enabled", - config: &AllowListConfig{admins, enableds}, - other: &AllowListConfig{admins, []common.Address{{3}}}, - expected: false, - }, - { - name: "same config", - config: &AllowListConfig{admins, enableds}, - other: &AllowListConfig{admins, enableds}, - expected: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) +func TestVerifyAllowlist(t *testing.T) { + VerifyPrecompileWithAllowListTests(t, testModule, nil) +} - require.Equal(tt.expected, tt.config.Equal(tt.other)) - }) - } +func TestEqualAllowList(t *testing.T) { + EqualPrecompileWithAllowListTests(t, testModule, nil) } diff --git a/precompile/allowlist/test_allowlist.go b/precompile/allowlist/test_allowlist.go index 78158e55ee..233ade3f65 100644 --- a/precompile/allowlist/test_allowlist.go +++ b/precompile/allowlist/test_allowlist.go @@ -4,12 +4,10 @@ package allowlist import ( - "encoding/json" "testing" "github.com/ava-labs/subnet-evm/precompile/contract" "github.com/ava-labs/subnet-evm/precompile/modules" - "github.com/ava-labs/subnet-evm/precompile/precompileconfig" "github.com/ava-labs/subnet-evm/precompile/testutils" "github.com/ava-labs/subnet-evm/vmerrs" "github.com/ethereum/go-ethereum/common" @@ -22,23 +20,6 @@ var ( TestNoRoleAddr = common.HexToAddress("0x0000000000000000000000000000000000000033") ) -// mkConfigWithAllowList creates a new config with the correct type for [module] -// by marshalling [cfg] to JSON and then unmarshalling it into the config. -func mkConfigWithAllowList(module modules.Module, cfg *AllowListConfig) precompileconfig.Config { - jsonBytes, err := json.Marshal(cfg) - if err != nil { - panic(err) - } - - moduleCfg := module.MakeConfig() - err = json.Unmarshal(jsonBytes, moduleCfg) - if err != nil { - panic(err) - } - - return moduleCfg -} - func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { contractAddress := module.Address return map[string]testutils.PrecompileTest{ diff --git a/precompile/allowlist/test_allowlist_config.go b/precompile/allowlist/test_allowlist_config.go new file mode 100644 index 0000000000..d1dc909768 --- /dev/null +++ b/precompile/allowlist/test_allowlist_config.go @@ -0,0 +1,133 @@ +// (c) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package allowlist + +import ( + "encoding/json" + "testing" + + "github.com/ava-labs/subnet-evm/precompile/modules" + "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/ava-labs/subnet-evm/precompile/testutils" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +// mkConfigWithAllowList creates a new config with the correct type for [module] +// by marshalling [cfg] to JSON and then unmarshalling it into the config. +func mkConfigWithAllowList(module modules.Module, cfg *AllowListConfig) precompileconfig.Config { + jsonBytes, err := json.Marshal(cfg) + if err != nil { + panic(err) + } + + moduleCfg := module.MakeConfig() + err = json.Unmarshal(jsonBytes, moduleCfg) + if err != nil { + panic(err) + } + + return moduleCfg +} + +func AllowListConfigVerifyTests(module modules.Module) map[string]testutils.ConfigVerifyTest { + return map[string]testutils.ConfigVerifyTest{ + "invalid allow list config with duplicate admins in allowlist": { + Config: mkConfigWithAllowList(module, &AllowListConfig{[]common.Address{TestAdminAddr, TestAdminAddr}, nil}), + ExpectedError: "duplicate address in admin list", + }, + "invalid allow list config with duplicate enableds in allowlist": { + Config: mkConfigWithAllowList(module, &AllowListConfig{nil, []common.Address{TestEnabledAddr, TestEnabledAddr}}), + ExpectedError: "duplicate address in enabled list", + }, + "invalid allow list config with same admin and enabled in allowlist": { + Config: mkConfigWithAllowList(module, &AllowListConfig{[]common.Address{TestAdminAddr}, []common.Address{TestAdminAddr}}), + ExpectedError: "cannot set address as both admin and enabled", + }, + "nil member allow list config in allowlist": { + Config: mkConfigWithAllowList(module, &AllowListConfig{nil, nil}), + ExpectedError: "", + }, + "empty member allow list config in allowlist": { + Config: mkConfigWithAllowList(module, &AllowListConfig{[]common.Address{}, []common.Address{}}), + ExpectedError: "", + }, + "valid allow list config in allowlist": { + Config: mkConfigWithAllowList(module, &AllowListConfig{[]common.Address{TestAdminAddr}, []common.Address{TestEnabledAddr}}), + ExpectedError: "", + }, + } +} + +func AllowListConfigEqualTests(module modules.Module) map[string]testutils.ConfigEqualTest { + return map[string]testutils.ConfigEqualTest{ + "allowlist non-nil config and nil other": { + Config: mkConfigWithAllowList(module, &AllowListConfig{[]common.Address{TestAdminAddr}, []common.Address{TestEnabledAddr}}), + Other: nil, + Expected: false, + }, + "allowlist different admin": { + Config: mkConfigWithAllowList(module, &AllowListConfig{[]common.Address{TestAdminAddr}, []common.Address{TestEnabledAddr}}), + Other: mkConfigWithAllowList(module, &AllowListConfig{[]common.Address{{3}}, []common.Address{TestEnabledAddr}}), + Expected: false, + }, + "allowlist different enabled": { + Config: mkConfigWithAllowList(module, &AllowListConfig{[]common.Address{TestAdminAddr}, []common.Address{TestEnabledAddr}}), + Other: mkConfigWithAllowList(module, &AllowListConfig{[]common.Address{module.Address}, []common.Address{{3}}}), + Expected: false, + }, + "allowlist same config": { + Config: mkConfigWithAllowList(module, &AllowListConfig{[]common.Address{TestAdminAddr}, []common.Address{TestEnabledAddr}}), + Other: mkConfigWithAllowList(module, &AllowListConfig{[]common.Address{TestAdminAddr}, []common.Address{TestEnabledAddr}}), + Expected: true, + }, + } +} + +func VerifyPrecompileWithAllowListTests(t *testing.T, module modules.Module, verifyTests map[string]testutils.ConfigVerifyTest) { + t.Helper() + tests := AllowListConfigVerifyTests(module) + // Add the contract specific tests to the map of tests to run. + for name, test := range verifyTests { + if _, exists := tests[name]; exists { + t.Fatalf("duplicate test name: %s", name) + } + tests[name] = test + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + t.Helper() + require := require.New(t) + + err := test.Config.Verify() + if test.ExpectedError == "" { + require.NoError(err) + } else { + require.ErrorContains(err, test.ExpectedError) + } + }) + } +} + +func EqualPrecompileWithAllowListTests(t *testing.T, module modules.Module, equalTests map[string]testutils.ConfigEqualTest) { + t.Helper() + tests := AllowListConfigEqualTests(module) + // Add the contract specific tests to the map of tests to run. + for name, test := range equalTests { + if _, exists := tests[name]; exists { + t.Fatalf("duplicate test name: %s", name) + } + tests[name] = test + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + t.Helper() + require := require.New(t) + + require.Equal(test.Expected, test.Config.Equal(test.Other)) + }) + } +} diff --git a/precompile/contracts/deployerallowlist/config_test.go b/precompile/contracts/deployerallowlist/config_test.go index caa3d8995a..318531d02b 100644 --- a/precompile/contracts/deployerallowlist/config_test.go +++ b/precompile/contracts/deployerallowlist/config_test.go @@ -7,89 +7,40 @@ import ( "math/big" "testing" + "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/ava-labs/subnet-evm/precompile/testutils" "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" ) func TestVerifyContractDeployerConfig(t *testing.T) { - admins := []common.Address{{1}} - tests := []struct { - name string - config precompileconfig.Config - ExpectedError string - }{ - { - name: "invalid allow list config in deployer allowlist", - config: NewConfig(big.NewInt(3), admins, admins), - ExpectedError: "cannot set address", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) - - err := tt.config.Verify() - if tt.ExpectedError == "" { - require.NoError(err) - } else { - require.ErrorContains(err, tt.ExpectedError) - } - }) - } + allowlist.VerifyPrecompileWithAllowListTests(t, Module, nil) } func TestEqualContractDeployerAllowListConfig(t *testing.T) { - admins := []common.Address{{1}} - enableds := []common.Address{{2}} - tests := []struct { - name string - config precompileconfig.Config - other precompileconfig.Config - expected bool - }{ - { - name: "non-nil config and nil other", - config: NewConfig(big.NewInt(3), admins, enableds), - other: nil, - expected: false, + admins := []common.Address{allowlist.TestAdminAddr} + enableds := []common.Address{allowlist.TestEnabledAddr} + tests := map[string]testutils.ConfigEqualTest{ + "non-nil config and nil other": { + Config: NewConfig(big.NewInt(3), admins, enableds), + Other: nil, + Expected: false, }, - { - name: "different type", - config: NewConfig(big.NewInt(3), admins, enableds), - other: precompileconfig.NewNoopStatefulPrecompileConfig(), - expected: false, + "different type": { + Config: NewConfig(nil, nil, nil), + Other: precompileconfig.NewNoopStatefulPrecompileConfig(), + Expected: false, }, - { - name: "different admin", - config: NewConfig(big.NewInt(3), admins, enableds), - other: NewConfig(big.NewInt(3), []common.Address{{3}}, enableds), - expected: false, + "different timestamp": { + Config: NewConfig(big.NewInt(3), admins, enableds), + Other: NewConfig(big.NewInt(4), admins, enableds), + Expected: false, }, - { - name: "different enabled", - config: NewConfig(big.NewInt(3), admins, enableds), - other: NewConfig(big.NewInt(3), admins, []common.Address{{3}}), - expected: false, + "same config": { + Config: NewConfig(big.NewInt(3), admins, enableds), + Other: NewConfig(big.NewInt(3), admins, enableds), + Expected: true, }, - { - name: "different timestamp", - config: NewConfig(big.NewInt(3), admins, enableds), - other: NewConfig(big.NewInt(4), admins, enableds), - expected: false, - }, - { - name: "same config", - config: NewConfig(big.NewInt(3), admins, enableds), - other: NewConfig(big.NewInt(3), admins, enableds), - expected: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) - - require.Equal(tt.expected, tt.config.Equal(tt.other)) - }) } + allowlist.EqualPrecompileWithAllowListTests(t, Module, tests) } diff --git a/precompile/contracts/feemanager/config_test.go b/precompile/contracts/feemanager/config_test.go index 4b5654d5d9..0f3b7bca33 100644 --- a/precompile/contracts/feemanager/config_test.go +++ b/precompile/contracts/feemanager/config_test.go @@ -8,9 +8,10 @@ import ( "testing" "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/ava-labs/subnet-evm/precompile/testutils" "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" ) var validFeeConfig = commontype.FeeConfig{ @@ -27,106 +28,61 @@ var validFeeConfig = commontype.FeeConfig{ } func TestVerifyFeeManagerConfig(t *testing.T) { - admins := []common.Address{{1}} + admins := []common.Address{allowlist.TestAdminAddr} invalidFeeConfig := validFeeConfig invalidFeeConfig.GasLimit = big.NewInt(0) - tests := []struct { - name string - config precompileconfig.Config - ExpectedError string - }{ - { - name: "invalid allow list config in fee manager allowlist", - config: NewConfig(big.NewInt(3), admins, admins, nil), - ExpectedError: "cannot set address", - }, - { - name: "invalid initial fee manager config", - config: NewConfig(big.NewInt(3), admins, nil, &invalidFeeConfig), + tests := map[string]testutils.ConfigVerifyTest{ + "invalid initial fee manager config": { + Config: NewConfig(big.NewInt(3), admins, nil, &invalidFeeConfig), ExpectedError: "gasLimit = 0 cannot be less than or equal to 0", }, - { - name: "nil initial fee manager config", - config: NewConfig(big.NewInt(3), admins, nil, &commontype.FeeConfig{}), + "nil initial fee manager config": { + Config: NewConfig(big.NewInt(3), admins, nil, &commontype.FeeConfig{}), ExpectedError: "gasLimit cannot be nil", }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) - - err := tt.config.Verify() - if tt.ExpectedError == "" { - require.NoError(err) - } else { - require.ErrorContains(err, tt.ExpectedError) - } - }) - } + allowlist.VerifyPrecompileWithAllowListTests(t, Module, tests) } func TestEqualFeeManagerConfig(t *testing.T) { - admins := []common.Address{{1}} - enableds := []common.Address{{2}} - tests := []struct { - name string - config precompileconfig.Config - other precompileconfig.Config - expected bool - }{ - { - name: "non-nil config and nil other", - config: NewConfig(big.NewInt(3), admins, enableds, nil), - other: nil, - expected: false, + admins := []common.Address{allowlist.TestAdminAddr} + enableds := []common.Address{allowlist.TestEnabledAddr} + tests := map[string]testutils.ConfigEqualTest{ + "non-nil config and nil other": { + Config: NewConfig(big.NewInt(3), admins, enableds, nil), + Other: nil, + Expected: false, }, - { - name: "different type", - config: NewConfig(big.NewInt(3), admins, enableds, nil), - other: precompileconfig.NewNoopStatefulPrecompileConfig(), - expected: false, + "different type": { + Config: NewConfig(big.NewInt(3), admins, enableds, nil), + Other: precompileconfig.NewNoopStatefulPrecompileConfig(), + Expected: false, }, - { - name: "different timestamp", - config: NewConfig(big.NewInt(3), admins, nil, nil), - other: NewConfig(big.NewInt(4), admins, nil, nil), - expected: false, + "different timestamp": { + Config: NewConfig(big.NewInt(3), admins, nil, nil), + Other: NewConfig(big.NewInt(4), admins, nil, nil), + Expected: false, }, - { - name: "different enabled", - config: NewConfig(big.NewInt(3), admins, nil, nil), - other: NewConfig(big.NewInt(3), admins, enableds, nil), - expected: false, + "non-nil initial config and nil initial config": { + Config: NewConfig(big.NewInt(3), admins, nil, &validFeeConfig), + Other: NewConfig(big.NewInt(3), admins, nil, nil), + Expected: false, }, - { - name: "non-nil initial config and nil initial config", - config: NewConfig(big.NewInt(3), admins, nil, &validFeeConfig), - other: NewConfig(big.NewInt(3), admins, nil, nil), - expected: false, - }, - { - name: "different initial config", - config: NewConfig(big.NewInt(3), admins, nil, &validFeeConfig), - other: NewConfig(big.NewInt(3), admins, nil, + "different initial config": { + Config: NewConfig(big.NewInt(3), admins, nil, &validFeeConfig), + Other: NewConfig(big.NewInt(3), admins, nil, func() *commontype.FeeConfig { c := validFeeConfig c.GasLimit = big.NewInt(123) return &c }()), - expected: false, + Expected: false, }, - { - name: "same config", - config: NewConfig(big.NewInt(3), admins, nil, &validFeeConfig), - other: NewConfig(big.NewInt(3), admins, nil, &validFeeConfig), - expected: true, + "same config": { + Config: NewConfig(big.NewInt(3), admins, nil, &validFeeConfig), + Other: NewConfig(big.NewInt(3), admins, nil, &validFeeConfig), + Expected: true, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) - - require.Equal(tt.expected, tt.config.Equal(tt.other)) - }) - } + allowlist.EqualPrecompileWithAllowListTests(t, Module, tests) } diff --git a/precompile/contracts/nativeminter/config_test.go b/precompile/contracts/nativeminter/config_test.go index 1927a93b9b..6f8754e493 100644 --- a/precompile/contracts/nativeminter/config_test.go +++ b/precompile/contracts/nativeminter/config_test.go @@ -7,47 +7,39 @@ import ( "math/big" "testing" + "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/ava-labs/subnet-evm/precompile/testutils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math" - "github.com/stretchr/testify/require" ) func TestVerifyContractNativeMinterConfig(t *testing.T) { admins := []common.Address{{1}} enableds := []common.Address{{2}} - tests := []struct { - name string - config precompileconfig.Config - ExpectedError string - }{ - { - name: "invalid allow list config in native minter allowlist", - config: NewConfig(big.NewInt(3), admins, admins, nil), + tests := map[string]testutils.ConfigVerifyTest{ + "invalid allow list config in native minter allowlist": { + Config: NewConfig(big.NewInt(3), admins, admins, nil), ExpectedError: "cannot set address", }, - { - name: "duplicate admins in config in native minter allowlist", - config: NewConfig(big.NewInt(3), append(admins, admins[0]), enableds, nil), + "duplicate admins in config in native minter allowlist": { + Config: NewConfig(big.NewInt(3), append(admins, admins[0]), enableds, nil), ExpectedError: "duplicate address", }, - { - name: "duplicate enableds in config in native minter allowlist", - config: NewConfig(big.NewInt(3), admins, append(enableds, enableds[0]), nil), + "duplicate enableds in config in native minter allowlist": { + Config: NewConfig(big.NewInt(3), admins, append(enableds, enableds[0]), nil), ExpectedError: "duplicate address", }, - { - name: "nil amount in native minter config", - config: NewConfig(big.NewInt(3), admins, nil, + "nil amount in native minter config": { + Config: NewConfig(big.NewInt(3), admins, nil, map[common.Address]*math.HexOrDecimal256{ common.HexToAddress("0x01"): math.NewHexOrDecimal256(123), common.HexToAddress("0x02"): nil, }), ExpectedError: "initial mint cannot contain nil", }, - { - name: "negative amount in native minter config", - config: NewConfig(big.NewInt(3), admins, nil, + "negative amount in native minter config": { + Config: NewConfig(big.NewInt(3), admins, nil, map[common.Address]*math.HexOrDecimal256{ common.HexToAddress("0x01"): math.NewHexOrDecimal256(123), common.HexToAddress("0x02"): math.NewHexOrDecimal256(-1), @@ -55,95 +47,61 @@ func TestVerifyContractNativeMinterConfig(t *testing.T) { ExpectedError: "initial mint cannot contain invalid amount", }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) - - err := tt.config.Verify() - if tt.ExpectedError == "" { - require.NoError(err) - } else { - require.ErrorContains(err, tt.ExpectedError) - } - }) - } + allowlist.VerifyPrecompileWithAllowListTests(t, Module, tests) } func TestEqualContractNativeMinterConfig(t *testing.T) { - admins := []common.Address{{1}} - enableds := []common.Address{{2}} - tests := []struct { - name string - config precompileconfig.Config - other precompileconfig.Config - expected bool - }{ - { - name: "non-nil config and nil other", - config: NewConfig(big.NewInt(3), admins, enableds, nil), - other: nil, - expected: false, + admins := []common.Address{allowlist.TestAdminAddr} + enableds := []common.Address{allowlist.TestEnabledAddr} + tests := map[string]testutils.ConfigEqualTest{ + "non-nil config and nil other": { + Config: NewConfig(big.NewInt(3), admins, enableds, nil), + Other: nil, + Expected: false, }, - { - name: "different type", - config: NewConfig(big.NewInt(3), admins, enableds, nil), - other: precompileconfig.NewNoopStatefulPrecompileConfig(), - expected: false, + "different type": { + Config: NewConfig(big.NewInt(3), admins, enableds, nil), + Other: precompileconfig.NewNoopStatefulPrecompileConfig(), + Expected: false, }, - { - name: "different timestamps", - config: NewConfig(big.NewInt(3), admins, nil, nil), - other: NewConfig(big.NewInt(4), admins, nil, nil), - expected: false, + "different timestamps": { + Config: NewConfig(big.NewInt(3), admins, nil, nil), + Other: NewConfig(big.NewInt(4), admins, nil, nil), + Expected: false, }, - { - name: "different enabled", - config: NewConfig(big.NewInt(3), admins, nil, nil), - other: NewConfig(big.NewInt(3), admins, enableds, nil), - expected: false, - }, - { - name: "different initial mint amounts", - config: NewConfig(big.NewInt(3), admins, nil, + "different initial mint amounts": { + Config: NewConfig(big.NewInt(3), admins, nil, map[common.Address]*math.HexOrDecimal256{ common.HexToAddress("0x01"): math.NewHexOrDecimal256(1), }), - other: NewConfig(big.NewInt(3), admins, nil, + Other: NewConfig(big.NewInt(3), admins, nil, map[common.Address]*math.HexOrDecimal256{ common.HexToAddress("0x01"): math.NewHexOrDecimal256(2), }), - expected: false, + Expected: false, }, - { - name: "different initial mint addresses", - config: NewConfig(big.NewInt(3), admins, nil, + "different initial mint addresses": { + Config: NewConfig(big.NewInt(3), admins, nil, map[common.Address]*math.HexOrDecimal256{ common.HexToAddress("0x01"): math.NewHexOrDecimal256(1), }), - other: NewConfig(big.NewInt(3), admins, nil, + Other: NewConfig(big.NewInt(3), admins, nil, map[common.Address]*math.HexOrDecimal256{ common.HexToAddress("0x02"): math.NewHexOrDecimal256(1), }), - expected: false, + Expected: false, }, - { - name: "same config", - config: NewConfig(big.NewInt(3), admins, nil, + "same config": { + Config: NewConfig(big.NewInt(3), admins, nil, map[common.Address]*math.HexOrDecimal256{ common.HexToAddress("0x01"): math.NewHexOrDecimal256(1), }), - other: NewConfig(big.NewInt(3), admins, nil, + Other: NewConfig(big.NewInt(3), admins, nil, map[common.Address]*math.HexOrDecimal256{ common.HexToAddress("0x01"): math.NewHexOrDecimal256(1), }), - expected: true, + Expected: true, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) - - require.Equal(tt.expected, tt.config.Equal(tt.other)) - }) - } + allowlist.EqualPrecompileWithAllowListTests(t, Module, tests) } diff --git a/precompile/contracts/rewardmanager/config_test.go b/precompile/contracts/rewardmanager/config_test.go index c78dec4c6f..2c3b3ab154 100644 --- a/precompile/contracts/rewardmanager/config_test.go +++ b/precompile/contracts/rewardmanager/config_test.go @@ -7,115 +7,72 @@ import ( "math/big" "testing" + "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/ava-labs/subnet-evm/precompile/testutils" "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" ) func TestVerifyRewardManagerConfig(t *testing.T) { admins := []common.Address{{1}} enableds := []common.Address{{2}} - tests := []struct { - name string - config precompileconfig.Config - ExpectedError string - }{ - { - name: "duplicate enableds in config in reward manager allowlist", - config: NewConfig(big.NewInt(3), admins, append(enableds, enableds[0]), nil), - ExpectedError: "duplicate address", - }, - { - name: "both reward mechanisms should not be activated at the same time in reward manager", - config: NewConfig(big.NewInt(3), admins, enableds, &InitialRewardConfig{ + tests := map[string]testutils.ConfigVerifyTest{ + "both reward mechanisms should not be activated at the same time in reward manager": { + Config: NewConfig(big.NewInt(3), admins, enableds, &InitialRewardConfig{ AllowFeeRecipients: true, RewardAddress: common.HexToAddress("0x01"), }), ExpectedError: ErrCannotEnableBothRewards.Error(), }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) - - err := tt.config.Verify() - if tt.ExpectedError == "" { - require.NoError(err) - } else { - require.ErrorContains(err, tt.ExpectedError) - } - }) - } + allowlist.VerifyPrecompileWithAllowListTests(t, Module, tests) } func TestEqualRewardManagerConfig(t *testing.T) { admins := []common.Address{{1}} enableds := []common.Address{{2}} - tests := []struct { - name string - config precompileconfig.Config - other precompileconfig.Config - expected bool - }{ - { - name: "non-nil config and nil other", - config: NewConfig(big.NewInt(3), admins, enableds, nil), - other: nil, - expected: false, + tests := map[string]testutils.ConfigEqualTest{ + "non-nil config and nil other": { + Config: NewConfig(big.NewInt(3), admins, enableds, nil), + Other: nil, + Expected: false, }, - { - name: "different type", - config: NewConfig(big.NewInt(3), admins, enableds, nil), - other: precompileconfig.NewNoopStatefulPrecompileConfig(), - expected: false, + "different type": { + Config: NewConfig(big.NewInt(3), admins, enableds, nil), + Other: precompileconfig.NewNoopStatefulPrecompileConfig(), + Expected: false, }, - { - name: "different timestamp", - config: NewConfig(big.NewInt(3), admins, nil, nil), - other: NewConfig(big.NewInt(4), admins, nil, nil), - expected: false, + "different timestamp": { + Config: NewConfig(big.NewInt(3), admins, nil, nil), + Other: NewConfig(big.NewInt(4), admins, nil, nil), + Expected: false, }, - { - name: "different enabled", - config: NewConfig(big.NewInt(3), admins, nil, nil), - other: NewConfig(big.NewInt(3), admins, enableds, nil), - expected: false, - }, - { - name: "non-nil initial config and nil initial config", - config: NewConfig(big.NewInt(3), admins, nil, &InitialRewardConfig{ + "non-nil initial config and nil initial config": { + Config: NewConfig(big.NewInt(3), admins, nil, &InitialRewardConfig{ AllowFeeRecipients: true, }), - other: NewConfig(big.NewInt(3), admins, nil, nil), - expected: false, + Other: NewConfig(big.NewInt(3), admins, nil, nil), + Expected: false, }, - { - name: "different initial config", - config: NewConfig(big.NewInt(3), admins, nil, &InitialRewardConfig{ + "different initial config": { + Config: NewConfig(big.NewInt(3), admins, nil, &InitialRewardConfig{ RewardAddress: common.HexToAddress("0x01"), }), - other: NewConfig(big.NewInt(3), admins, nil, + Other: NewConfig(big.NewInt(3), admins, nil, &InitialRewardConfig{ RewardAddress: common.HexToAddress("0x02"), }), - expected: false, + Expected: false, }, - { - name: "same config", - config: NewConfig(big.NewInt(3), admins, nil, &InitialRewardConfig{ + "same config": { + Config: NewConfig(big.NewInt(3), admins, nil, &InitialRewardConfig{ RewardAddress: common.HexToAddress("0x01"), }), - other: NewConfig(big.NewInt(3), admins, nil, &InitialRewardConfig{ + Other: NewConfig(big.NewInt(3), admins, nil, &InitialRewardConfig{ RewardAddress: common.HexToAddress("0x01"), }), - expected: true, + Expected: true, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) - - require.Equal(tt.expected, tt.config.Equal(tt.other)) - }) - } + allowlist.EqualPrecompileWithAllowListTests(t, Module, tests) } diff --git a/precompile/contracts/txallowlist/config_test.go b/precompile/contracts/txallowlist/config_test.go index 54ab46ac34..672db2501e 100644 --- a/precompile/contracts/txallowlist/config_test.go +++ b/precompile/contracts/txallowlist/config_test.go @@ -7,99 +7,40 @@ import ( "math/big" "testing" + "github.com/ava-labs/subnet-evm/precompile/allowlist" "github.com/ava-labs/subnet-evm/precompile/precompileconfig" + "github.com/ava-labs/subnet-evm/precompile/testutils" "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" ) func TestVerifyTxAllowlistConfig(t *testing.T) { - admins := []common.Address{{1}} - enableds := []common.Address{{2}} - tests := []struct { - name string - config precompileconfig.Config - ExpectedError string - }{ - { - name: "invalid allow list config in tx allowlist", - config: NewConfig(big.NewInt(3), admins, admins), - ExpectedError: "cannot set address", - }, - { - name: "nil member allow list config in tx allowlist", - config: NewConfig(big.NewInt(3), nil, nil), - ExpectedError: "", - }, - { - name: "empty member allow list config in tx allowlist", - config: NewConfig(big.NewInt(3), []common.Address{}, []common.Address{}), - ExpectedError: "", - }, - { - name: "valid allow list config in tx allowlist", - config: NewConfig(big.NewInt(3), admins, enableds), - ExpectedError: "", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) - - err := tt.config.Verify() - if tt.ExpectedError == "" { - require.NoError(err) - } else { - require.ErrorContains(err, tt.ExpectedError) - } - }) - } + allowlist.VerifyPrecompileWithAllowListTests(t, Module, nil) } func TestEqualTxAllowListConfig(t *testing.T) { - admins := []common.Address{{1}} - enableds := []common.Address{{2}} - tests := []struct { - name string - config precompileconfig.Config - other precompileconfig.Config - expected bool - }{ - { - name: "non-nil config and nil other", - config: NewConfig(big.NewInt(3), admins, enableds), - other: nil, - expected: false, + admins := []common.Address{allowlist.TestAdminAddr} + enableds := []common.Address{allowlist.TestEnabledAddr} + tests := map[string]testutils.ConfigEqualTest{ + "non-nil config and nil other": { + Config: NewConfig(big.NewInt(3), admins, enableds), + Other: nil, + Expected: false, + }, + "different type": { + Config: NewConfig(nil, nil, nil), + Other: precompileconfig.NewNoopStatefulPrecompileConfig(), + Expected: false, + }, + "different timestamp": { + Config: NewConfig(big.NewInt(3), admins, enableds), + Other: NewConfig(big.NewInt(4), admins, enableds), + Expected: false, + }, + "same config": { + Config: NewConfig(big.NewInt(3), admins, enableds), + Other: NewConfig(big.NewInt(3), admins, enableds), + Expected: true, }, - { - name: "different admin", - config: NewConfig(big.NewInt(3), admins, enableds), - other: NewConfig(big.NewInt(3), []common.Address{{3}}, enableds), - expected: false, - }, - { - name: "different enabled", - config: NewConfig(big.NewInt(3), admins, enableds), - other: NewConfig(big.NewInt(3), admins, []common.Address{{3}}), - expected: false, - }, - { - name: "different timestamp", - config: NewConfig(big.NewInt(3), admins, enableds), - other: NewConfig(big.NewInt(4), admins, enableds), - expected: false, - }, - { - name: "same config", - config: NewConfig(big.NewInt(3), admins, enableds), - other: NewConfig(big.NewInt(3), admins, enableds), - expected: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - require := require.New(t) - - require.Equal(tt.expected, tt.config.Equal(tt.other)) - }) } + allowlist.EqualPrecompileWithAllowListTests(t, Module, tests) } diff --git a/precompile/testutils/test_config.go b/precompile/testutils/test_config.go new file mode 100644 index 0000000000..ef0d656460 --- /dev/null +++ b/precompile/testutils/test_config.go @@ -0,0 +1,21 @@ +// (c) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package testutils + +import ( + "github.com/ava-labs/subnet-evm/precompile/precompileconfig" +) + +// ConfigVerifyTest is a test case for verifying a config +type ConfigVerifyTest struct { + Config precompileconfig.Config + ExpectedError string +} + +// ConfigEqualTest is a test case for comparing two configs +type ConfigEqualTest struct { + Config precompileconfig.Config + Other precompileconfig.Config + Expected bool +} From 241ddaea815364cff1f1cf243c044e2424f9909d Mon Sep 17 00:00:00 2001 From: aaronbuchwald Date: Tue, 4 Apr 2023 12:22:40 -0400 Subject: [PATCH 02/10] Rename local var validationTrieProcTime (#602) --- core/blockchain.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 16c0a43bfd..0e14ec8e76 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1356,9 +1356,9 @@ func (bc *BlockChain) insertBlock(block *types.Block, writes bool) error { storageUpdateTimer.Inc(statedb.StorageUpdates.Milliseconds()) // Storage updates are complete, we can mark them accountHashTimer.Inc(statedb.AccountHashes.Milliseconds()) // Account hashes are complete, we can mark them storageHashTimer.Inc(statedb.StorageHashes.Milliseconds()) // Storage hashes are complete, we can mark them - additionalTrieProc := statedb.AccountHashes + statedb.StorageHashes + statedb.AccountUpdates + statedb.StorageUpdates - trieproc - blockStateValidationTimer.Inc((time.Since(substart) - additionalTrieProc).Milliseconds()) - blockTrieOpsTimer.Inc((trieproc + additionalTrieProc).Milliseconds()) + validationTrieProcTime := statedb.AccountHashes + statedb.StorageHashes + statedb.AccountUpdates + statedb.StorageUpdates - trieproc + blockStateValidationTimer.Inc((time.Since(substart) - validationTrieProcTime).Milliseconds()) + blockTrieOpsTimer.Inc((trieproc + validationTrieProcTime).Milliseconds()) // If [writes] are disabled, skip [writeBlockWithState] so that we do not write the block // or the state trie to disk. From fcf241c54fef7f4eb5e7f07392ae5864a5d63b82 Mon Sep 17 00:00:00 2001 From: aaronbuchwald Date: Wed, 5 Apr 2023 11:19:07 -0400 Subject: [PATCH 03/10] goreleaser match all tags (#607) --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index eba62efd7f..88596af0be 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,7 @@ name: Release on: push: tags: - - 'v[0-9]+.[0-9]+.[0-9]+' + - '*' jobs: release: From b182d9e12b4182e66163fd6513bef6c8d6cd5d75 Mon Sep 17 00:00:00 2001 From: aaronbuchwald Date: Wed, 5 Apr 2023 11:19:38 -0400 Subject: [PATCH 04/10] Warp prep nits (#606) * Move verifyWithContext debug log to correct location * Disable warp API by default --- plugin/evm/block.go | 11 +++++------ plugin/evm/config.go | 2 -- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/plugin/evm/block.go b/plugin/evm/block.go index 3dec6e6c11..a510817e25 100644 --- a/plugin/evm/block.go +++ b/plugin/evm/block.go @@ -202,12 +202,6 @@ func (b *Block) ShouldVerifyWithContext(context.Context) (bool, error) { // VerifyWithContext implements the block.WithVerifyContext interface func (b *Block) VerifyWithContext(ctx context.Context, proposerVMBlockCtx *block.Context) error { - if proposerVMBlockCtx != nil { - log.Debug("Verifying block with context", "block", b.ID(), "height", b.Height()) - } else { - log.Debug("Verifying block without context", "block", b.ID(), "height", b.Height()) - } - return b.verify(&precompileconfig.ProposerPredicateContext{ PrecompilePredicateContext: precompileconfig.PrecompilePredicateContext{ SnowCtx: b.vm.ctx, @@ -220,6 +214,11 @@ func (b *Block) VerifyWithContext(ctx context.Context, proposerVMBlockCtx *block // Enforces that the predicates are valid within [predicateContext]. // Writes the block details to disk and the state to the trie manager iff writes=true. func (b *Block) verify(predicateContext *precompileconfig.ProposerPredicateContext, writes bool) error { + if predicateContext.ProposerVMBlockCtx != nil { + log.Debug("Verifying block with context", "block", b.ID(), "height", b.Height()) + } else { + log.Debug("Verifying block without context", "block", b.ID(), "height", b.Height()) + } if err := b.syntacticVerify(); err != nil { return fmt.Errorf("syntactic block verification failed: %w", err) } diff --git a/plugin/evm/config.go b/plugin/evm/config.go index 86cd6cf37a..6abaed1093 100644 --- a/plugin/evm/config.go +++ b/plugin/evm/config.go @@ -47,7 +47,6 @@ const ( defaultPopulateMissingTriesParallelism = 1024 defaultStateSyncServerTrieCache = 64 // MB defaultAcceptedCacheSize = 32 // blocks - defaultWarpAPIEnabled = true // defaultStateSyncMinBlocks is the minimum number of blocks the blockchain // should be ahead of local last accepted to perform state sync. @@ -225,7 +224,6 @@ func (c *Config) SetDefaults() { c.RPCGasCap = defaultRpcGasCap c.RPCTxFeeCap = defaultRpcTxFeeCap c.MetricsExpensiveEnabled = defaultMetricsExpensiveEnabled - c.WarpAPIEnabled = defaultWarpAPIEnabled c.TxPoolJournal = core.DefaultTxPoolConfig.Journal c.TxPoolRejournal = Duration{core.DefaultTxPoolConfig.Rejournal} From 56b073609de85b516807a88f5c91590255c770df Mon Sep 17 00:00:00 2001 From: aaronbuchwald Date: Thu, 6 Apr 2023 15:44:22 -0400 Subject: [PATCH 05/10] Add workflow dispatch for goreleaser and revert matching tags change (#608) --- .github/workflows/release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 88596af0be..ecd5f01f8a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,9 +1,10 @@ name: Release on: + workflow_dispatch: push: tags: - - '*' + - 'v[0-9]+.[0-9]+.[0-9]+' jobs: release: From 4e2eab7f3d22cfb636d0f2748c0f46118c7e5ac9 Mon Sep 17 00:00:00 2001 From: Ceyhun Onur Date: Fri, 7 Apr 2023 18:13:46 +0300 Subject: [PATCH 06/10] move runner and export it (#539) * move runner and export it * add version str --- plugin/main.go | 23 +++-------------------- plugin/{ => runner}/keys.go | 2 +- plugin/{ => runner}/params.go | 2 +- plugin/runner/runner.go | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 22 deletions(-) rename plugin/{ => runner}/keys.go (90%) rename plugin/{ => runner}/params.go (98%) create mode 100644 plugin/runner/runner.go diff --git a/plugin/main.go b/plugin/main.go index f0258adcfa..afdd416d2a 100644 --- a/plugin/main.go +++ b/plugin/main.go @@ -4,31 +4,14 @@ package main import ( - "context" "fmt" - "os" - "github.com/ava-labs/avalanchego/utils/logging" - "github.com/ava-labs/avalanchego/utils/ulimit" "github.com/ava-labs/avalanchego/version" - "github.com/ava-labs/avalanchego/vms/rpcchainvm" - "github.com/ava-labs/subnet-evm/plugin/evm" + "github.com/ava-labs/subnet-evm/plugin/runner" ) func main() { - printVersion, err := PrintVersion() - if err != nil { - fmt.Printf("couldn't get config: %s", err) - os.Exit(1) - } - if printVersion { - fmt.Printf("Subnet-EVM/%s [AvalancheGo=%s, rpcchainvm=%d]\n", evm.Version, version.Current, version.RPCChainVMProtocol) - os.Exit(0) - } - if err := ulimit.Set(ulimit.DefaultFDLimit, logging.NoLog{}); err != nil { - fmt.Printf("failed to set fd limit correctly due to: %s", err) - os.Exit(1) - } - rpcchainvm.Serve(context.Background(), &evm.VM{}) + versionString := fmt.Sprintf("Subnet-EVM/%s [AvalancheGo=%s, rpcchainvm=%d]", evm.Version, version.Current, version.RPCChainVMProtocol) + runner.Run(versionString) } diff --git a/plugin/keys.go b/plugin/runner/keys.go similarity index 90% rename from plugin/keys.go rename to plugin/runner/keys.go index 7cdbd5aa55..5302b4a4db 100644 --- a/plugin/keys.go +++ b/plugin/runner/keys.go @@ -1,7 +1,7 @@ // (c) 2019-2020, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package main +package runner const ( versionKey = "version" diff --git a/plugin/params.go b/plugin/runner/params.go similarity index 98% rename from plugin/params.go rename to plugin/runner/params.go index ab2d6bde4e..01a80f2c6a 100644 --- a/plugin/params.go +++ b/plugin/runner/params.go @@ -1,7 +1,7 @@ // (c) 2019-2020, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package main +package runner import ( "flag" diff --git a/plugin/runner/runner.go b/plugin/runner/runner.go new file mode 100644 index 0000000000..9b5b5efe29 --- /dev/null +++ b/plugin/runner/runner.go @@ -0,0 +1,33 @@ +// (c) 2019-2020, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package runner + +import ( + "context" + "fmt" + "os" + + "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/utils/ulimit" + "github.com/ava-labs/avalanchego/vms/rpcchainvm" + + "github.com/ava-labs/subnet-evm/plugin/evm" +) + +func Run(versionStr string) { + printVersion, err := PrintVersion() + if err != nil { + fmt.Printf("couldn't get config: %s", err) + os.Exit(1) + } + if printVersion && versionStr != "" { + fmt.Printf(versionStr) + os.Exit(0) + } + if err := ulimit.Set(ulimit.DefaultFDLimit, logging.NoLog{}); err != nil { + fmt.Printf("failed to set fd limit correctly due to: %s", err) + os.Exit(1) + } + rpcchainvm.Serve(context.Background(), &evm.VM{}) +} From a1865ccc3191f732272b12247602522d86bda6fa Mon Sep 17 00:00:00 2001 From: aaronbuchwald Date: Mon, 10 Apr 2023 13:34:25 -0400 Subject: [PATCH 07/10] Update log levels (#609) --- accounts/abi/bind/backends/simulated.go | 2 +- core/blockchain.go | 2 +- internal/ethapi/api.go | 4 ++-- internal/ethapi/transaction_args.go | 2 +- plugin/evm/message/cross_chain_handler.go | 8 ++++---- plugin/evm/syncervm_client.go | 2 +- plugin/evm/vm.go | 4 ++-- rpc/handler.go | 2 +- sync/handlers/block_request.go | 4 ++-- sync/handlers/code_request.go | 2 +- warp/handlers/signature_request.go | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index a74cf34d60..d71be6ca53 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -572,7 +572,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call interfaces.Call if transfer == nil { transfer = new(big.Int) } - log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance, + log.Info("Gas estimation capped by limited funds", "original", hi, "balance", balance, "sent", transfer, "feecap", feeCap, "fundable", allowance) hi = allowance.Uint64() } diff --git a/core/blockchain.go b/core/blockchain.go index 0e14ec8e76..e9dc0a98f2 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1508,7 +1508,7 @@ func (bc *BlockChain) reorg(oldBlock, newBlock *types.Block) error { logFn(msg, "number", commonBlock.Number(), "hash", commonBlock.Hash(), "drop", len(oldChain), "dropfrom", oldChain[0].Hash(), "add", len(newChain), "addfrom", newChain[0].Hash()) } else { - log.Warn("Unlikely preference change (rewind to ancestor) occurred", "oldnum", oldHead.Number(), "oldhash", oldHead.Hash(), "newnum", newHead.Number(), "newhash", newHead.Hash()) + log.Debug("Preference change (rewind to ancestor) occurred", "oldnum", oldHead.Number(), "oldhash", oldHead.Hash(), "newnum", newHead.Number(), "newhash", newHead.Hash()) } // Insert the new chain(except the head block(reverse order)), // taking care of the proper incremental order. diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 3083753aa9..3ea8b6ab52 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1162,14 +1162,14 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr if transfer == nil { transfer = new(hexutil.Big) } - log.Warn("Gas estimation capped by limited funds", "original", hi, "balance", balance, + log.Info("Gas estimation capped by limited funds", "original", hi, "balance", balance, "sent", transfer.ToInt(), "maxFeePerGas", feeCap, "fundable", allowance) hi = allowance.Uint64() } } // Recap the highest gas allowance with specified gascap. if gasCap != 0 && hi > gasCap { - log.Warn("Caller gas above allowance, capping", "requested", hi, "cap", gasCap) + log.Info("Caller gas above allowance, capping", "requested", hi, "cap", gasCap) hi = gasCap } cap = hi diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 6cff3a1d08..37e50f676e 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -235,7 +235,7 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t gas = uint64(*args.Gas) } if globalGasCap != 0 && globalGasCap < gas { - log.Warn("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap) + log.Info("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap) gas = globalGasCap } var ( diff --git a/plugin/evm/message/cross_chain_handler.go b/plugin/evm/message/cross_chain_handler.go index f356684ee3..f470e576fd 100644 --- a/plugin/evm/message/cross_chain_handler.go +++ b/plugin/evm/message/cross_chain_handler.go @@ -43,19 +43,19 @@ func (c *crossChainHandler) HandleEthCallRequest(ctx context.Context, requesting transactionArgs := ethapi.TransactionArgs{} err := json.Unmarshal(ethCallRequest.RequestArgs, &transactionArgs) if err != nil { - log.Debug("error occurred with JSON unmarshalling ethCallRequest.RequestArgs", "err", err) + log.Error("error occurred with JSON unmarshalling ethCallRequest.RequestArgs", "err", err) return nil, nil } result, err := ethapi.DoCall(ctx, c.backend, transactionArgs, lastAcceptedBlockNumberOrHash, nil, c.backend.RPCEVMTimeout(), c.backend.RPCGasCap()) if err != nil { - log.Debug("error occurred with EthCall", "err", err, "transactionArgs", ethCallRequest.RequestArgs, "blockNumberOrHash", lastAcceptedBlockNumberOrHash) + log.Error("error occurred with EthCall", "err", err, "transactionArgs", ethCallRequest.RequestArgs, "blockNumberOrHash", lastAcceptedBlockNumberOrHash) return nil, nil } executionResult, err := json.Marshal(&result) if err != nil { - log.Debug("error occurred with JSON marshalling result", "err", err) + log.Error("error occurred with JSON marshalling result", "err", err) return nil, nil } @@ -65,7 +65,7 @@ func (c *crossChainHandler) HandleEthCallRequest(ctx context.Context, requesting responseBytes, err := c.crossChainCodec.Marshal(Version, response) if err != nil { - log.Warn("error occurred with marshalling EthCallResponse", "err", err, "EthCallResponse", response) + log.Error("error occurred with marshalling EthCallResponse", "err", err, "EthCallResponse", response) return nil, nil } diff --git a/plugin/evm/syncervm_client.go b/plugin/evm/syncervm_client.go index bf185900c0..caa3682d77 100644 --- a/plugin/evm/syncervm_client.go +++ b/plugin/evm/syncervm_client.go @@ -257,7 +257,7 @@ func (client *stateSyncerClient) syncBlocks(ctx context.Context, fromHash common } blocks, err := client.client.GetBlocks(ctx, nextHash, nextHeight, parentsPerRequest) if err != nil { - log.Warn("could not get blocks from peer", "err", err, "nextHash", nextHash, "remaining", i+1) + log.Error("could not get blocks from peer", "err", err, "nextHash", nextHash, "remaining", i+1) return err } for _, block := range blocks { diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index a37d7824f8..1f979b0181 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -304,7 +304,7 @@ func (vm *VM) Initialize( vm.syntacticBlockValidator = NewBlockValidator() if g.Config.FeeConfig == commontype.EmptyFeeConfig { - log.Warn("No fee config given in genesis, setting default fee config", "DefaultFeeConfig", params.DefaultFeeConfig) + log.Info("No fee config given in genesis, setting default fee config", "DefaultFeeConfig", params.DefaultFeeConfig) g.Config.FeeConfig = params.DefaultFeeConfig } @@ -369,7 +369,7 @@ func (vm *VM) Initialize( log.Info("Setting fee recipient", "address", address) vm.ethConfig.Miner.Etherbase = address } else { - log.Warn("Config has not specified any coinbase address. Defaulting to the blackhole address.") + log.Info("Config has not specified any coinbase address. Defaulting to the blackhole address.") vm.ethConfig.Miner.Etherbase = constants.BlackholeAddr } diff --git a/rpc/handler.go b/rpc/handler.go index abc4dae504..fec952f92a 100644 --- a/rpc/handler.go +++ b/rpc/handler.go @@ -400,7 +400,7 @@ func (h *handler) handleCallMsg(ctx *callProc, msg *jsonrpcMessage) *jsonrpcMess if resp.Error.Data != nil { ctx = append(ctx, "errdata", resp.Error.Data) } - h.log.Warn("Served "+msg.Method, ctx...) + h.log.Info("Served "+msg.Method, ctx...) } else { h.log.Debug("Served "+msg.Method, ctx...) } diff --git a/sync/handlers/block_request.go b/sync/handlers/block_request.go index 59577d8e73..76203b78bc 100644 --- a/sync/handlers/block_request.go +++ b/sync/handlers/block_request.go @@ -80,7 +80,7 @@ func (b *BlockRequestHandler) OnBlockRequest(ctx context.Context, nodeID ids.Nod buf := new(bytes.Buffer) if err := block.EncodeRLP(buf); err != nil { - log.Warn("failed to RLP encode block", "hash", block.Hash(), "height", block.NumberU64(), "err", err) + log.Error("failed to RLP encode block", "hash", block.Hash(), "height", block.NumberU64(), "err", err) return nil, nil } @@ -100,7 +100,7 @@ func (b *BlockRequestHandler) OnBlockRequest(ctx context.Context, nodeID ids.Nod } responseBytes, err := b.codec.Marshal(message.Version, response) if err != nil { - log.Warn("failed to marshal BlockResponse, dropping request", "nodeID", nodeID, "requestID", requestID, "hash", blockRequest.Hash, "parents", blockRequest.Parents, "blocksLen", len(response.Blocks), "err", err) + log.Error("failed to marshal BlockResponse, dropping request", "nodeID", nodeID, "requestID", requestID, "hash", blockRequest.Hash, "parents", blockRequest.Parents, "blocksLen", len(response.Blocks), "err", err) return nil, nil } diff --git a/sync/handlers/code_request.go b/sync/handlers/code_request.go index ba45a7bbb7..08162b85af 100644 --- a/sync/handlers/code_request.go +++ b/sync/handlers/code_request.go @@ -75,7 +75,7 @@ func (n *CodeRequestHandler) OnCodeRequest(_ context.Context, nodeID ids.NodeID, codeResponse := message.CodeResponse{Data: codeBytes} responseBytes, err := n.codec.Marshal(message.Version, codeResponse) if err != nil { - log.Warn("could not marshal CodeResponse, dropping request", "nodeID", nodeID, "requestID", requestID, "request", codeRequest, "err", err) + log.Error("could not marshal CodeResponse, dropping request", "nodeID", nodeID, "requestID", requestID, "request", codeRequest, "err", err) return nil, nil } n.stats.UpdateCodeBytesReturned(uint32(totalBytes)) diff --git a/warp/handlers/signature_request.go b/warp/handlers/signature_request.go index a0198509fa..992adc07f0 100644 --- a/warp/handlers/signature_request.go +++ b/warp/handlers/signature_request.go @@ -61,7 +61,7 @@ func (s *signatureRequestHandler) OnSignatureRequest(ctx context.Context, nodeID response := message.SignatureResponse{Signature: signature} responseBytes, err := s.codec.Marshal(message.Version, &response) if err != nil { - log.Warn("could not marshal SignatureResponse, dropping request", "nodeID", nodeID, "requestID", requestID, "err", err) + log.Error("could not marshal SignatureResponse, dropping request", "nodeID", nodeID, "requestID", requestID, "err", err) return nil, nil } From e4aa8377b565fc8796669b660c2206062b0808d4 Mon Sep 17 00:00:00 2001 From: aaronbuchwald Date: Tue, 11 Apr 2023 13:48:27 -0400 Subject: [PATCH 08/10] Bench precompile (#610) * Add stateful precompile benchmarks * Add GH Action for bench precompiles * Remove coverage from benchmarks * Rename bench workflow --- .github/workflows/bench.yml | 19 ++ core/state/test_statedb.go | 2 +- precompile/allowlist/allowlist_test.go | 9 + precompile/allowlist/test_allowlist.go | 57 +++-- precompile/contract/interfaces.go | 3 + .../deployerallowlist/contract_test.go | 4 + .../contracts/feemanager/contract_test.go | 77 +++--- .../contracts/nativeminter/contract_test.go | 224 +++++++++--------- .../contracts/rewardmanager/contract_test.go | 71 +++--- .../contracts/txallowlist/contract_test.go | 4 + precompile/testutils/test_precompile.go | 113 ++++++++- scripts/build_bench_precompiles.sh | 19 ++ 12 files changed, 396 insertions(+), 206 deletions(-) create mode 100644 .github/workflows/bench.yml create mode 100755 scripts/build_bench_precompiles.sh diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml new file mode 100644 index 0000000000..a2c5614b50 --- /dev/null +++ b/.github/workflows/bench.yml @@ -0,0 +1,19 @@ +name: Bench + +on: + workflow_dispatch: + pull_request: + +jobs: + bench: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-go@v3 + with: + go-version: "1.19" + - run: go mod download + shell: bash + - run: ./scripts/build_bench_precompiles.sh + shell: bash + diff --git a/core/state/test_statedb.go b/core/state/test_statedb.go index 6dc1aa1065..9aa5bb092e 100644 --- a/core/state/test_statedb.go +++ b/core/state/test_statedb.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" ) -func NewTestStateDB(t *testing.T) contract.StateDB { +func NewTestStateDB(t testing.TB) contract.StateDB { db := memorydb.New() stateDB, err := New(common.Hash{}, NewDatabase(db), nil) require.NoError(t, err) diff --git a/precompile/allowlist/allowlist_test.go b/precompile/allowlist/allowlist_test.go index 4f0eeb3b51..5ae172a06a 100644 --- a/precompile/allowlist/allowlist_test.go +++ b/precompile/allowlist/allowlist_test.go @@ -60,3 +60,12 @@ func TestAllowListRun(t *testing.T) { } RunPrecompileWithAllowListTests(t, dummyModule, state.NewTestStateDB, nil) } + +func BenchmarkAllowList(b *testing.B) { + dummyModule := modules.Module{ + Address: dummyAddr, + Contract: CreateAllowListPrecompile(dummyAddr), + Configurator: &dummyConfigurator{}, + } + BenchPrecompileWithAllowList(b, dummyModule, state.NewTestStateDB, nil) +} diff --git a/precompile/allowlist/test_allowlist.go b/precompile/allowlist/test_allowlist.go index 233ade3f65..8012d2e95c 100644 --- a/precompile/allowlist/test_allowlist.go +++ b/precompile/allowlist/test_allowlist.go @@ -26,7 +26,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { "set admin": { Caller: TestAdminAddr, BeforeHook: SetDefaultRoles(contractAddress), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackModifyAllowList(TestNoRoleAddr, AdminRole) require.NoError(t, err) @@ -35,7 +35,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { SuppliedGas: ModifyAllowListGasCost, ReadOnly: false, ExpectedRes: []byte{}, - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { res := GetAllowListStatus(state, contractAddress, TestNoRoleAddr) require.Equal(t, AdminRole, res) }, @@ -43,7 +43,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { "set enabled": { Caller: TestAdminAddr, BeforeHook: SetDefaultRoles(contractAddress), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackModifyAllowList(TestNoRoleAddr, EnabledRole) require.NoError(t, err) @@ -52,7 +52,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { SuppliedGas: ModifyAllowListGasCost, ReadOnly: false, ExpectedRes: []byte{}, - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { res := GetAllowListStatus(state, contractAddress, TestNoRoleAddr) require.Equal(t, EnabledRole, res) }, @@ -60,7 +60,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { "set no role": { Caller: TestAdminAddr, BeforeHook: SetDefaultRoles(contractAddress), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackModifyAllowList(TestEnabledAddr, NoRole) require.NoError(t, err) @@ -69,7 +69,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { SuppliedGas: ModifyAllowListGasCost, ReadOnly: false, ExpectedRes: []byte{}, - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { res := GetAllowListStatus(state, contractAddress, TestEnabledAddr) require.Equal(t, NoRole, res) }, @@ -77,7 +77,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { "set no role from no role": { Caller: TestNoRoleAddr, BeforeHook: SetDefaultRoles(contractAddress), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackModifyAllowList(TestEnabledAddr, NoRole) require.NoError(t, err) @@ -90,7 +90,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { "set enabled from no role": { Caller: TestNoRoleAddr, BeforeHook: SetDefaultRoles(contractAddress), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackModifyAllowList(TestNoRoleAddr, EnabledRole) require.NoError(t, err) @@ -103,7 +103,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { "set admin from no role": { Caller: TestNoRoleAddr, BeforeHook: SetDefaultRoles(contractAddress), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackModifyAllowList(TestEnabledAddr, AdminRole) require.NoError(t, err) @@ -116,7 +116,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { "set no role from enabled": { Caller: TestEnabledAddr, BeforeHook: SetDefaultRoles(contractAddress), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackModifyAllowList(TestAdminAddr, NoRole) require.NoError(t, err) @@ -129,7 +129,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { "set enabled from enabled": { Caller: TestEnabledAddr, BeforeHook: SetDefaultRoles(contractAddress), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackModifyAllowList(TestNoRoleAddr, EnabledRole) require.NoError(t, err) @@ -142,7 +142,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { "set admin from enabled": { Caller: TestEnabledAddr, BeforeHook: SetDefaultRoles(contractAddress), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackModifyAllowList(TestNoRoleAddr, AdminRole) require.NoError(t, err) @@ -155,7 +155,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { "set no role with readOnly enabled": { Caller: TestAdminAddr, BeforeHook: SetDefaultRoles(contractAddress), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackModifyAllowList(TestEnabledAddr, NoRole) require.NoError(t, err) @@ -168,7 +168,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { "set no role insufficient gas": { Caller: TestAdminAddr, BeforeHook: SetDefaultRoles(contractAddress), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackModifyAllowList(TestEnabledAddr, NoRole) require.NoError(t, err) @@ -219,7 +219,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { ), SuppliedGas: 0, ReadOnly: false, - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { require.Equal(t, AdminRole, GetAllowListStatus(state, contractAddress, TestNoRoleAddr)) require.Equal(t, AdminRole, GetAllowListStatus(state, contractAddress, TestEnabledAddr)) }, @@ -233,7 +233,7 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { ), SuppliedGas: 0, ReadOnly: false, - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { require.Equal(t, EnabledRole, GetAllowListStatus(state, contractAddress, TestAdminAddr)) require.Equal(t, EnabledRole, GetAllowListStatus(state, contractAddress, TestNoRoleAddr)) }, @@ -243,8 +243,8 @@ func AllowListTests(module modules.Module) map[string]testutils.PrecompileTest { // SetDefaultRoles returns a BeforeHook that sets roles TestAdminAddr and TestEnabledAddr // to have the AdminRole and EnabledRole respectively. -func SetDefaultRoles(contractAddress common.Address) func(t *testing.T, state contract.StateDB) { - return func(t *testing.T, state contract.StateDB) { +func SetDefaultRoles(contractAddress common.Address) func(t testing.TB, state contract.StateDB) { + return func(t testing.TB, state contract.StateDB) { SetAllowListRole(state, contractAddress, TestAdminAddr, AdminRole) SetAllowListRole(state, contractAddress, TestEnabledAddr, EnabledRole) require.Equal(t, AdminRole, GetAllowListStatus(state, contractAddress, TestAdminAddr)) @@ -253,7 +253,7 @@ func SetDefaultRoles(contractAddress common.Address) func(t *testing.T, state co } } -func RunPrecompileWithAllowListTests(t *testing.T, module modules.Module, newStateDB func(t *testing.T) contract.StateDB, contractTests map[string]testutils.PrecompileTest) { +func RunPrecompileWithAllowListTests(t *testing.T, module modules.Module, newStateDB func(t testing.TB) contract.StateDB, contractTests map[string]testutils.PrecompileTest) { t.Helper() tests := AllowListTests(module) // Add the contract specific tests to the map of tests to run. @@ -270,3 +270,22 @@ func RunPrecompileWithAllowListTests(t *testing.T, module modules.Module, newSta }) } } + +func BenchPrecompileWithAllowList(b *testing.B, module modules.Module, newStateDB func(t testing.TB) contract.StateDB, contractTests map[string]testutils.PrecompileTest) { + b.Helper() + + tests := AllowListTests(module) + // Add the contract specific tests to the map of tests to run. + for name, test := range contractTests { + if _, exists := tests[name]; exists { + b.Fatalf("duplicate bench name: %s", name) + } + tests[name] = test + } + + for name, test := range tests { + b.Run(name, func(b *testing.B) { + test.Bench(b, module, newStateDB(b)) + }) + } +} diff --git a/precompile/contract/interfaces.go b/precompile/contract/interfaces.go index e36df7aefa..0432c939b6 100644 --- a/precompile/contract/interfaces.go +++ b/precompile/contract/interfaces.go @@ -48,6 +48,9 @@ type StateDB interface { Suicide(common.Address) bool Finalise(deleteEmptyObjects bool) + + Snapshot() int + RevertToSnapshot(int) } // AccessibleState defines the interface exposed to stateful precompile contracts diff --git a/precompile/contracts/deployerallowlist/contract_test.go b/precompile/contracts/deployerallowlist/contract_test.go index ba144fd155..d5037444a5 100644 --- a/precompile/contracts/deployerallowlist/contract_test.go +++ b/precompile/contracts/deployerallowlist/contract_test.go @@ -13,3 +13,7 @@ import ( func TestContractDeployerAllowListRun(t *testing.T) { allowlist.RunPrecompileWithAllowListTests(t, Module, state.NewTestStateDB, nil) } + +func BenchmarkContractDeployerAllowList(b *testing.B) { + allowlist.BenchPrecompileWithAllowList(b, Module, state.NewTestStateDB, nil) +} diff --git a/precompile/contracts/feemanager/contract_test.go b/precompile/contracts/feemanager/contract_test.go index 4911a2368e..6daa21935d 100644 --- a/precompile/contracts/feemanager/contract_test.go +++ b/precompile/contracts/feemanager/contract_test.go @@ -17,26 +17,25 @@ import ( "github.com/stretchr/testify/require" ) -var testFeeConfig = 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), -} - -func TestFeeManager(t *testing.T) { - testBlockNumber := big.NewInt(7) - tests := map[string]testutils.PrecompileTest{ +var ( + testFeeConfig = 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), + } + testBlockNumber = big.NewInt(7) + tests = map[string]testutils.PrecompileTest{ "set config from no role fails": { Caller: allowlist.TestNoRoleAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackSetFeeConfig(testFeeConfig) require.NoError(t, err) @@ -49,7 +48,7 @@ func TestFeeManager(t *testing.T) { "set config from enabled address": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackSetFeeConfig(testFeeConfig) require.NoError(t, err) @@ -58,7 +57,7 @@ func TestFeeManager(t *testing.T) { SuppliedGas: SetFeeConfigGasCost, ReadOnly: false, ExpectedRes: []byte{}, - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { feeConfig := GetStoredFeeConfig(state) require.Equal(t, testFeeConfig, feeConfig) }, @@ -66,7 +65,7 @@ func TestFeeManager(t *testing.T) { "set invalid config from enabled address": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { feeConfig := testFeeConfig feeConfig.MinBlockGasCost = new(big.Int).Mul(feeConfig.MaxBlockGasCost, common.Big2) input, err := PackSetFeeConfig(feeConfig) @@ -80,7 +79,7 @@ func TestFeeManager(t *testing.T) { InitialFeeConfig: &testFeeConfig, }, ExpectedErr: "cannot be greater than maxBlockGasCost", - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { feeConfig := GetStoredFeeConfig(state) require.Equal(t, testFeeConfig, feeConfig) }, @@ -88,7 +87,7 @@ func TestFeeManager(t *testing.T) { "set config from admin address": { Caller: allowlist.TestAdminAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackSetFeeConfig(testFeeConfig) require.NoError(t, err) @@ -98,7 +97,7 @@ func TestFeeManager(t *testing.T) { ReadOnly: false, ExpectedRes: []byte{}, BlockNumber: testBlockNumber.Int64(), - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { feeConfig := GetStoredFeeConfig(state) require.Equal(t, testFeeConfig, feeConfig) lastChangedAt := GetFeeConfigLastChangedAt(state) @@ -107,7 +106,7 @@ func TestFeeManager(t *testing.T) { }, "get fee config from non-enabled address": { Caller: allowlist.TestNoRoleAddr, - BeforeHook: func(t *testing.T, state contract.StateDB) { + BeforeHook: func(t testing.TB, state contract.StateDB) { allowlist.SetDefaultRoles(Module.Address)(t, state) err := StoreFeeConfig(state, testFeeConfig, contract.NewMockBlockContext(big.NewInt(6), 0)) require.NoError(t, err) @@ -117,10 +116,12 @@ func TestFeeManager(t *testing.T) { ReadOnly: true, ExpectedRes: func() []byte { res, err := PackFeeConfig(testFeeConfig) - require.NoError(t, err) + if err != nil { + panic(err) + } return res }(), - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { feeConfig := GetStoredFeeConfig(state) lastChangedAt := GetFeeConfigLastChangedAt(state) require.Equal(t, testFeeConfig, feeConfig) @@ -138,11 +139,13 @@ func TestFeeManager(t *testing.T) { ReadOnly: true, ExpectedRes: func() []byte { res, err := PackFeeConfig(testFeeConfig) - require.NoError(t, err) + if err != nil { + panic(err) + } return res }(), BlockNumber: testBlockNumber.Int64(), - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { feeConfig := GetStoredFeeConfig(state) lastChangedAt := GetFeeConfigLastChangedAt(state) require.Equal(t, testFeeConfig, feeConfig) @@ -151,7 +154,7 @@ func TestFeeManager(t *testing.T) { }, "get last changed at from non-enabled address": { Caller: allowlist.TestNoRoleAddr, - BeforeHook: func(t *testing.T, state contract.StateDB) { + BeforeHook: func(t testing.TB, state contract.StateDB) { allowlist.SetDefaultRoles(Module.Address)(t, state) err := StoreFeeConfig(state, testFeeConfig, contract.NewMockBlockContext(testBlockNumber, 0)) require.NoError(t, err) @@ -160,7 +163,7 @@ func TestFeeManager(t *testing.T) { SuppliedGas: GetLastChangedAtGasCost, ReadOnly: true, ExpectedRes: common.BigToHash(testBlockNumber).Bytes(), - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { feeConfig := GetStoredFeeConfig(state) lastChangedAt := GetFeeConfigLastChangedAt(state) require.Equal(t, testFeeConfig, feeConfig) @@ -170,7 +173,7 @@ func TestFeeManager(t *testing.T) { "readOnly setFeeConfig with noRole fails": { Caller: allowlist.TestNoRoleAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackSetFeeConfig(testFeeConfig) require.NoError(t, err) @@ -183,7 +186,7 @@ func TestFeeManager(t *testing.T) { "readOnly setFeeConfig with allow role fails": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackSetFeeConfig(testFeeConfig) require.NoError(t, err) @@ -196,7 +199,7 @@ func TestFeeManager(t *testing.T) { "readOnly setFeeConfig with admin role fails": { Caller: allowlist.TestAdminAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackSetFeeConfig(testFeeConfig) require.NoError(t, err) @@ -209,7 +212,7 @@ func TestFeeManager(t *testing.T) { "insufficient gas setFeeConfig from admin": { Caller: allowlist.TestAdminAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackSetFeeConfig(testFeeConfig) require.NoError(t, err) @@ -220,6 +223,12 @@ func TestFeeManager(t *testing.T) { ExpectedErr: vmerrs.ErrOutOfGas.Error(), }, } +) +func TestFeeManager(t *testing.T) { allowlist.RunPrecompileWithAllowListTests(t, Module, state.NewTestStateDB, tests) } + +func BenchmarkFeeManager(b *testing.B) { + allowlist.BenchPrecompileWithAllowList(b, Module, state.NewTestStateDB, tests) +} diff --git a/precompile/contracts/nativeminter/contract_test.go b/precompile/contracts/nativeminter/contract_test.go index a987dc9998..a45f26dc2c 100644 --- a/precompile/contracts/nativeminter/contract_test.go +++ b/precompile/contracts/nativeminter/contract_test.go @@ -16,134 +16,138 @@ import ( "github.com/stretchr/testify/require" ) -func TestContractNativeMinterRun(t *testing.T) { - tests := map[string]testutils.PrecompileTest{ - "mint funds from no role fails": { - Caller: allowlist.TestNoRoleAddr, - BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { - input, err := PackMintInput(allowlist.TestNoRoleAddr, common.Big1) - require.NoError(t, err) +var tests = map[string]testutils.PrecompileTest{ + "mint funds from no role fails": { + Caller: allowlist.TestNoRoleAddr, + BeforeHook: allowlist.SetDefaultRoles(Module.Address), + InputFn: func(t testing.TB) []byte { + input, err := PackMintInput(allowlist.TestNoRoleAddr, common.Big1) + require.NoError(t, err) - return input - }, - SuppliedGas: MintGasCost, - ReadOnly: false, - ExpectedErr: ErrCannotMint.Error(), + return input }, - "mint funds from enabled address": { - Caller: allowlist.TestEnabledAddr, - BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { - input, err := PackMintInput(allowlist.TestEnabledAddr, common.Big1) - require.NoError(t, err) + SuppliedGas: MintGasCost, + ReadOnly: false, + ExpectedErr: ErrCannotMint.Error(), + }, + "mint funds from enabled address": { + Caller: allowlist.TestEnabledAddr, + BeforeHook: allowlist.SetDefaultRoles(Module.Address), + InputFn: func(t testing.TB) []byte { + input, err := PackMintInput(allowlist.TestEnabledAddr, common.Big1) + require.NoError(t, err) - return input - }, - SuppliedGas: MintGasCost, - ReadOnly: false, - ExpectedRes: []byte{}, - AfterHook: func(t *testing.T, state contract.StateDB) { - require.Equal(t, common.Big1, state.GetBalance(allowlist.TestEnabledAddr), "expected minted funds") - }, + return input }, - "initial mint funds": { - Caller: allowlist.TestEnabledAddr, - BeforeHook: allowlist.SetDefaultRoles(Module.Address), - Config: &Config{ - InitialMint: map[common.Address]*math.HexOrDecimal256{ - allowlist.TestEnabledAddr: math.NewHexOrDecimal256(2), - }, - }, - AfterHook: func(t *testing.T, state contract.StateDB) { - require.Equal(t, common.Big2, state.GetBalance(allowlist.TestEnabledAddr), "expected minted funds") + SuppliedGas: MintGasCost, + ReadOnly: false, + ExpectedRes: []byte{}, + AfterHook: func(t testing.TB, state contract.StateDB) { + require.Equal(t, common.Big1, state.GetBalance(allowlist.TestEnabledAddr), "expected minted funds") + }, + }, + "initial mint funds": { + Caller: allowlist.TestEnabledAddr, + BeforeHook: allowlist.SetDefaultRoles(Module.Address), + Config: &Config{ + InitialMint: map[common.Address]*math.HexOrDecimal256{ + allowlist.TestEnabledAddr: math.NewHexOrDecimal256(2), }, }, - "mint funds from admin address": { - Caller: allowlist.TestAdminAddr, - BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { - input, err := PackMintInput(allowlist.TestAdminAddr, common.Big1) - require.NoError(t, err) + AfterHook: func(t testing.TB, state contract.StateDB) { + require.Equal(t, common.Big2, state.GetBalance(allowlist.TestEnabledAddr), "expected minted funds") + }, + }, + "mint funds from admin address": { + Caller: allowlist.TestAdminAddr, + BeforeHook: allowlist.SetDefaultRoles(Module.Address), + InputFn: func(t testing.TB) []byte { + input, err := PackMintInput(allowlist.TestAdminAddr, common.Big1) + require.NoError(t, err) - return input - }, - SuppliedGas: MintGasCost, - ReadOnly: false, - ExpectedRes: []byte{}, - AfterHook: func(t *testing.T, state contract.StateDB) { - require.Equal(t, common.Big1, state.GetBalance(allowlist.TestAdminAddr), "expected minted funds") - }, + return input }, - "mint max big funds": { - Caller: allowlist.TestAdminAddr, - BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { - input, err := PackMintInput(allowlist.TestAdminAddr, math.MaxBig256) - require.NoError(t, err) + SuppliedGas: MintGasCost, + ReadOnly: false, + ExpectedRes: []byte{}, + AfterHook: func(t testing.TB, state contract.StateDB) { + require.Equal(t, common.Big1, state.GetBalance(allowlist.TestAdminAddr), "expected minted funds") + }, + }, + "mint max big funds": { + Caller: allowlist.TestAdminAddr, + BeforeHook: allowlist.SetDefaultRoles(Module.Address), + InputFn: func(t testing.TB) []byte { + input, err := PackMintInput(allowlist.TestAdminAddr, math.MaxBig256) + require.NoError(t, err) - return input - }, - SuppliedGas: MintGasCost, - ReadOnly: false, - ExpectedRes: []byte{}, - AfterHook: func(t *testing.T, state contract.StateDB) { - require.Equal(t, math.MaxBig256, state.GetBalance(allowlist.TestAdminAddr), "expected minted funds") - }, + return input + }, + SuppliedGas: MintGasCost, + ReadOnly: false, + ExpectedRes: []byte{}, + AfterHook: func(t testing.TB, state contract.StateDB) { + require.Equal(t, math.MaxBig256, state.GetBalance(allowlist.TestAdminAddr), "expected minted funds") }, - "readOnly mint with noRole fails": { - Caller: allowlist.TestNoRoleAddr, - BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { - input, err := PackMintInput(allowlist.TestAdminAddr, common.Big1) - require.NoError(t, err) + }, + "readOnly mint with noRole fails": { + Caller: allowlist.TestNoRoleAddr, + BeforeHook: allowlist.SetDefaultRoles(Module.Address), + InputFn: func(t testing.TB) []byte { + input, err := PackMintInput(allowlist.TestAdminAddr, common.Big1) + require.NoError(t, err) - return input - }, - SuppliedGas: MintGasCost, - ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + return input }, - "readOnly mint with allow role fails": { - Caller: allowlist.TestEnabledAddr, - BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { - input, err := PackMintInput(allowlist.TestEnabledAddr, common.Big1) - require.NoError(t, err) + SuppliedGas: MintGasCost, + ReadOnly: true, + ExpectedErr: vmerrs.ErrWriteProtection.Error(), + }, + "readOnly mint with allow role fails": { + Caller: allowlist.TestEnabledAddr, + BeforeHook: allowlist.SetDefaultRoles(Module.Address), + InputFn: func(t testing.TB) []byte { + input, err := PackMintInput(allowlist.TestEnabledAddr, common.Big1) + require.NoError(t, err) - return input - }, - SuppliedGas: MintGasCost, - ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + return input }, - "readOnly mint with admin role fails": { - Caller: allowlist.TestAdminAddr, - BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { - input, err := PackMintInput(allowlist.TestAdminAddr, common.Big1) - require.NoError(t, err) + SuppliedGas: MintGasCost, + ReadOnly: true, + ExpectedErr: vmerrs.ErrWriteProtection.Error(), + }, + "readOnly mint with admin role fails": { + Caller: allowlist.TestAdminAddr, + BeforeHook: allowlist.SetDefaultRoles(Module.Address), + InputFn: func(t testing.TB) []byte { + input, err := PackMintInput(allowlist.TestAdminAddr, common.Big1) + require.NoError(t, err) - return input - }, - SuppliedGas: MintGasCost, - ReadOnly: true, - ExpectedErr: vmerrs.ErrWriteProtection.Error(), + return input }, - "insufficient gas mint from admin": { - Caller: allowlist.TestAdminAddr, - BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { - input, err := PackMintInput(allowlist.TestEnabledAddr, common.Big1) - require.NoError(t, err) + SuppliedGas: MintGasCost, + ReadOnly: true, + ExpectedErr: vmerrs.ErrWriteProtection.Error(), + }, + "insufficient gas mint from admin": { + Caller: allowlist.TestAdminAddr, + BeforeHook: allowlist.SetDefaultRoles(Module.Address), + InputFn: func(t testing.TB) []byte { + input, err := PackMintInput(allowlist.TestEnabledAddr, common.Big1) + require.NoError(t, err) - return input - }, - SuppliedGas: MintGasCost - 1, - ReadOnly: false, - ExpectedErr: vmerrs.ErrOutOfGas.Error(), + return input }, - } + SuppliedGas: MintGasCost - 1, + ReadOnly: false, + ExpectedErr: vmerrs.ErrOutOfGas.Error(), + }, +} +func TestContractNativeMinterRun(t *testing.T) { allowlist.RunPrecompileWithAllowListTests(t, Module, state.NewTestStateDB, tests) } + +func BenchmarkContractNativeMinter(b *testing.B) { + allowlist.BenchPrecompileWithAllowList(b, Module, state.NewTestStateDB, tests) +} diff --git a/precompile/contracts/rewardmanager/contract_test.go b/precompile/contracts/rewardmanager/contract_test.go index db1d61d3ae..034856c0c9 100644 --- a/precompile/contracts/rewardmanager/contract_test.go +++ b/precompile/contracts/rewardmanager/contract_test.go @@ -16,14 +16,13 @@ import ( "github.com/stretchr/testify/require" ) -func TestRewardManagerRun(t *testing.T) { - testAddr := common.HexToAddress("0x0123") - - tests := map[string]testutils.PrecompileTest{ +var ( + testAddr = common.HexToAddress("0x0123") + tests = map[string]testutils.PrecompileTest{ "set allow fee recipients from no role fails": { Caller: allowlist.TestNoRoleAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackAllowFeeRecipients() require.NoError(t, err) @@ -36,7 +35,7 @@ func TestRewardManagerRun(t *testing.T) { "set reward address from no role fails": { Caller: allowlist.TestNoRoleAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackSetRewardAddress(testAddr) require.NoError(t, err) @@ -49,7 +48,7 @@ func TestRewardManagerRun(t *testing.T) { "disable rewards from no role fails": { Caller: allowlist.TestNoRoleAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackDisableRewards() require.NoError(t, err) @@ -62,7 +61,7 @@ func TestRewardManagerRun(t *testing.T) { "set allow fee recipients from enabled succeeds": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackAllowFeeRecipients() require.NoError(t, err) @@ -71,7 +70,7 @@ func TestRewardManagerRun(t *testing.T) { SuppliedGas: AllowFeeRecipientsGasCost, ReadOnly: false, ExpectedRes: []byte{}, - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { _, isFeeRecipients := GetStoredRewardAddress(state) require.True(t, isFeeRecipients) }, @@ -79,7 +78,7 @@ func TestRewardManagerRun(t *testing.T) { "set reward address from enabled succeeds": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackSetRewardAddress(testAddr) require.NoError(t, err) @@ -88,7 +87,7 @@ func TestRewardManagerRun(t *testing.T) { SuppliedGas: SetRewardAddressGasCost, ReadOnly: false, ExpectedRes: []byte{}, - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { address, isFeeRecipients := GetStoredRewardAddress(state) require.Equal(t, testAddr, address) require.False(t, isFeeRecipients) @@ -97,7 +96,7 @@ func TestRewardManagerRun(t *testing.T) { "disable rewards from enabled succeeds": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackDisableRewards() require.NoError(t, err) @@ -106,7 +105,7 @@ func TestRewardManagerRun(t *testing.T) { SuppliedGas: DisableRewardsGasCost, ReadOnly: false, ExpectedRes: []byte{}, - AfterHook: func(t *testing.T, state contract.StateDB) { + AfterHook: func(t testing.TB, state contract.StateDB) { address, isFeeRecipients := GetStoredRewardAddress(state) require.False(t, isFeeRecipients) require.Equal(t, constants.BlackholeAddr, address) @@ -114,11 +113,11 @@ func TestRewardManagerRun(t *testing.T) { }, "get current reward address from no role succeeds": { Caller: allowlist.TestNoRoleAddr, - BeforeHook: func(t *testing.T, state contract.StateDB) { + BeforeHook: func(t testing.TB, state contract.StateDB) { allowlist.SetDefaultRoles(Module.Address)(t, state) StoreRewardAddress(state, testAddr) }, - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackCurrentRewardAddress() require.NoError(t, err) @@ -128,17 +127,19 @@ func TestRewardManagerRun(t *testing.T) { ReadOnly: false, ExpectedRes: func() []byte { res, err := PackCurrentRewardAddressOutput(testAddr) - require.NoError(t, err) + if err != nil { + panic(err) + } return res }(), }, "get are fee recipients allowed from no role succeeds": { Caller: allowlist.TestNoRoleAddr, - BeforeHook: func(t *testing.T, state contract.StateDB) { + BeforeHook: func(t testing.TB, state contract.StateDB) { allowlist.SetDefaultRoles(Module.Address)(t, state) EnableAllowFeeRecipients(state) }, - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackAreFeeRecipientsAllowed() require.NoError(t, err) return input @@ -147,14 +148,16 @@ func TestRewardManagerRun(t *testing.T) { ReadOnly: false, ExpectedRes: func() []byte { res, err := PackAreFeeRecipientsAllowedOutput(true) - require.NoError(t, err) + if err != nil { + panic(err) + } return res }(), }, "get initial config with address": { Caller: allowlist.TestNoRoleAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackCurrentRewardAddress() require.NoError(t, err) return input @@ -168,14 +171,16 @@ func TestRewardManagerRun(t *testing.T) { ReadOnly: false, ExpectedRes: func() []byte { res, err := PackCurrentRewardAddressOutput(testAddr) - require.NoError(t, err) + if err != nil { + panic(err) + } return res }(), }, "get initial config with allow fee recipients enabled": { Caller: allowlist.TestNoRoleAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackAreFeeRecipientsAllowed() require.NoError(t, err) return input @@ -189,14 +194,16 @@ func TestRewardManagerRun(t *testing.T) { ReadOnly: false, ExpectedRes: func() []byte { res, err := PackAreFeeRecipientsAllowedOutput(true) - require.NoError(t, err) + if err != nil { + panic(err) + } return res }(), }, "readOnly allow fee recipients with allowed role fails": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackAllowFeeRecipients() require.NoError(t, err) @@ -209,7 +216,7 @@ func TestRewardManagerRun(t *testing.T) { "readOnly set reward addresss with allowed role fails": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackSetRewardAddress(testAddr) require.NoError(t, err) @@ -222,7 +229,7 @@ func TestRewardManagerRun(t *testing.T) { "insufficient gas set reward address from allowed role": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackSetRewardAddress(testAddr) require.NoError(t, err) @@ -235,7 +242,7 @@ func TestRewardManagerRun(t *testing.T) { "insufficient gas allow fee recipients from allowed role": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackAllowFeeRecipients() require.NoError(t, err) @@ -248,7 +255,7 @@ func TestRewardManagerRun(t *testing.T) { "insufficient gas read current reward address from allowed role": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackCurrentRewardAddress() require.NoError(t, err) @@ -261,7 +268,7 @@ func TestRewardManagerRun(t *testing.T) { "insufficient gas are fee recipients allowed from allowed role": { Caller: allowlist.TestEnabledAddr, BeforeHook: allowlist.SetDefaultRoles(Module.Address), - InputFn: func(t *testing.T) []byte { + InputFn: func(t testing.TB) []byte { input, err := PackAreFeeRecipientsAllowed() require.NoError(t, err) @@ -272,6 +279,12 @@ func TestRewardManagerRun(t *testing.T) { ExpectedErr: vmerrs.ErrOutOfGas.Error(), }, } +) +func TestRewardManagerRun(t *testing.T) { allowlist.RunPrecompileWithAllowListTests(t, Module, state.NewTestStateDB, tests) } + +func BenchmarkRewardManager(b *testing.B) { + allowlist.BenchPrecompileWithAllowList(b, Module, state.NewTestStateDB, tests) +} diff --git a/precompile/contracts/txallowlist/contract_test.go b/precompile/contracts/txallowlist/contract_test.go index 08104024c5..119fec3817 100644 --- a/precompile/contracts/txallowlist/contract_test.go +++ b/precompile/contracts/txallowlist/contract_test.go @@ -13,3 +13,7 @@ import ( func TestTxAllowListRun(t *testing.T) { allowlist.RunPrecompileWithAllowListTests(t, Module, state.NewTestStateDB, nil) } + +func BenchmarkTxAllowList(b *testing.B) { + allowlist.BenchPrecompileWithAllowList(b, Module, state.NewTestStateDB, nil) +} diff --git a/precompile/testutils/test_precompile.go b/precompile/testutils/test_precompile.go index 6e7fe23c1c..eb06ec3325 100644 --- a/precompile/testutils/test_precompile.go +++ b/precompile/testutils/test_precompile.go @@ -6,6 +6,7 @@ package testutils import ( "math/big" "testing" + "time" "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/subnet-evm/commontype" @@ -24,7 +25,7 @@ type PrecompileTest struct { Input []byte // InputFn is a function that returns the raw input bytes to the precompile // If specified, Input will be ignored. - InputFn func(t *testing.T) []byte + InputFn func(t testing.TB) []byte // SuppliedGas is the amount of gas supplied to the precompile SuppliedGas uint64 // ReadOnly is whether the precompile should be called in read only @@ -36,9 +37,9 @@ type PrecompileTest struct { // If nil, Configure will not be called. Config precompileconfig.Config // BeforeHook is called before the precompile is called. - BeforeHook func(t *testing.T, state contract.StateDB) + BeforeHook func(t testing.TB, state contract.StateDB) // AfterHook is called after the precompile is called. - AfterHook func(t *testing.T, state contract.StateDB) + AfterHook func(t testing.TB, state contract.StateDB) // ExpectedRes is the expected raw byte result returned by the precompile ExpectedRes []byte // ExpectedErr is the expected error returned by the precompile @@ -47,7 +48,35 @@ type PrecompileTest struct { BlockNumber int64 } +type PrecompileRunparams struct { + AccessibleState contract.AccessibleState + Caller common.Address + ContractAddress common.Address + Input []byte + SuppliedGas uint64 + ReadOnly bool +} + func (test PrecompileTest) Run(t *testing.T, module modules.Module, state contract.StateDB) { + runParams := test.setup(t, module, state) + + if runParams.Input != nil { + ret, remainingGas, err := module.Contract.Run(runParams.AccessibleState, runParams.Caller, runParams.ContractAddress, runParams.Input, runParams.SuppliedGas, runParams.ReadOnly) + if len(test.ExpectedErr) != 0 { + require.ErrorContains(t, err, test.ExpectedErr) + } else { + require.NoError(t, err) + } + require.Equal(t, uint64(0), remainingGas) + require.Equal(t, test.ExpectedRes, ret) + } + + if test.AfterHook != nil { + test.AfterHook(t, state) + } +} + +func (test PrecompileTest) setup(t testing.TB, module modules.Module, state contract.StateDB) PrecompileRunparams { t.Helper() contractAddress := module.Address @@ -69,18 +98,76 @@ func (test PrecompileTest) Run(t *testing.T, module modules.Module, state contra input = test.InputFn(t) } - if input != nil { - ret, remainingGas, err := module.Contract.Run(accesibleState, test.Caller, contractAddress, input, test.SuppliedGas, test.ReadOnly) - if len(test.ExpectedErr) != 0 { - require.ErrorContains(t, err, test.ExpectedErr) - } else { - require.NoError(t, err) - } - require.Equal(t, uint64(0), remainingGas) - require.Equal(t, test.ExpectedRes, ret) + return PrecompileRunparams{ + AccessibleState: accesibleState, + Caller: test.Caller, + ContractAddress: contractAddress, + Input: input, + SuppliedGas: test.SuppliedGas, + ReadOnly: test.ReadOnly, + } +} + +func (test PrecompileTest) Bench(b *testing.B, module modules.Module, state contract.StateDB) { + runParams := test.setup(b, module, state) + + if runParams.Input == nil { + b.Skip("Skipping precompile benchmark due to nil input (used for configuration tests)") } + stateDB := runParams.AccessibleState.GetStateDB() + snapshot := stateDB.Snapshot() + + ret, remainingGas, err := module.Contract.Run(runParams.AccessibleState, runParams.Caller, runParams.ContractAddress, runParams.Input, runParams.SuppliedGas, runParams.ReadOnly) + if len(test.ExpectedErr) != 0 { + require.ErrorContains(b, err, test.ExpectedErr) + } else { + require.NoError(b, err) + } + require.Equal(b, uint64(0), remainingGas) + require.Equal(b, test.ExpectedRes, ret) + if test.AfterHook != nil { - test.AfterHook(t, state) + test.AfterHook(b, state) + } + + b.ReportAllocs() + start := time.Now() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + // Revert to the previous snapshot and take a new snapshot, so we can reset the state after execution + stateDB.RevertToSnapshot(snapshot) + snapshot = stateDB.Snapshot() + + // Ignore return values for benchmark + _, _, _ = module.Contract.Run(runParams.AccessibleState, runParams.Caller, runParams.ContractAddress, runParams.Input, runParams.SuppliedGas, runParams.ReadOnly) + } + b.StopTimer() + + elapsed := uint64(time.Since(start)) + if elapsed < 1 { + elapsed = 1 + } + gasUsed := runParams.SuppliedGas * uint64(b.N) + b.ReportMetric(float64(runParams.SuppliedGas), "gas/op") + // Keep it as uint64, multiply 100 to get two digit float later + mgasps := (100 * 1000 * gasUsed) / elapsed + b.ReportMetric(float64(mgasps)/100, "mgas/s") + + // Execute the test one final time to ensure that if our RevertToSnapshot logic breaks such that each run is actually failing or resulting in unexpected behavior + // the benchmark should catch the error here. + stateDB.RevertToSnapshot(snapshot) + ret, remainingGas, err = module.Contract.Run(runParams.AccessibleState, runParams.Caller, runParams.ContractAddress, runParams.Input, runParams.SuppliedGas, runParams.ReadOnly) + if len(test.ExpectedErr) != 0 { + require.ErrorContains(b, err, test.ExpectedErr) + } else { + require.NoError(b, err) + } + require.Equal(b, uint64(0), remainingGas) + require.Equal(b, test.ExpectedRes, ret) + + if test.AfterHook != nil { + test.AfterHook(b, state) } } diff --git a/scripts/build_bench_precompiles.sh b/scripts/build_bench_precompiles.sh new file mode 100755 index 0000000000..5cd0be44b0 --- /dev/null +++ b/scripts/build_bench_precompiles.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -o errexit +set -o nounset +set -o pipefail + +# Root directory +SUBNET_EVM_PATH=$( + cd "$(dirname "${BASH_SOURCE[0]}")" + cd .. && pwd +) + +# Load the versions +source "$SUBNET_EVM_PATH"/scripts/versions.sh + +# Load the constants +source "$SUBNET_EVM_PATH"/scripts/constants.sh + +go test ./precompile/contracts/... -bench=./... -timeout="10m" $@ From c33961ff88bae910e35f6b152d4eaf09f7220f24 Mon Sep 17 00:00:00 2001 From: aaronbuchwald Date: Wed, 12 Apr 2023 13:04:01 -0400 Subject: [PATCH 09/10] Bump avalanchego to v1.10.0 (#604) * Bump avalanchego to v1.10.0-fuji-rc.2 * Add comptibility version * Bump avalanchego dep to v1.10.0 and update version to v0.5.0 * Fix interface changes from avalanchego * Update compatibility in README --- README.md | 5 +++-- compatibility.json | 1 + go.mod | 3 ++- go.sum | 6 ++++-- plugin/evm/version.go | 2 +- scripts/versions.sh | 4 ++-- tests/load/load_test.go | 2 +- tests/precompile/precompile_test.go | 2 +- tests/precompile/solidity/suites.go | 2 +- 9 files changed, 16 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 176a4ae6b2..f37b13b738 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,9 @@ The Subnet EVM runs in a separate process from the main AvalancheGo process and [v0.4.8] AvalancheGo@v1.9.6-v1.9.8 (Protocol Version: 22) [v0.4.9] AvalancheGo@v1.9.9 (Protocol Version: 23) [v0.4.10] AvalancheGo@v1.9.9 (Protocol Version: 23) -[v0.4.11] AvalancheGo@v1.9.10 (Protocol Version: 24) -[v0.4.12] AvalancheGo@v1.9.10 (Protocol Version: 24) +[v0.4.11] AvalancheGo@v1.9.10-v1.9.16 (Protocol Version: 24) +[v0.4.12] AvalancheGo@v1.9.10-v1.9.16 (Protocol Version: 24) +[v0.5.0] AvalancheGo@v1.10.0 (Protocol Version: 25) ``` ## API diff --git a/compatibility.json b/compatibility.json index 7783acaee3..6ff8ec84a5 100644 --- a/compatibility.json +++ b/compatibility.json @@ -1,5 +1,6 @@ { "rpcChainVMProtocolVersion": { + "v0.5.0": 25, "v0.4.12": 24, "v0.4.11": 24, "v0.4.10": 23, diff --git a/go.mod b/go.mod index 524fbdfb94..c786c1da09 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/VictoriaMetrics/fastcache v1.10.0 - github.com/ava-labs/avalanchego v1.9.11 + github.com/ava-labs/avalanchego v1.10.0 github.com/cespare/cp v0.1.0 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 @@ -47,6 +47,7 @@ require ( ) require ( + github.com/DataDog/zstd v1.5.2 // indirect github.com/NYTimes/gziphandler v1.1.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect diff --git a/go.sum b/go.sum index e471048922..995d22e1d6 100644 --- a/go.sum +++ b/go.sum @@ -44,6 +44,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -61,8 +63,8 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= -github.com/ava-labs/avalanchego v1.9.11 h1:5hXHJMvErfaolWD7Hw9gZaVylck2shBaV/2NTHA0BfA= -github.com/ava-labs/avalanchego v1.9.11/go.mod h1:nNc+4JCIJMaEt2xRmeMVAUyQwDIap7RvnMrfWD2Tpo8= +github.com/ava-labs/avalanchego v1.10.0 h1:Rn6Nyd62OkzQG5QpCgtCGVXtjuiaEzxV000kqG9aUIg= +github.com/ava-labs/avalanchego v1.10.0/go.mod h1:hTaSLGN4y/EmhmYd+yjUj9Lsm00q70V78jOYDdnLrgQ= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= diff --git a/plugin/evm/version.go b/plugin/evm/version.go index 532a9ac3da..0387a27e18 100644 --- a/plugin/evm/version.go +++ b/plugin/evm/version.go @@ -11,7 +11,7 @@ var ( // GitCommit is set by the build script GitCommit string // Version is the version of Subnet EVM - Version string = "v0.4.12" + Version string = "v0.5.0" ) func init() { diff --git a/scripts/versions.sh b/scripts/versions.sh index 9e9395b789..c4ee6de3e5 100644 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -1,9 +1,9 @@ #!/usr/bin/env bash # Set up the versions to be used - populate ENV variables only if they are not already populated -SUBNET_EVM_VERSION=${SUBNET_EVM_VERSION:-'v0.4.12'} +SUBNET_EVM_VERSION=${SUBNET_EVM_VERSION:-'v0.5.0'} # Don't export them as they're used in the context of other calls -AVALANCHE_VERSION=${AVALANCHE_VERSION:-'v1.9.11'} +AVALANCHE_VERSION=${AVALANCHE_VERSION:-'v1.10.0'} AVALANCHEGO_VERSION=${AVALANCHEGO_VERSION:-$AVALANCHE_VERSION} GINKGO_VERSION=${GINKGO_VERSION:-'v2.2.0'} diff --git a/tests/load/load_test.go b/tests/load/load_test.go index 07641a4ce6..68f7b5896b 100644 --- a/tests/load/load_test.go +++ b/tests/load/load_test.go @@ -40,7 +40,7 @@ var _ = ginkgo.BeforeSuite(func() { // Assumes that startCmd will launch a node with HTTP Port at [utils.DefaultLocalNodeURI] healthClient := health.NewClient(utils.DefaultLocalNodeURI) - healthy, err := health.AwaitReady(ctx, healthClient, 5*time.Second) + healthy, err := health.AwaitReady(ctx, healthClient, 5*time.Second, nil) gomega.Expect(err).Should(gomega.BeNil()) gomega.Expect(healthy).Should(gomega.BeTrue()) log.Info("AvalancheGo node is healthy") diff --git a/tests/precompile/precompile_test.go b/tests/precompile/precompile_test.go index 46acc862df..b7d9c29242 100644 --- a/tests/precompile/precompile_test.go +++ b/tests/precompile/precompile_test.go @@ -40,7 +40,7 @@ var _ = ginkgo.BeforeSuite(func() { // Assumes that startCmd will launch a node with HTTP Port at [utils.DefaultLocalNodeURI] healthClient := health.NewClient(utils.DefaultLocalNodeURI) - healthy, err := health.AwaitReady(ctx, healthClient, 5*time.Second) + healthy, err := health.AwaitReady(ctx, healthClient, 5*time.Second, nil) gomega.Expect(err).Should(gomega.BeNil()) gomega.Expect(healthy).Should(gomega.BeTrue()) log.Info("AvalancheGo node is healthy") diff --git a/tests/precompile/solidity/suites.go b/tests/precompile/solidity/suites.go index 1404a01603..685015c27e 100644 --- a/tests/precompile/solidity/suites.go +++ b/tests/precompile/solidity/suites.go @@ -17,7 +17,7 @@ import ( var _ = ginkgo.Describe("[Precompiles]", ginkgo.Ordered, func() { ginkgo.It("ping the network", ginkgo.Label("setup"), func() { client := health.NewClient(utils.DefaultLocalNodeURI) - healthy, err := client.Readiness(context.Background()) + healthy, err := client.Readiness(context.Background(), nil) gomega.Expect(err).Should(gomega.BeNil()) gomega.Expect(healthy.Healthy).Should(gomega.BeTrue()) }) From 157e9b953185abfaeec507dbb86820e18d2c319a Mon Sep 17 00:00:00 2001 From: Darioush Jalali Date: Wed, 12 Apr 2023 11:26:11 -0700 Subject: [PATCH 10/10] Make state sync request size configurable (#614) * Make state sync request size configurable * finish passing the parameter * set default to 256 --- plugin/evm/config.go | 5 ++++- plugin/evm/syncervm_client.go | 4 +++- plugin/evm/vm.go | 19 ++++++++++--------- sync/client/client_test.go | 2 +- sync/client/leaf_syncer.go | 20 ++++++++++---------- sync/statesync/state_syncer.go | 7 ++++--- sync/statesync/sync_test.go | 1 + 7 files changed, 33 insertions(+), 25 deletions(-) diff --git a/plugin/evm/config.go b/plugin/evm/config.go index 6abaed1093..82f6378cde 100644 --- a/plugin/evm/config.go +++ b/plugin/evm/config.go @@ -55,7 +55,8 @@ const ( // time assumptions: // - normal bootstrap processing time: ~14 blocks / second // - state sync time: ~6 hrs. - defaultStateSyncMinBlocks = 300_000 + defaultStateSyncMinBlocks = 300_000 + defaultStateSyncRequestSize = 256 // the number of key/values to ask peers for per request ) var ( @@ -186,6 +187,7 @@ type Config struct { StateSyncIDs string `json:"state-sync-ids"` StateSyncCommitInterval uint64 `json:"state-sync-commit-interval"` StateSyncMinBlocks uint64 `json:"state-sync-min-blocks"` + StateSyncRequestSize uint16 `json:"state-sync-request-size"` // SkipUpgradeCheck disables checking that upgrades must take place before the last // accepted block. Skipping this check is useful when a node operator does not update @@ -263,6 +265,7 @@ func (c *Config) SetDefaults() { c.StateSyncServerTrieCache = defaultStateSyncServerTrieCache c.StateSyncCommitInterval = defaultSyncableCommitInterval c.StateSyncMinBlocks = defaultStateSyncMinBlocks + c.StateSyncRequestSize = defaultStateSyncRequestSize c.AllowUnprotectedTxHashes = defaultAllowUnprotectedTxHashes c.AcceptedCacheSize = defaultAcceptedCacheSize } diff --git a/plugin/evm/syncervm_client.go b/plugin/evm/syncervm_client.go index caa3682d77..2a3f4c3cbf 100644 --- a/plugin/evm/syncervm_client.go +++ b/plugin/evm/syncervm_client.go @@ -42,7 +42,8 @@ type stateSyncClientConfig struct { // Specifies the number of blocks behind the latest state summary that the chain must be // in order to prefer performing state sync over falling back to the normal bootstrapping // algorithm. - stateSyncMinBlocks uint64 + stateSyncMinBlocks uint64 + stateSyncRequestSize uint16 // number of key/value pairs to ask peers for per request lastAcceptedHeight uint64 @@ -283,6 +284,7 @@ func (client *stateSyncerClient) syncStateTrie(ctx context.Context) error { DB: client.chaindb, MaxOutstandingCodeHashes: statesync.DefaultMaxOutstandingCodeHashes, NumCodeFetchingWorkers: statesync.DefaultNumCodeFetchingWorkers, + RequestSize: client.stateSyncRequestSize, }) if err != nil { return err diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index 1f979b0181..446bbe54cb 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -505,15 +505,16 @@ func (vm *VM) initializeStateSyncClient(lastAcceptedHeight uint64) error { BlockParser: vm, }, ), - enabled: vm.config.StateSyncEnabled, - skipResume: vm.config.StateSyncSkipResume, - stateSyncMinBlocks: vm.config.StateSyncMinBlocks, - lastAcceptedHeight: lastAcceptedHeight, // TODO clean up how this is passed around - chaindb: vm.chaindb, - metadataDB: vm.metadataDB, - acceptedBlockDB: vm.acceptedBlockDB, - db: vm.db, - toEngine: vm.toEngine, + enabled: vm.config.StateSyncEnabled, + skipResume: vm.config.StateSyncSkipResume, + stateSyncMinBlocks: vm.config.StateSyncMinBlocks, + stateSyncRequestSize: vm.config.StateSyncRequestSize, + lastAcceptedHeight: lastAcceptedHeight, // TODO clean up how this is passed around + chaindb: vm.chaindb, + metadataDB: vm.metadataDB, + acceptedBlockDB: vm.acceptedBlockDB, + db: vm.db, + toEngine: vm.toEngine, }) // If StateSync is disabled, clear any ongoing summary so that we will not attempt to resume diff --git a/sync/client/client_test.go b/sync/client/client_test.go index b5c7b12c06..3c907b4a42 100644 --- a/sync/client/client_test.go +++ b/sync/client/client_test.go @@ -799,7 +799,7 @@ func TestGetLeafsRetries(t *testing.T) { Root: root, Start: bytes.Repeat([]byte{0x00}, common.HashLength), End: bytes.Repeat([]byte{0xff}, common.HashLength), - Limit: defaultLeafRequestLimit, + Limit: 1024, } ctx, cancel := context.WithCancel(context.Background()) diff --git a/sync/client/leaf_syncer.go b/sync/client/leaf_syncer.go index 6aa1dab7f4..8ad9ef27c6 100644 --- a/sync/client/leaf_syncer.go +++ b/sync/client/leaf_syncer.go @@ -20,8 +20,6 @@ var ( errFailedToFetchLeafs = errors.New("failed to fetch leafs") ) -const defaultLeafRequestLimit = 1024 - // LeafSyncTask represents a complete task to be completed by the leaf syncer. // Note: each LeafSyncTask is processed on its own goroutine and there will // not be concurrent calls to the callback methods. Implementations should return @@ -38,9 +36,10 @@ type LeafSyncTask interface { } type CallbackLeafSyncer struct { - client LeafClient - done chan error - tasks <-chan LeafSyncTask + client LeafClient + done chan error + tasks <-chan LeafSyncTask + requestSize uint16 } type LeafClient interface { @@ -50,11 +49,12 @@ type LeafClient interface { } // NewCallbackLeafSyncer creates a new syncer object to perform leaf sync of tries. -func NewCallbackLeafSyncer(client LeafClient, tasks <-chan LeafSyncTask) *CallbackLeafSyncer { +func NewCallbackLeafSyncer(client LeafClient, tasks <-chan LeafSyncTask, requestSize uint16) *CallbackLeafSyncer { return &CallbackLeafSyncer{ - client: client, - done: make(chan error), - tasks: tasks, + client: client, + done: make(chan error), + tasks: tasks, + requestSize: requestSize, } } @@ -100,7 +100,7 @@ func (c *CallbackLeafSyncer) syncTask(ctx context.Context, task LeafSyncTask) er Root: root, Account: task.Account(), Start: start, - Limit: defaultLeafRequestLimit, + Limit: c.requestSize, }) if err != nil { return fmt.Errorf("%s: %w", errFailedToFetchLeafs, err) diff --git a/sync/statesync/state_syncer.go b/sync/statesync/state_syncer.go index b20d4a2645..ef38f14c36 100644 --- a/sync/statesync/state_syncer.go +++ b/sync/statesync/state_syncer.go @@ -28,8 +28,9 @@ type StateSyncerConfig struct { Client syncclient.Client DB ethdb.Database BatchSize int - MaxOutstandingCodeHashes int // Maximum number of code hashes in the code syncer queue - NumCodeFetchingWorkers int // Number of code syncing threads + MaxOutstandingCodeHashes int // Maximum number of code hashes in the code syncer queue + NumCodeFetchingWorkers int // Number of code syncing threads + RequestSize uint16 // Number of leafs to request from a peer at a time } // stateSync keeps the state of the entire state sync operation. @@ -82,7 +83,7 @@ func NewStateSyncer(config *StateSyncerConfig) (*stateSync, error) { mainTrieDone: make(chan struct{}), done: make(chan error, 1), } - ss.syncer = syncclient.NewCallbackLeafSyncer(config.Client, ss.segments) + ss.syncer = syncclient.NewCallbackLeafSyncer(config.Client, ss.segments, config.RequestSize) ss.codeSyncer = newCodeSyncer(CodeSyncerConfig{ DB: config.DB, Client: config.Client, diff --git a/sync/statesync/sync_test.go b/sync/statesync/sync_test.go index 04b22cbb63..d23495ee2e 100644 --- a/sync/statesync/sync_test.go +++ b/sync/statesync/sync_test.go @@ -62,6 +62,7 @@ func testSync(t *testing.T, test syncTest) { BatchSize: 1000, // Use a lower batch size in order to get test coverage of batches being written early. NumCodeFetchingWorkers: DefaultNumCodeFetchingWorkers, MaxOutstandingCodeHashes: DefaultMaxOutstandingCodeHashes, + RequestSize: 1024, }) if err != nil { t.Fatal(err)