Skip to content

Commit

Permalink
Merge pull request #55 from Kava-Labs/extend-evm-module
Browse files Browse the repository at this point in the history
Extend x/evm module params with enabled_precompiles
  • Loading branch information
evgeniy-scherbina authored May 3, 2024
2 parents d9ad138 + d6a06d7 commit 2ada74f
Show file tree
Hide file tree
Showing 8 changed files with 799 additions and 234 deletions.
19 changes: 13 additions & 6 deletions proto/ethermint/evm/v1/evm.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@ message Params {
repeated int64 extra_eips = 4 [(gogoproto.customname) = "ExtraEIPs", (gogoproto.moretags) = "yaml:\"extra_eips\""];
// chain_config defines the EVM chain configuration parameters
ChainConfig chain_config = 5 [(gogoproto.moretags) = "yaml:\"chain_config\"", (gogoproto.nullable) = false];
// list of allowed eip712 msgs and their types
// eip712_allowed_msgs contains list of allowed eip712 msgs and their types
repeated EIP712AllowedMsg eip712_allowed_msgs = 6
[(gogoproto.customname) = "EIP712AllowedMsgs", (gogoproto.nullable) = false];
// allow_unprotected_txs defines if replay-protected (i.e non EIP155
// signed) transactions can be executed on the state machine.
bool allow_unprotected_txs = 7;
// enabled_precompiles contains list of hex-encoded evm addresses of enabled precompiled contracts.
// Precompile must be registered before it can be enabled.
// enabled_precompiles should be sorted in ascending order and unique.
// sorting and uniqueness are checked against bytes representation of addresses
repeated string enabled_precompiles = 8;
}

