forked from cerc-io/laconicd-deprecated
evm: params (#458)
* evm: params * setup * bump commit * fixes * increase gas usage * tests * evm denom param * more config updates * update genesis * update ante handler * csdb param test * more tests and fixes * update statedb.Copy * lint * additional test * fix importer tests * fix AnteHandler test * minor update * revert * undo gas update * stringer test * changelog * fix csdb index error (#493) * attempt to fix * cleanup * add idx check * update csdb.Copy * update default hash * update querier * update rpc tests * fix estimate gas test Co-authored-by: noot <36753753+noot@users.noreply.github.com> Co-authored-by: noot <elizabethjbinks@gmail.com>
This commit is contained in:
co-authored by
noot
noot
parent
26816e2648
commit
792c1ff756
+4
-3
@@ -7,9 +7,10 @@ import (
|
||||
|
||||
// nolint
|
||||
const (
|
||||
ModuleName = types.ModuleName
|
||||
StoreKey = types.StoreKey
|
||||
RouterKey = types.RouterKey
|
||||
ModuleName = types.ModuleName
|
||||
StoreKey = types.StoreKey
|
||||
RouterKey = types.RouterKey
|
||||
DefaultParamspace = types.DefaultParamspace
|
||||
)
|
||||
|
||||
// nolint
|
||||
|
||||
+9
-2
@@ -28,6 +28,9 @@ func InitGenesis(ctx sdk.Context, k Keeper, data GenesisState) []abci.ValidatorU
|
||||
}
|
||||
}
|
||||
|
||||
k.SetChainConfig(ctx, data.ChainConfig)
|
||||
k.SetParams(ctx, data.Params)
|
||||
|
||||
// set state objects and code to store
|
||||
_, err = k.Commit(ctx, false)
|
||||
if err != nil {
|
||||
@@ -74,8 +77,12 @@ func ExportGenesis(ctx sdk.Context, k Keeper, ak types.AccountKeeper) GenesisSta
|
||||
ethGenAccounts = append(ethGenAccounts, genAccount)
|
||||
}
|
||||
|
||||
config, _ := k.GetChainConfig(ctx)
|
||||
|
||||
return GenesisState{
|
||||
Accounts: ethGenAccounts,
|
||||
TxsLogs: k.GetAllTxLogs(ctx),
|
||||
Accounts: ethGenAccounts,
|
||||
TxsLogs: k.GetAllTxLogs(ctx),
|
||||
ChainConfig: config,
|
||||
Params: k.GetParams(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
+12
-3
@@ -65,8 +65,12 @@ func handleMsgEthereumTx(ctx sdk.Context, k Keeper, msg types.MsgEthereumTx) (*s
|
||||
k.CommitStateDB.Prepare(ethHash, common.Hash{}, k.TxCount)
|
||||
k.TxCount++
|
||||
|
||||
// TODO: move to keeper
|
||||
executionResult, err := st.TransitionDb(ctx)
|
||||
config, found := k.GetChainConfig(ctx)
|
||||
if !found {
|
||||
return nil, types.ErrChainConfigNotFound
|
||||
}
|
||||
|
||||
executionResult, err := st.TransitionDb(ctx, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -142,7 +146,12 @@ func handleMsgEthermint(ctx sdk.Context, k Keeper, msg types.MsgEthermint) (*sdk
|
||||
k.CommitStateDB.Prepare(ethHash, common.Hash{}, k.TxCount)
|
||||
k.TxCount++
|
||||
|
||||
executionResult, err := st.TransitionDb(ctx)
|
||||
config, found := k.GetChainConfig(ctx)
|
||||
if !found {
|
||||
return nil, types.ErrChainConfigNotFound
|
||||
}
|
||||
|
||||
executionResult, err := st.TransitionDb(ctx, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+33
-3
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
@@ -28,7 +29,8 @@ type Keeper struct {
|
||||
// - storing transaction Logs
|
||||
// - storing block height -> bloom filter map. Needed for the Web3 API.
|
||||
// - storing block hash -> block height map. Needed for the Web3 API.
|
||||
storeKey sdk.StoreKey
|
||||
storeKey sdk.StoreKey
|
||||
// Ethermint concrete implementation on the EVM StateDB interface
|
||||
CommitStateDB *types.CommitStateDB
|
||||
// Transaction counter in a block. Used on StateSB's Prepare function.
|
||||
// It is reset to 0 every block on BeginBlock so there's no point in storing the counter
|
||||
@@ -39,12 +41,18 @@ type Keeper struct {
|
||||
|
||||
// NewKeeper generates new evm module keeper
|
||||
func NewKeeper(
|
||||
cdc *codec.Codec, storeKey sdk.StoreKey, ak types.AccountKeeper,
|
||||
cdc *codec.Codec, storeKey sdk.StoreKey, paramSpace params.Subspace, ak types.AccountKeeper,
|
||||
) Keeper {
|
||||
// set KeyTable if it has not already been set
|
||||
if !paramSpace.HasKeyTable() {
|
||||
paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable())
|
||||
}
|
||||
|
||||
// NOTE: we pass in the parameter space to the CommitStateDB in order to use custom denominations for the EVM operations
|
||||
return Keeper{
|
||||
cdc: cdc,
|
||||
storeKey: storeKey,
|
||||
CommitStateDB: types.NewCommitStateDB(sdk.Context{}, storeKey, ak),
|
||||
CommitStateDB: types.NewCommitStateDB(sdk.Context{}, storeKey, paramSpace, ak),
|
||||
TxCount: 0,
|
||||
Bloom: big.NewInt(0),
|
||||
}
|
||||
@@ -134,3 +142,25 @@ func (k Keeper) GetAccountStorage(ctx sdk.Context, address common.Address) (type
|
||||
|
||||
return storage, nil
|
||||
}
|
||||
|
||||
// GetChainConfig gets block height from block consensus hash
|
||||
func (k Keeper) GetChainConfig(ctx sdk.Context) (types.ChainConfig, bool) {
|
||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChainConfig)
|
||||
// get from an empty key that's already prefixed by KeyPrefixChainConfig
|
||||
bz := store.Get([]byte{})
|
||||
if len(bz) == 0 {
|
||||
return types.ChainConfig{}, false
|
||||
}
|
||||
|
||||
var config types.ChainConfig
|
||||
k.cdc.MustUnmarshalBinaryBare(bz, &config)
|
||||
return config, true
|
||||
}
|
||||
|
||||
// SetChainConfig sets the mapping from block consensus hash to block height
|
||||
func (k Keeper) SetChainConfig(ctx sdk.Context, config types.ChainConfig) {
|
||||
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixChainConfig)
|
||||
bz := k.cdc.MustMarshalBinaryBare(config)
|
||||
// get to an empty key that's already prefixed by KeyPrefixChainConfig
|
||||
store.Set([]byte{}, bz)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/cosmos/ethermint/app"
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/keeper"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
@@ -148,3 +149,15 @@ func (suite *KeeperTestSuite) TestDBStorage() {
|
||||
// simulate BaseApp EndBlocker commitment
|
||||
suite.app.Commit()
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestChainConfig() {
|
||||
config, found := suite.app.EvmKeeper.GetChainConfig(suite.ctx)
|
||||
suite.Require().True(found)
|
||||
suite.Require().Equal(types.DefaultChainConfig(), config)
|
||||
|
||||
config.EIP150Block = sdk.NewInt(100)
|
||||
suite.app.EvmKeeper.SetChainConfig(suite.ctx, config)
|
||||
newConfig, found := suite.app.EvmKeeper.GetChainConfig(suite.ctx)
|
||||
suite.Require().True(found)
|
||||
suite.Require().Equal(config, newConfig)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
// GetParams returns the total set of evm parameters.
|
||||
func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) {
|
||||
return k.CommitStateDB.WithContext(ctx).GetParams()
|
||||
}
|
||||
|
||||
// SetParams sets the evm parameters to the param space.
|
||||
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
|
||||
k.CommitStateDB.WithContext(ctx).SetParams(params)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestParams() {
|
||||
params := suite.app.EvmKeeper.GetParams(suite.ctx)
|
||||
suite.Require().Equal(types.DefaultParams(), params)
|
||||
params.EvmDenom = "ara"
|
||||
suite.app.EvmKeeper.SetParams(suite.ctx, params)
|
||||
newParams := suite.app.EvmKeeper.GetParams(suite.ctx)
|
||||
suite.Require().Equal(newParams, params)
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
|
||||
// NewQuerier is the module level router for state queries
|
||||
func NewQuerier(keeper Keeper) sdk.Querier {
|
||||
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
|
||||
return func(ctx sdk.Context, path []string, _ abci.RequestQuery) ([]byte, error) {
|
||||
switch path[0] {
|
||||
case types.QueryProtocolVersion:
|
||||
return queryProtocolVersion(keeper)
|
||||
@@ -203,7 +203,7 @@ func queryExportAccount(ctx sdk.Context, path []string, keeper Keeper) ([]byte,
|
||||
addr := ethcmn.HexToAddress(path[1])
|
||||
|
||||
var storage types.Storage
|
||||
err := keeper.CommitStateDB.ForEachStorage(addr, func(key, value ethcmn.Hash) bool {
|
||||
err := keeper.ForEachStorage(ctx, addr, func(key, value ethcmn.Hash) bool {
|
||||
storage = append(storage, types.NewState(key, value))
|
||||
return false
|
||||
})
|
||||
|
||||
@@ -18,8 +18,11 @@ var testJSON = `{
|
||||
"address": "0x2cc7fdf9fde6746731d7f11979609d455c2c197a",
|
||||
"balance": 0,
|
||||
"code": "0x60806040"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"params": {
|
||||
"evm_denom": "aphoton"
|
||||
}
|
||||
}`
|
||||
|
||||
func (suite *EvmTestSuite) TestInitGenesis() {
|
||||
|
||||
+159
-13
@@ -2,25 +2,171 @@ package types
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
// GenerateChainConfig returns an Ethereum chainconfig for EVM state transitions
|
||||
func GenerateChainConfig(chainID *big.Int) *params.ChainConfig {
|
||||
// TODO: Update chainconfig to take in parameters for fork blocks
|
||||
// ChainConfig defines the Ethereum ChainConfig parameters using sdk.Int values instead of big.Int.
|
||||
//
|
||||
// NOTE 1: Since empty/uninitialized Ints (i.e with a nil big.Int value) are parsed to zero, we need to manually
|
||||
// specify that negative Int values will be considered as nil. See getBlockValue for reference.
|
||||
//
|
||||
// NOTE 2: This type is not a configurable Param since the SDK does not allow for validation against
|
||||
// a previous stored parameter values or the current block height (retrieved from context). If you
|
||||
// want to update the config values, use an software upgrade procedure.
|
||||
type ChainConfig struct {
|
||||
HomesteadBlock sdk.Int `json:"homestead_block" yaml:"homestead_block"` // Homestead switch block (< 0 no fork, 0 = already homestead)
|
||||
|
||||
DAOForkBlock sdk.Int `json:"dao_fork_block" yaml:"dao_fork_block"` // TheDAO hard-fork switch block (< 0 no fork)
|
||||
DAOForkSupport bool `json:"dao_fork_support" yaml:"dao_fork_support"` // Whether the nodes supports or opposes the DAO hard-fork
|
||||
|
||||
// EIP150 implements the Gas price changes (https://github.com/ethereum/EIPs/issues/150)
|
||||
EIP150Block sdk.Int `json:"eip150_block" yaml:"eip150_block"` // EIP150 HF block (< 0 no fork)
|
||||
EIP150Hash string `json:"eip150_hash" yaml:"eip150_hash"` // EIP150 HF hash (needed for header only clients as only gas pricing changed)
|
||||
|
||||
EIP155Block sdk.Int `json:"eip155_block" yaml:"eip155_block"` // EIP155 HF block
|
||||
EIP158Block sdk.Int `json:"eip158_block" yaml:"eip158_block"` // EIP158 HF block
|
||||
|
||||
ByzantiumBlock sdk.Int `json:"byzantium_block" yaml:"byzantium_block"` // Byzantium switch block (< 0 no fork, 0 = already on byzantium)
|
||||
ConstantinopleBlock sdk.Int `json:"constantinople_block" yaml:"constantinople_block"` // Constantinople switch block (< 0 no fork, 0 = already activated)
|
||||
PetersburgBlock sdk.Int `json:"petersburg_block" yaml:"petersburg_block"` // Petersburg switch block (< 0 same as Constantinople)
|
||||
IstanbulBlock sdk.Int `json:"istanbul_block" yaml:"istanbul_block"` // Istanbul switch block (< 0 no fork, 0 = already on istanbul)
|
||||
MuirGlacierBlock sdk.Int `json:"muir_glacier_block" yaml:"muir_glacier_block"` // Eip-2384 (bomb delay) switch block (< 0 no fork, 0 = already activated)
|
||||
|
||||
YoloV1Block sdk.Int `json:"yoloV1_block" yaml:"yoloV1_block"` // YOLO v1: https://github.com/ethereum/EIPs/pull/2657 (Ephemeral testnet)
|
||||
EWASMBlock sdk.Int `json:"ewasm_block" yaml:"ewasm_block"` // EWASM switch block (< 0 no fork, 0 = already activated)
|
||||
}
|
||||
|
||||
// EthereumConfig returns an Ethereum ChainConfig for EVM state transitions.
|
||||
// All the negative or nil values are converted to nil
|
||||
func (cc ChainConfig) EthereumConfig(chainID *big.Int) *params.ChainConfig {
|
||||
return ¶ms.ChainConfig{
|
||||
ChainID: chainID,
|
||||
HomesteadBlock: big.NewInt(0),
|
||||
DAOForkBlock: big.NewInt(0),
|
||||
DAOForkSupport: true,
|
||||
EIP150Block: big.NewInt(0),
|
||||
EIP150Hash: common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
|
||||
EIP155Block: big.NewInt(0),
|
||||
EIP158Block: big.NewInt(0),
|
||||
ByzantiumBlock: big.NewInt(0),
|
||||
ConstantinopleBlock: big.NewInt(0),
|
||||
PetersburgBlock: big.NewInt(0),
|
||||
HomesteadBlock: getBlockValue(cc.HomesteadBlock),
|
||||
DAOForkBlock: getBlockValue(cc.DAOForkBlock),
|
||||
DAOForkSupport: cc.DAOForkSupport,
|
||||
EIP150Block: getBlockValue(cc.EIP150Block),
|
||||
EIP150Hash: common.HexToHash(cc.EIP150Hash),
|
||||
EIP155Block: getBlockValue(cc.EIP155Block),
|
||||
EIP158Block: getBlockValue(cc.EIP158Block),
|
||||
ByzantiumBlock: getBlockValue(cc.ByzantiumBlock),
|
||||
ConstantinopleBlock: getBlockValue(cc.ConstantinopleBlock),
|
||||
PetersburgBlock: getBlockValue(cc.PetersburgBlock),
|
||||
IstanbulBlock: getBlockValue(cc.IstanbulBlock),
|
||||
MuirGlacierBlock: getBlockValue(cc.MuirGlacierBlock),
|
||||
YoloV1Block: getBlockValue(cc.YoloV1Block),
|
||||
EWASMBlock: getBlockValue(cc.EWASMBlock),
|
||||
}
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface
|
||||
func (cc ChainConfig) String() string {
|
||||
out, _ := yaml.Marshal(cc)
|
||||
return string(out)
|
||||
}
|
||||
|
||||
// DefaultChainConfig returns default evm parameters. Th
|
||||
func DefaultChainConfig() ChainConfig {
|
||||
return ChainConfig{
|
||||
HomesteadBlock: sdk.ZeroInt(),
|
||||
DAOForkBlock: sdk.ZeroInt(),
|
||||
DAOForkSupport: true,
|
||||
EIP150Block: sdk.ZeroInt(),
|
||||
EIP150Hash: common.Hash{}.String(),
|
||||
EIP155Block: sdk.ZeroInt(),
|
||||
EIP158Block: sdk.ZeroInt(),
|
||||
ByzantiumBlock: sdk.ZeroInt(),
|
||||
ConstantinopleBlock: sdk.ZeroInt(),
|
||||
PetersburgBlock: sdk.ZeroInt(),
|
||||
IstanbulBlock: sdk.NewInt(-1),
|
||||
MuirGlacierBlock: sdk.NewInt(-1),
|
||||
YoloV1Block: sdk.NewInt(-1),
|
||||
EWASMBlock: sdk.NewInt(-1),
|
||||
}
|
||||
}
|
||||
|
||||
func getBlockValue(block sdk.Int) *big.Int {
|
||||
if block.IsNegative() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return block.BigInt()
|
||||
}
|
||||
|
||||
// Validate performs a basic validation of the ChainConfig params. The function will return an error
|
||||
// if any of the block values is uninitialized (i.e nil) or if the EIP150Hash is an invalid hash.
|
||||
func (cc ChainConfig) Validate() error {
|
||||
if err := validateBlock(cc.HomesteadBlock); err != nil {
|
||||
return sdkerrors.Wrap(err, "homesteadBlock")
|
||||
}
|
||||
if err := validateBlock(cc.DAOForkBlock); err != nil {
|
||||
return sdkerrors.Wrap(err, "daoForkBlock")
|
||||
}
|
||||
if err := validateBlock(cc.EIP150Block); err != nil {
|
||||
return sdkerrors.Wrap(err, "eip150Block")
|
||||
}
|
||||
if err := validateHash(cc.EIP150Hash); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateBlock(cc.EIP155Block); err != nil {
|
||||
return sdkerrors.Wrap(err, "eip155Block")
|
||||
}
|
||||
if err := validateBlock(cc.EIP158Block); err != nil {
|
||||
return sdkerrors.Wrap(err, "eip158Block")
|
||||
}
|
||||
if err := validateBlock(cc.ByzantiumBlock); err != nil {
|
||||
return sdkerrors.Wrap(err, "byzantiumBlock")
|
||||
}
|
||||
if err := validateBlock(cc.ConstantinopleBlock); err != nil {
|
||||
return sdkerrors.Wrap(err, "constantinopleBlock")
|
||||
}
|
||||
if err := validateBlock(cc.PetersburgBlock); err != nil {
|
||||
return sdkerrors.Wrap(err, "petersburgBlock")
|
||||
}
|
||||
if err := validateBlock(cc.IstanbulBlock); err != nil {
|
||||
return sdkerrors.Wrap(err, "istanbulBlock")
|
||||
}
|
||||
if err := validateBlock(cc.MuirGlacierBlock); err != nil {
|
||||
return sdkerrors.Wrap(err, "muirGlacierBlock")
|
||||
}
|
||||
if err := validateBlock(cc.YoloV1Block); err != nil {
|
||||
return sdkerrors.Wrap(err, "yoloV1Block")
|
||||
}
|
||||
if err := validateBlock(cc.EWASMBlock); err != nil {
|
||||
return sdkerrors.Wrap(err, "eWASMBlock")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateHash(hex string) error {
|
||||
if hex != "" && strings.TrimSpace(hex) == "" {
|
||||
return sdkerrors.Wrapf(ErrInvalidChainConfig, "hash cannot be blank")
|
||||
}
|
||||
|
||||
bz := common.FromHex(hex)
|
||||
lenHex := len(bz)
|
||||
if lenHex > 0 && lenHex != common.HashLength {
|
||||
return sdkerrors.Wrapf(ErrInvalidChainConfig, "invalid hash length, expected %d, got %d", common.HashLength, lenHex)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateBlock(block sdk.Int) error {
|
||||
if block == (sdk.Int{}) || block.BigInt() == nil {
|
||||
return sdkerrors.Wrapf(
|
||||
ErrInvalidChainConfig,
|
||||
"cannot use uninitialized or nil values for Int, set a negative Int value if you want to define a nil Ethereum block",
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
var defaultEIP150Hash = common.Hash{}.String()
|
||||
|
||||
func TestChainConfigValidate(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
config ChainConfig
|
||||
expError bool
|
||||
}{
|
||||
{"default", DefaultChainConfig(), false},
|
||||
{
|
||||
"valid",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.OneInt(),
|
||||
EIP150Hash: defaultEIP150Hash,
|
||||
EIP155Block: sdk.OneInt(),
|
||||
EIP158Block: sdk.OneInt(),
|
||||
ByzantiumBlock: sdk.OneInt(),
|
||||
ConstantinopleBlock: sdk.OneInt(),
|
||||
PetersburgBlock: sdk.OneInt(),
|
||||
IstanbulBlock: sdk.OneInt(),
|
||||
MuirGlacierBlock: sdk.OneInt(),
|
||||
YoloV1Block: sdk.OneInt(),
|
||||
EWASMBlock: sdk.OneInt(),
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"empty",
|
||||
ChainConfig{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid HomesteadBlock",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid DAOForkBlock",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid EIP150Block",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid EIP150Hash",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.OneInt(),
|
||||
EIP150Hash: " ",
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid EIP155Block",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.OneInt(),
|
||||
EIP150Hash: defaultEIP150Hash,
|
||||
EIP155Block: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid EIP158Block",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.OneInt(),
|
||||
EIP150Hash: defaultEIP150Hash,
|
||||
EIP155Block: sdk.OneInt(),
|
||||
EIP158Block: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid ByzantiumBlock",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.OneInt(),
|
||||
EIP150Hash: defaultEIP150Hash,
|
||||
EIP155Block: sdk.OneInt(),
|
||||
EIP158Block: sdk.OneInt(),
|
||||
ByzantiumBlock: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid ConstantinopleBlock",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.OneInt(),
|
||||
EIP150Hash: defaultEIP150Hash,
|
||||
EIP155Block: sdk.OneInt(),
|
||||
EIP158Block: sdk.OneInt(),
|
||||
ByzantiumBlock: sdk.OneInt(),
|
||||
ConstantinopleBlock: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid PetersburgBlock",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.OneInt(),
|
||||
EIP150Hash: defaultEIP150Hash,
|
||||
EIP155Block: sdk.OneInt(),
|
||||
EIP158Block: sdk.OneInt(),
|
||||
ByzantiumBlock: sdk.OneInt(),
|
||||
ConstantinopleBlock: sdk.OneInt(),
|
||||
PetersburgBlock: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid IstanbulBlock",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.OneInt(),
|
||||
EIP150Hash: defaultEIP150Hash,
|
||||
EIP155Block: sdk.OneInt(),
|
||||
EIP158Block: sdk.OneInt(),
|
||||
ByzantiumBlock: sdk.OneInt(),
|
||||
ConstantinopleBlock: sdk.OneInt(),
|
||||
PetersburgBlock: sdk.OneInt(),
|
||||
IstanbulBlock: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid MuirGlacierBlock",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.OneInt(),
|
||||
EIP150Hash: defaultEIP150Hash,
|
||||
EIP155Block: sdk.OneInt(),
|
||||
EIP158Block: sdk.OneInt(),
|
||||
ByzantiumBlock: sdk.OneInt(),
|
||||
ConstantinopleBlock: sdk.OneInt(),
|
||||
PetersburgBlock: sdk.OneInt(),
|
||||
IstanbulBlock: sdk.OneInt(),
|
||||
MuirGlacierBlock: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid YoloV1Block",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.OneInt(),
|
||||
EIP150Hash: defaultEIP150Hash,
|
||||
EIP155Block: sdk.OneInt(),
|
||||
EIP158Block: sdk.OneInt(),
|
||||
ByzantiumBlock: sdk.OneInt(),
|
||||
ConstantinopleBlock: sdk.OneInt(),
|
||||
PetersburgBlock: sdk.OneInt(),
|
||||
IstanbulBlock: sdk.OneInt(),
|
||||
MuirGlacierBlock: sdk.OneInt(),
|
||||
YoloV1Block: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid EWASMBlock",
|
||||
ChainConfig{
|
||||
HomesteadBlock: sdk.OneInt(),
|
||||
DAOForkBlock: sdk.OneInt(),
|
||||
EIP150Block: sdk.OneInt(),
|
||||
EIP150Hash: defaultEIP150Hash,
|
||||
EIP155Block: sdk.OneInt(),
|
||||
EIP158Block: sdk.OneInt(),
|
||||
ByzantiumBlock: sdk.OneInt(),
|
||||
ConstantinopleBlock: sdk.OneInt(),
|
||||
PetersburgBlock: sdk.OneInt(),
|
||||
IstanbulBlock: sdk.OneInt(),
|
||||
MuirGlacierBlock: sdk.OneInt(),
|
||||
YoloV1Block: sdk.OneInt(),
|
||||
EWASMBlock: sdk.Int{},
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
err := tc.config.Validate()
|
||||
|
||||
if tc.expError {
|
||||
require.Error(t, err, tc.name)
|
||||
} else {
|
||||
require.NoError(t, err, tc.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestChainConfig_String(t *testing.T) {
|
||||
configStr := `homestead_block: "0"
|
||||
dao_fork_block: "0"
|
||||
dao_fork_support: true
|
||||
eip150_block: "0"
|
||||
eip150_hash: "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
eip155_block: "0"
|
||||
eip158_block: "0"
|
||||
byzantium_block: "0"
|
||||
constantinople_block: "0"
|
||||
petersburg_block: "0"
|
||||
istanbul_block: "-1"
|
||||
muir_glacier_block: "-1"
|
||||
yoloV1_block: "-1"
|
||||
ewasm_block: "-1"
|
||||
`
|
||||
require.Equal(t, configStr, DefaultChainConfig().String())
|
||||
}
|
||||
@@ -13,6 +13,7 @@ func RegisterCodec(cdc *codec.Codec) {
|
||||
cdc.RegisterConcrete(MsgEthereumTx{}, "ethermint/MsgEthereumTx", nil)
|
||||
cdc.RegisterConcrete(MsgEthermint{}, "ethermint/MsgEthermint", nil)
|
||||
cdc.RegisterConcrete(TxData{}, "ethermint/TxData", nil)
|
||||
cdc.RegisterConcrete(ChainConfig{}, "ethermint/ChainConfig", nil)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
@@ -9,4 +9,10 @@ import (
|
||||
var (
|
||||
// ErrInvalidState returns an error resulting from an invalid Storage State.
|
||||
ErrInvalidState = sdkerrors.Register(ModuleName, 2, "invalid storage state")
|
||||
|
||||
// ErrChainConfigNotFound returns an error if the chain config cannot be found on the store.
|
||||
ErrChainConfigNotFound = sdkerrors.Register(ModuleName, 3, "chain configuration not found")
|
||||
|
||||
// ErrInvalidChainConfig returns an error resulting from an invalid ChainConfig.
|
||||
ErrInvalidChainConfig = sdkerrors.Register(ModuleName, 4, "invalid chain configuration")
|
||||
)
|
||||
|
||||
+15
-6
@@ -13,8 +13,10 @@ import (
|
||||
type (
|
||||
// GenesisState defines the evm module genesis state
|
||||
GenesisState struct {
|
||||
Accounts []GenesisAccount `json:"accounts"`
|
||||
TxsLogs []TransactionLogs `json:"txs_logs"`
|
||||
Accounts []GenesisAccount `json:"accounts"`
|
||||
TxsLogs []TransactionLogs `json:"txs_logs"`
|
||||
ChainConfig ChainConfig `json:"chain_config"`
|
||||
Params Params `json:"params"`
|
||||
}
|
||||
|
||||
// GenesisAccount defines an account to be initialized in the genesis state.
|
||||
@@ -46,11 +48,14 @@ func (ga GenesisAccount) Validate() error {
|
||||
return ga.Storage.Validate()
|
||||
}
|
||||
|
||||
// DefaultGenesisState sets default evm genesis state with empty accounts.
|
||||
// DefaultGenesisState sets default evm genesis state with empty accounts and default params and
|
||||
// chain config values.
|
||||
func DefaultGenesisState() GenesisState {
|
||||
return GenesisState{
|
||||
Accounts: []GenesisAccount{},
|
||||
TxsLogs: []TransactionLogs{},
|
||||
Accounts: []GenesisAccount{},
|
||||
TxsLogs: []TransactionLogs{},
|
||||
ChainConfig: DefaultChainConfig(),
|
||||
Params: DefaultParams(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,5 +85,9 @@ func (gs GenesisState) Validate() error {
|
||||
seenTxs[tx.Hash.String()] = true
|
||||
}
|
||||
|
||||
return nil
|
||||
if err := gs.ChainConfig.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return gs.Params.Validate()
|
||||
}
|
||||
|
||||
@@ -122,9 +122,16 @@ func TestValidateGenesis(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
ChainConfig: DefaultChainConfig(),
|
||||
Params: DefaultParams(),
|
||||
},
|
||||
expPass: true,
|
||||
},
|
||||
{
|
||||
name: "empty genesis",
|
||||
genState: GenesisState{},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid genesis",
|
||||
genState: GenesisState{
|
||||
@@ -227,6 +234,22 @@ func TestValidateGenesis(t *testing.T) {
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid params",
|
||||
genState: GenesisState{
|
||||
ChainConfig: DefaultChainConfig(),
|
||||
Params: Params{},
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
{
|
||||
name: "invalid chain config",
|
||||
genState: GenesisState{
|
||||
ChainConfig: ChainConfig{},
|
||||
Params: DefaultParams(),
|
||||
},
|
||||
expPass: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/store"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
@@ -119,11 +120,12 @@ func (suite *JournalTestSuite) setup() {
|
||||
paramsKeeper := params.NewKeeper(cdc, keyParams, tkeyParams)
|
||||
|
||||
authSubspace := paramsKeeper.Subspace(auth.DefaultParamspace)
|
||||
evmSubspace := paramsKeeper.Subspace(types.DefaultParamspace)
|
||||
|
||||
ak := auth.NewAccountKeeper(cdc, authKey, authSubspace, ethermint.ProtoAccount)
|
||||
|
||||
suite.ctx = sdk.NewContext(cms, abci.Header{ChainID: "8"}, false, tmlog.NewNopLogger())
|
||||
suite.stateDB = NewCommitStateDB(suite.ctx, storeKey, ak).WithContext(suite.ctx)
|
||||
suite.stateDB = NewCommitStateDB(suite.ctx, storeKey, evmSubspace, ak).WithContext(suite.ctx)
|
||||
}
|
||||
|
||||
func TestJournalTestSuite(t *testing.T) {
|
||||
|
||||
+6
-5
@@ -21,11 +21,12 @@ const (
|
||||
|
||||
// KVStore key prefixes
|
||||
var (
|
||||
KeyPrefixBlockHash = []byte{0x01}
|
||||
KeyPrefixBloom = []byte{0x02}
|
||||
KeyPrefixLogs = []byte{0x03}
|
||||
KeyPrefixCode = []byte{0x04}
|
||||
KeyPrefixStorage = []byte{0x05}
|
||||
KeyPrefixBlockHash = []byte{0x01}
|
||||
KeyPrefixBloom = []byte{0x02}
|
||||
KeyPrefixLogs = []byte{0x03}
|
||||
KeyPrefixCode = []byte{0x04}
|
||||
KeyPrefixStorage = []byte{0x05}
|
||||
KeyPrefixChainConfig = []byte{0x06}
|
||||
)
|
||||
|
||||
// BloomKey defines the store key for a block Bloom
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultParamspace for params keeper
|
||||
DefaultParamspace = ModuleName
|
||||
)
|
||||
|
||||
// Parameter keys
|
||||
var (
|
||||
ParamStoreKeyEVMDenom = []byte("EVMDenom")
|
||||
)
|
||||
|
||||
// ParamKeyTable returns the parameter key table.
|
||||
func ParamKeyTable() params.KeyTable {
|
||||
return params.NewKeyTable().RegisterParamSet(&Params{})
|
||||
}
|
||||
|
||||
// Params defines the EVM module parameters
|
||||
type Params struct {
|
||||
EvmDenom string `json:"evm_denom" yaml:"evm_denom"`
|
||||
}
|
||||
|
||||
// NewParams creates a new Params instance
|
||||
func NewParams(evmDenom string) Params {
|
||||
return Params{
|
||||
EvmDenom: evmDenom,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultParams returns default evm parameters
|
||||
func DefaultParams() Params {
|
||||
return Params{
|
||||
EvmDenom: ethermint.DenomDefault,
|
||||
}
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface
|
||||
func (p Params) String() string {
|
||||
out, _ := yaml.Marshal(p)
|
||||
return string(out)
|
||||
}
|
||||
|
||||
// ParamSetPairs returns the parameter set pairs.
|
||||
func (p *Params) ParamSetPairs() params.ParamSetPairs {
|
||||
return params.ParamSetPairs{
|
||||
params.NewParamSetPair(ParamStoreKeyEVMDenom, &p.EvmDenom, validateEVMDenom),
|
||||
}
|
||||
}
|
||||
|
||||
// Validate performs basic validation on evm parameters.
|
||||
func (p Params) Validate() error {
|
||||
return sdk.ValidateDenom(p.EvmDenom)
|
||||
}
|
||||
|
||||
func validateEVMDenom(i interface{}) error {
|
||||
denom, ok := i.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid parameter type: %T", i)
|
||||
}
|
||||
|
||||
return sdk.ValidateDenom(denom)
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParamsValidate(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
params Params
|
||||
expError bool
|
||||
}{
|
||||
{"default", DefaultParams(), false},
|
||||
{
|
||||
"valid",
|
||||
NewParams("ara"),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"empty",
|
||||
Params{},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid evm denom",
|
||||
Params{
|
||||
EvmDenom: "@!#!@$!@5^32",
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
err := tc.params.Validate()
|
||||
|
||||
if tc.expError {
|
||||
require.Error(t, err, tc.name)
|
||||
} else {
|
||||
require.NoError(t, err, tc.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParamsValidatePriv(t *testing.T) {
|
||||
require.Error(t, validateEVMDenom(false))
|
||||
}
|
||||
|
||||
func TestParams_String(t *testing.T) {
|
||||
require.Equal(t, "evm_denom: aphoton\n", DefaultParams().String())
|
||||
}
|
||||
@@ -176,8 +176,8 @@ func (so *stateObject) AddBalance(amount *big.Int) {
|
||||
return
|
||||
}
|
||||
|
||||
// newBalance := so.balance.Add(amt)
|
||||
newBalance := so.account.GetCoins().AmountOf(types.DenomDefault).Add(amt)
|
||||
evmDenom := so.stateDB.GetParams().EvmDenom
|
||||
newBalance := so.account.GetCoins().AmountOf(evmDenom).Add(amt)
|
||||
so.SetBalance(newBalance.BigInt())
|
||||
}
|
||||
|
||||
@@ -188,7 +188,9 @@ func (so *stateObject) SubBalance(amount *big.Int) {
|
||||
if amt.IsZero() {
|
||||
return
|
||||
}
|
||||
newBalance := so.account.GetCoins().AmountOf(types.DenomDefault).Sub(amt)
|
||||
|
||||
evmDenom := so.stateDB.GetParams().EvmDenom
|
||||
newBalance := so.account.GetCoins().AmountOf(evmDenom).Sub(amt)
|
||||
so.SetBalance(newBalance.BigInt())
|
||||
}
|
||||
|
||||
@@ -196,9 +198,10 @@ func (so *stateObject) SubBalance(amount *big.Int) {
|
||||
func (so *stateObject) SetBalance(amount *big.Int) {
|
||||
amt := sdk.NewIntFromBigInt(amount)
|
||||
|
||||
evmDenom := so.stateDB.GetParams().EvmDenom
|
||||
so.stateDB.journal.append(balanceChange{
|
||||
account: &so.address,
|
||||
prev: so.account.GetCoins().AmountOf(types.DenomDefault),
|
||||
prev: so.account.GetCoins().AmountOf(evmDenom),
|
||||
})
|
||||
|
||||
so.setBalance(amt)
|
||||
|
||||
@@ -10,8 +10,6 @@ import (
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
|
||||
emint "github.com/cosmos/ethermint/types"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
)
|
||||
@@ -49,7 +47,7 @@ type ExecutionResult struct {
|
||||
GasInfo GasInfo
|
||||
}
|
||||
|
||||
func (st StateTransition) newEVM(ctx sdk.Context, csdb *CommitStateDB, gasLimit uint64, gasPrice *big.Int) *vm.EVM {
|
||||
func (st StateTransition) newEVM(ctx sdk.Context, csdb *CommitStateDB, gasLimit uint64, gasPrice *big.Int, config ChainConfig) *vm.EVM {
|
||||
// Create context for evm
|
||||
context := vm.Context{
|
||||
CanTransfer: core.CanTransfer,
|
||||
@@ -63,13 +61,13 @@ func (st StateTransition) newEVM(ctx sdk.Context, csdb *CommitStateDB, gasLimit
|
||||
GasPrice: gasPrice,
|
||||
}
|
||||
|
||||
return vm.NewEVM(context, csdb, GenerateChainConfig(st.ChainID), vm.Config{})
|
||||
return vm.NewEVM(context, csdb, config.EthereumConfig(st.ChainID), vm.Config{})
|
||||
}
|
||||
|
||||
// TransitionDb will transition the state by applying the current transaction and
|
||||
// returning the evm execution result.
|
||||
// NOTE: State transition checks are run during AnteHandler execution.
|
||||
func (st StateTransition) TransitionDb(ctx sdk.Context) (*ExecutionResult, error) {
|
||||
func (st StateTransition) TransitionDb(ctx sdk.Context, config ChainConfig) (*ExecutionResult, error) {
|
||||
contractCreation := st.Recipient == nil
|
||||
|
||||
cost, err := core.IntrinsicGas(st.Payload, contractCreation, true, false)
|
||||
@@ -103,12 +101,13 @@ func (st StateTransition) TransitionDb(ctx sdk.Context) (*ExecutionResult, error
|
||||
// Clear cache of accounts to handle changes outside of the EVM
|
||||
csdb.UpdateAccounts()
|
||||
|
||||
gasPrice := ctx.MinGasPrices().AmountOf(emint.DenomDefault)
|
||||
evmDenom := csdb.GetParams().EvmDenom
|
||||
gasPrice := ctx.MinGasPrices().AmountOf(evmDenom)
|
||||
if gasPrice.IsNil() {
|
||||
return nil, errors.New("gas price cannot be nil")
|
||||
}
|
||||
|
||||
evm := st.newEVM(ctx, csdb, gasLimit, gasPrice.Int)
|
||||
evm := st.newEVM(ctx, csdb, gasLimit, gasPrice.Int, config)
|
||||
|
||||
var (
|
||||
ret []byte
|
||||
|
||||
@@ -132,7 +132,7 @@ func (suite *StateDBTestSuite) TestTransitionDb() {
|
||||
for _, tc := range testCase {
|
||||
tc.malleate()
|
||||
|
||||
_, err = tc.state.TransitionDb(suite.ctx)
|
||||
_, err = tc.state.TransitionDb(suite.ctx, types.DefaultChainConfig())
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err, tc.name)
|
||||
|
||||
+23
-8
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/params"
|
||||
|
||||
emint "github.com/cosmos/ethermint/types"
|
||||
|
||||
@@ -42,6 +43,7 @@ type CommitStateDB struct {
|
||||
ctx sdk.Context
|
||||
|
||||
storeKey sdk.StoreKey
|
||||
paramSpace params.Subspace
|
||||
accountKeeper AccountKeeper
|
||||
|
||||
// array that hold 'live' objects, which will get modified while processing a
|
||||
@@ -85,11 +87,12 @@ type CommitStateDB struct {
|
||||
// CONTRACT: Stores used for state must be cache-wrapped as the ordering of the
|
||||
// key/value space matters in determining the merkle root.
|
||||
func NewCommitStateDB(
|
||||
ctx sdk.Context, storeKey sdk.StoreKey, ak AccountKeeper,
|
||||
ctx sdk.Context, storeKey sdk.StoreKey, paramSpace params.Subspace, ak AccountKeeper,
|
||||
) *CommitStateDB {
|
||||
return &CommitStateDB{
|
||||
ctx: ctx,
|
||||
storeKey: storeKey,
|
||||
paramSpace: paramSpace,
|
||||
accountKeeper: ak,
|
||||
stateObjects: []stateEntry{},
|
||||
addressToObjectIndex: make(map[ethcmn.Address]int),
|
||||
@@ -110,6 +113,11 @@ func (csdb *CommitStateDB) WithContext(ctx sdk.Context) *CommitStateDB {
|
||||
// Setters
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// SetParams sets the evm parameters to the param space.
|
||||
func (csdb *CommitStateDB) SetParams(params Params) {
|
||||
csdb.paramSpace.SetParamSet(csdb.ctx, ¶ms)
|
||||
}
|
||||
|
||||
// SetBalance sets the balance of an account.
|
||||
func (csdb *CommitStateDB) SetBalance(addr ethcmn.Address, amount *big.Int) {
|
||||
so := csdb.GetOrNewStateObject(addr)
|
||||
@@ -239,6 +247,12 @@ func (csdb *CommitStateDB) SubRefund(gas uint64) {
|
||||
// Getters
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// GetParams returns the total set of evm parameters.
|
||||
func (csdb *CommitStateDB) GetParams() (params Params) {
|
||||
csdb.paramSpace.GetParamSet(csdb.ctx, ¶ms)
|
||||
return params
|
||||
}
|
||||
|
||||
// GetBalance retrieves the balance from the given address or 0 if object not
|
||||
// found.
|
||||
func (csdb *CommitStateDB) GetBalance(addr ethcmn.Address) *big.Int {
|
||||
@@ -489,8 +503,9 @@ func (csdb *CommitStateDB) IntermediateRoot(deleteEmptyObjects bool) (ethcmn.Has
|
||||
|
||||
// updateStateObject writes the given state object to the store.
|
||||
func (csdb *CommitStateDB) updateStateObject(so *stateObject) error {
|
||||
evmDenom := csdb.GetParams().EvmDenom
|
||||
// NOTE: we don't use sdk.NewCoin here to avoid panic on test importer's genesis
|
||||
newBalance := sdk.Coin{Denom: emint.DenomDefault, Amount: sdk.NewIntFromBigInt(so.Balance())}
|
||||
newBalance := sdk.Coin{Denom: evmDenom, Amount: sdk.NewIntFromBigInt(so.Balance())}
|
||||
if !newBalance.IsValid() {
|
||||
return fmt.Errorf("invalid balance %s", newBalance)
|
||||
}
|
||||
@@ -631,9 +646,10 @@ func (csdb *CommitStateDB) UpdateAccounts() {
|
||||
continue
|
||||
}
|
||||
|
||||
evmDenom := csdb.GetParams().EvmDenom
|
||||
balance := sdk.Coin{
|
||||
Denom: emint.DenomDefault,
|
||||
Amount: emintAcc.GetCoins().AmountOf(emint.DenomDefault),
|
||||
Denom: evmDenom,
|
||||
Amount: emintAcc.GetCoins().AmountOf(evmDenom),
|
||||
}
|
||||
|
||||
if stateEntry.stateObject.Balance() != balance.Amount.BigInt() && balance.IsValid() ||
|
||||
@@ -692,6 +708,7 @@ func (csdb *CommitStateDB) Copy() *CommitStateDB {
|
||||
state := &CommitStateDB{
|
||||
ctx: csdb.ctx,
|
||||
storeKey: csdb.storeKey,
|
||||
paramSpace: csdb.paramSpace,
|
||||
accountKeeper: csdb.accountKeeper,
|
||||
stateObjects: []stateEntry{},
|
||||
addressToObjectIndex: make(map[ethcmn.Address]int),
|
||||
@@ -815,8 +832,7 @@ func (csdb *CommitStateDB) setError(err error) {
|
||||
// getStateObject attempts to retrieve a state object given by the address.
|
||||
// Returns nil and sets an error if not found.
|
||||
func (csdb *CommitStateDB) getStateObject(addr ethcmn.Address) (stateObject *stateObject) {
|
||||
idx, found := csdb.addressToObjectIndex[addr]
|
||||
if found {
|
||||
if idx, found := csdb.addressToObjectIndex[addr]; found {
|
||||
// prefer 'live' (cached) objects
|
||||
if so := csdb.stateObjects[idx].stateObject; so != nil {
|
||||
if so.deleted {
|
||||
@@ -842,8 +858,7 @@ func (csdb *CommitStateDB) getStateObject(addr ethcmn.Address) (stateObject *sta
|
||||
}
|
||||
|
||||
func (csdb *CommitStateDB) setStateObject(so *stateObject) {
|
||||
idx, found := csdb.addressToObjectIndex[so.Address()]
|
||||
if found {
|
||||
if idx, found := csdb.addressToObjectIndex[so.Address()]; found {
|
||||
// update the existing object
|
||||
csdb.stateObjects[idx].stateObject = so
|
||||
return
|
||||
|
||||
@@ -57,6 +57,16 @@ func (suite *StateDBTestSuite) SetupTest() {
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
suite.stateObject = suite.stateDB.GetOrNewStateObject(suite.address)
|
||||
}
|
||||
|
||||
func (suite *StateDBTestSuite) TestParams() {
|
||||
params := suite.stateDB.GetParams()
|
||||
suite.Require().Equal(types.DefaultParams(), params)
|
||||
params.EvmDenom = "ara"
|
||||
suite.stateDB.SetParams(params)
|
||||
newParams := suite.stateDB.GetParams()
|
||||
suite.Require().Equal(newParams, params)
|
||||
}
|
||||
|
||||
func (suite *StateDBTestSuite) TestBloomFilter() {
|
||||
// Prepare db for logs
|
||||
tHash := ethcmn.BytesToHash([]byte{0x1})
|
||||
|
||||
Reference in New Issue
Block a user