Files
evm/params/extras/precompile_upgrade_test.go

305 lines
8.3 KiB
Go

// (c) 2022, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package extras_test
import (
"math/big"
"testing"
"github.com/luxfi/evm/params/extras"
"github.com/luxfi/evm/precompile/contracts/deployerallowlist"
"github.com/luxfi/evm/precompile/contracts/txallowlist"
"github.com/luxfi/evm/utils"
"github.com/luxfi/geth/common"
"github.com/stretchr/testify/require"
)
func TestVerifyPrecompileUpgradeConfig(t *testing.T) {
admins := []common.Address{{1}}
chainConfig := &extras.ChainConfig{
FeeConfig: extras.DefaultFeeConfig,
}
chainConfig.GenesisPrecompiles = extras.Precompiles{
txallowlist.ConfigKey: txallowlist.NewConfig(utils.NewUint64(1), admins, nil, nil),
}
type test struct {
upgrades []extras.PrecompileUpgrade
expectedErrorString string
}
tests := map[string]test{
"upgrade bytes conflicts with genesis (re-enable without disable)": {
expectedErrorString: "disable should be [true]",
upgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewConfig(utils.NewUint64(2), admins, nil, nil),
},
},
},
"upgrade bytes conflicts with genesis (disable before enable)": {
expectedErrorString: "config block timestamp (0) <= previous timestamp (1) of same key",
upgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(0)),
},
},
},
"upgrade bytes conflicts with genesis (disable same time as enable)": {
expectedErrorString: "config block timestamp (1) <= previous timestamp (1) of same key",
upgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(1)),
},
},
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
// make a local copy of the chainConfig
chainConfig := chainConfig
// verify with the upgrades from the test
chainConfig.UpgradeConfig.PrecompileUpgrades = tt.upgrades
err := chainConfig.Verify()
if tt.expectedErrorString != "" {
require.ErrorContains(t, err, tt.expectedErrorString)
} else {
require.NoError(t, err)
}
})
}
}
func TestCheckCompatiblePrecompileUpgradeConfigs(t *testing.T) {
admins := []common.Address{{1}}
chainConfig := &extras.ChainConfig{}
chainConfig.GenesisPrecompiles = extras.Precompiles{
txallowlist.ConfigKey: txallowlist.NewConfig(utils.NewUint64(1), admins, nil, nil),
deployerallowlist.ConfigKey: deployerallowlist.NewConfig(utils.NewUint64(10), admins, nil, nil),
}
tests := map[string]upgradeCompatibilityTest{
"disable and re-enable": {
startTimestamps: []uint64{5},
configs: []*extras.UpgradeConfig{
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(7), admins, nil, nil),
},
},
},
},
},
"disable and re-enable, reschedule upgrade before it happens": {
startTimestamps: []uint64{5, 6},
configs: []*extras.UpgradeConfig{
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(7), admins, nil, nil),
},
},
},
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(8), admins, nil, nil),
},
},
},
},
},
"disable and re-enable, reschedule upgrade after it happens": {
expectedErrorString: "mismatching PrecompileUpgrade",
startTimestamps: []uint64{5, 8},
configs: []*extras.UpgradeConfig{
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(7), admins, nil, nil),
},
},
},
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(8), admins, nil, nil),
},
},
},
},
},
"disable and re-enable, cancel upgrade before it happens": {
startTimestamps: []uint64{5, 6},
configs: []*extras.UpgradeConfig{
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(7), admins, nil, nil),
},
},
},
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
},
},
},
},
"disable and re-enable, cancel upgrade after it happens": {
expectedErrorString: "mismatching missing PrecompileUpgrade",
startTimestamps: []uint64{5, 8},
configs: []*extras.UpgradeConfig{
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(7), admins, nil, nil),
},
},
},
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
},
},
},
},
"disable and re-enable, change upgrade config after upgrade not allowed": {
expectedErrorString: "mismatching PrecompileUpgrade",
startTimestamps: []uint64{5, 8},
configs: []*extras.UpgradeConfig{
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(7), admins, nil, nil),
},
},
},
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
{
// uses a different (empty) admin list, not allowed
Config: txallowlist.NewConfig(utils.NewUint64(7), []common.Address{}, nil, nil),
},
},
},
},
},
"disable and re-enable, identical upgrade config should be accepted": {
startTimestamps: []uint64{5, 8},
configs: []*extras.UpgradeConfig{
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(7), admins, nil, nil),
},
},
},
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(6)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(7), admins, nil, nil),
},
},
},
},
},
"retroactively enabling upgrades is not allowed": {
expectedErrorString: "cannot retroactively enable PrecompileUpgrade[1] in database (have timestamp nil, want timestamp 5, rewindto timestamp 5)",
startTimestamps: []uint64{6},
configs: []*extras.UpgradeConfig{
{
PrecompileUpgrades: []extras.PrecompileUpgrade{
{
Config: txallowlist.NewDisableConfig(utils.NewUint64(5)),
},
{
Config: txallowlist.NewConfig(utils.NewUint64(6), admins, nil, nil),
},
},
},
},
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
tt.run(t, *chainConfig)
})
}
}
type upgradeCompatibilityTest struct {
configs []*extras.UpgradeConfig
startTimestamps []uint64
expectedErrorString string
}
func (tt *upgradeCompatibilityTest) run(t *testing.T, chainConfig extras.ChainConfig) {
// apply all the upgrade bytes specified in order
for i, upgrade := range tt.configs {
newCfg := chainConfig
newCfg.UpgradeConfig = *upgrade
err := chainConfig.CheckConfigCompatible(&newCfg, new(big.Int), tt.startTimestamps[i])
// if this is not the final upgradeBytes, continue applying
// the next upgradeBytes. (only check the result on the last apply)
if i != len(tt.configs)-1 {
if err != nil {
t.Fatalf("expecting checkConfigCompatible call %d to return nil, got %s", i+1, err)
}
chainConfig = newCfg
continue
}
if tt.expectedErrorString != "" {
require.ErrorContains(t, err, tt.expectedErrorString)
} else {
require.Nil(t, err)
}
}
}