// ChainConfig defines the Ethereum ChainConfig parameters using *sdk.Int values
Expand Down Expand Up @@ -246,20 +251,20 @@ message TraceConfig {

// EIP712AllowedMsg stores an allowed legacy msg and its eip712 type.
message EIP712AllowedMsg {
// msg's proto type name. ie "/cosmos.bank.v1beta1.MsgSend"
// msg_type_url is a msg's proto type name. ie "/cosmos.bank.v1beta1.MsgSend"
string msg_type_url = 1;

// name of the eip712 value type. ie "MsgValueSend"
// msg_value_type_name is a name of the eip712 value type. ie "MsgValueSend"
string msg_value_type_name = 2;

// types of the msg value
// value_types is a list of msg value types
repeated EIP712MsgAttrType value_types = 3 [(gogoproto.nullable) = false];

// nested types of the msg value
// nested_types is a list of msg value nested types
repeated EIP712NestedMsgType nested_types = 4 [(gogoproto.nullable) = false];
}

// EIP712MsgType is the eip712 type of a single message.
// EIP712NestedMsgType is the eip712 type of a single message.
message EIP712NestedMsgType {
// name of the nested type. ie "Fee", "Coin"
string name = 1;
Expand All @@ -270,6 +275,8 @@ message EIP712NestedMsgType {

// EIP712MsgAttrType is the eip712 type of a single message attribute.
message EIP712MsgAttrType {
// name
string name = 1;
// type
string type = 2;
}
13 changes: 11 additions & 2 deletions x/evm/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"

precompile_modules "github.com/ethereum/go-ethereum/precompile/modules"
ethermint "github.com/evmos/ethermint/types"
"github.com/evmos/ethermint/x/evm/keeper"
"github.com/evmos/ethermint/x/evm/types"
Expand All @@ -36,10 +36,19 @@ func InitGenesis(
k *keeper.Keeper,
accountKeeper types.AccountKeeper,
data types.GenesisState,
registeredModules []precompile_modules.Module,
) []abci.ValidatorUpdate {
k.WithChainID(ctx)

err := k.SetParams(ctx, data.Params)
err := types.ValidatePrecompileRegistration(
registeredModules,
data.Params.GetEnabledPrecompiles(),
)
if err != nil {
panic(err)
}

err = k.SetParams(ctx, data.Params)
if err != nil {
panic(fmt.Errorf("error setting params %s", err))
}
Expand Down
209 changes: 139 additions & 70 deletions x/evm/genesis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package evm_test
import (
"math/big"

authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/ethereum/go-ethereum/common"
precompile_modules "github.com/ethereum/go-ethereum/precompile/modules"

authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/evmos/ethermint/crypto/ethsecp256k1"
etherminttypes "github.com/evmos/ethermint/types"
"github.com/evmos/ethermint/x/evm"
Expand All @@ -18,123 +19,191 @@ func (suite *EvmTestSuite) TestInitGenesis() {
suite.Require().NoError(err)

address := common.HexToAddress(privkey.PubKey().Address().String())
hexAddr1 := "0x1000000000000000000000000000000000000000"
hexAddr2 := "0x2000000000000000000000000000000000000000"

var vmdb *statedb.StateDB

testCases := []struct {
name string
malleate func()
genState *types.GenesisState
expPanic bool
name string
malleate func()
getGenState func() *types.GenesisState
registeredModules []precompile_modules.Module
expPanic bool
}{
{
"default",
func() {},
types.DefaultGenesisState(),
false,
name: "default",
malleate: func() {},
getGenState: func() *types.GenesisState {
return types.DefaultGenesisState()
},
expPanic: false,
},
{
"valid account",
func() {
name: "valid account",
malleate: func() {
vmdb.AddBalance(address, big.NewInt(1))
},
&types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
Storage: types.Storage{
{Key: common.BytesToHash([]byte("key")).String(), Value: common.BytesToHash([]byte("value")).String()},
getGenState: func() *types.GenesisState {
return &types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
Storage: types.Storage{
{Key: common.BytesToHash([]byte("key")).String(), Value: common.BytesToHash([]byte("value")).String()},
},
},
},
},
}
},
false,
expPanic: false,
},
{
"account not found",
func() {},
&types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
name: "account not found",
malleate: func() {},
getGenState: func() *types.GenesisState {
return &types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
},
},
},
}
},
true,
expPanic: true,
},
{
"invalid account type",
func() {
name: "invalid account type",
malleate: func() {
acc := authtypes.NewBaseAccountWithAddress(address.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
},
&types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
getGenState: func() *types.GenesisState {
return &types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
},
},
},
}
},
true,
expPanic: true,
},
{
"invalid code hash",
func() {
name: "invalid code hash",
malleate: func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
},
&types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
Code: "ffffffff",
getGenState: func() *types.GenesisState {
return &types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
Code: "ffffffff",
},
},
},
}
},
true,
expPanic: true,
},
{
"ignore empty account code checking",
func() {
name: "ignore empty account code checking",
malleate: func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())

suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
},
&types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
Code: "",
getGenState: func() *types.GenesisState {
return &types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
Code: "",
},
},
},
}
},
false,
expPanic: false,
},
{
"ignore empty account code checking with non-empty codehash",
func() {
name: "ignore empty account code checking with non-empty codehash",
malleate: func() {
ethAcc := &etherminttypes.EthAccount{
BaseAccount: authtypes.NewBaseAccount(address.Bytes(), nil, 0, 0),
CodeHash: common.BytesToHash([]byte{1, 2, 3}).Hex(),
}

suite.app.AccountKeeper.SetAccount(suite.ctx, ethAcc)
},
&types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
Code: "",
getGenState: func() *types.GenesisState {
return &types.GenesisState{
Params: types.DefaultParams(),
Accounts: []types.GenesisAccount{
{
Address: address.String(),
Code: "",
},
},
},
}
},
expPanic: false,
},
{
name: "precompile is enabled and registered",
malleate: func() {},
getGenState: func() *types.GenesisState {
defaultGen := types.DefaultGenesisState()
defaultGen.Params.EnabledPrecompiles = []string{hexAddr1}
return defaultGen
},
registeredModules: []precompile_modules.Module{
{Address: common.HexToAddress(hexAddr1)},
},
expPanic: false,
},
{
name: "precompile is enabled, but not registered",
malleate: func() {},
getGenState: func() *types.GenesisState {
defaultGen := types.DefaultGenesisState()
defaultGen.Params.EnabledPrecompiles = []string{hexAddr1}
return defaultGen
},
registeredModules: nil,
expPanic: true,
},
{
name: "enabled precompiles are not sorted",
malleate: func() {},
getGenState: func() *types.GenesisState {
defaultGen := types.DefaultGenesisState()
defaultGen.Params.EnabledPrecompiles = []string{hexAddr2, hexAddr1}
return defaultGen
},
registeredModules: []precompile_modules.Module{
{Address: common.HexToAddress(hexAddr1)},
{Address: common.HexToAddress(hexAddr2)},
},
expPanic: true,
},
{
name: "enabled precompiles are not unique",
malleate: func() {},
getGenState: func() *types.GenesisState {
defaultGen := types.DefaultGenesisState()
defaultGen.Params.EnabledPrecompiles = []string{hexAddr1, hexAddr1}
return defaultGen
},
registeredModules: []precompile_modules.Module{
{Address: common.HexToAddress(hexAddr1)},
},
false,
expPanic: true,
},
}

Expand All @@ -149,13 +218,13 @@ func (suite *EvmTestSuite) TestInitGenesis() {
if tc.expPanic {
suite.Require().Panics(
func() {
_ = evm.InitGenesis(suite.ctx, suite.app.EvmKeeper, suite.app.AccountKeeper, *tc.genState)
_ = evm.InitGenesis(suite.ctx, suite.app.EvmKeeper, suite.app.AccountKeeper, *tc.getGenState(), tc.registeredModules)
},
)
} else {
suite.Require().NotPanics(
func() {
_ = evm.InitGenesis(suite.ctx, suite.app.EvmKeeper, suite.app.AccountKeeper, *tc.genState)
_ = evm.InitGenesis(suite.ctx, suite.app.EvmKeeper, suite.app.AccountKeeper, *tc.getGenState(), tc.registeredModules)
},
)
}
Expand Down
Loading

0 comments on commit 2ada74f

Please sign in to comment.