diff --git a/app/ante/eth.go b/app/ante/eth.go index 669afccf3c..2402167be7 100644 --- a/app/ante/eth.go +++ b/app/ante/eth.go @@ -88,7 +88,7 @@ func (avd EthAccountVerificationDecorator) AnteHandle( if acct == nil { acc := avd.ak.NewAccountWithAddress(ctx, from) avd.ak.SetAccount(ctx, acc) - acct = evmtypes.NewEmptyAccount() + acct = statedb.NewEmptyAccount() } else if acct.IsContract() { return ctx, errorsmod.Wrapf(errortypes.ErrInvalidType, "the sender is not EOA: address %s, codeHash <%s>", fromAddr, acct.CodeHash) @@ -302,7 +302,7 @@ func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate BaseFee: baseFee, } - stateDB := statedb.New(ctx, ctd.evmKeeper, evmtypes.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes()))) + stateDB := statedb.New(ctx, ctd.evmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes()))) evm := ctd.evmKeeper.NewEVM(ctx, coreMsg, cfg, evmtypes.NewNoOpTracer(), stateDB) // check that caller has enough balance to cover asset transfer for **topmost** call diff --git a/app/ante/eth_test.go b/app/ante/eth_test.go index b5dd9dd7f1..0fb9ea8b20 100644 --- a/app/ante/eth_test.go +++ b/app/ante/eth_test.go @@ -10,8 +10,8 @@ import ( "github.com/evmos/ethermint/server/config" "github.com/evmos/ethermint/tests" ethermint "github.com/evmos/ethermint/types" + "github.com/evmos/ethermint/x/evm/statedb" evmtypes "github.com/evmos/ethermint/x/evm/types" - "github.com/evmos/ethermint/x/evm/vm" ethtypes "github.com/ethereum/go-ethereum/core/types" ) @@ -26,7 +26,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() { tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil) tx.From = addr.Hex() - var vmdb vm.StateDB + var vmdb *statedb.StateDB testCases := []struct { name string @@ -192,7 +192,7 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() { dynamicFeeTx.From = addr.Hex() dynamicFeeTxPriority := int64(1) - var vmdb vm.StateDB + var vmdb *statedb.StateDB testCases := []struct { name string @@ -352,7 +352,7 @@ func (suite AnteTestSuite) TestCanTransferDecorator() { err := tx.Sign(suite.ethSigner, tests.NewSigner(privKey)) suite.Require().NoError(err) - var vmdb vm.StateDB + var vmdb *statedb.StateDB testCases := []struct { name string diff --git a/app/ante/interfaces.go b/app/ante/interfaces.go index c2bb63cd62..e48e0a50a4 100644 --- a/app/ante/interfaces.go +++ b/app/ante/interfaces.go @@ -41,7 +41,7 @@ type DynamicFeeEVMKeeper interface { // EVMKeeper defines the expected keeper interface used on the Eth AnteHandler type EVMKeeper interface { - evm.StateDBKeeper + statedb.Keeper DynamicFeeEVMKeeper NewEVM(ctx sdk.Context, msg core.Message, cfg *statedb.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) evm.EVM diff --git a/app/ante/sigs_test.go b/app/ante/sigs_test.go index be87ab15f3..0c7b0539c8 100644 --- a/app/ante/sigs_test.go +++ b/app/ante/sigs_test.go @@ -4,7 +4,7 @@ import ( "math/big" "github.com/evmos/ethermint/tests" - "github.com/evmos/ethermint/x/evm/types" + "github.com/evmos/ethermint/x/evm/statedb" evmtypes "github.com/evmos/ethermint/x/evm/types" ) @@ -15,7 +15,7 @@ func (suite AnteTestSuite) TestSignatures() { addr, privKey := tests.NewAddrKey() to := tests.GenerateAddress() - acc := types.NewEmptyAccount() + acc := statedb.NewEmptyAccount() acc.Nonce = 1 acc.Balance = big.NewInt(10000000000) diff --git a/app/ante/utils_test.go b/app/ante/utils_test.go index e87c82e839..c92961c391 100644 --- a/app/ante/utils_test.go +++ b/app/ante/utils_test.go @@ -53,7 +53,6 @@ import ( "github.com/evmos/ethermint/tests" "github.com/evmos/ethermint/x/evm/statedb" evmtypes "github.com/evmos/ethermint/x/evm/types" - "github.com/evmos/ethermint/x/evm/vm" feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -74,8 +73,8 @@ type AnteTestSuite struct { const TestGasLimit uint64 = 100000 -func (suite *AnteTestSuite) StateDB() vm.StateDB { - return statedb.New(suite.ctx, suite.app.EvmKeeper, evmtypes.NewEmptyTxConfig(common.BytesToHash(suite.ctx.HeaderHash().Bytes()))) +func (suite *AnteTestSuite) StateDB() *statedb.StateDB { + return statedb.New(suite.ctx, suite.app.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(suite.ctx.HeaderHash().Bytes()))) } func (suite *AnteTestSuite) SetupTest() { diff --git a/app/app.go b/app/app.go index 7191014db5..7b5f98d319 100644 --- a/app/app.go +++ b/app/app.go @@ -123,7 +123,6 @@ import ( ethermint "github.com/evmos/ethermint/types" "github.com/evmos/ethermint/x/evm" evmkeeper "github.com/evmos/ethermint/x/evm/keeper" - "github.com/evmos/ethermint/x/evm/statedb" evmtypes "github.com/evmos/ethermint/x/evm/types" legacyevmtypes "github.com/evmos/ethermint/x/evm/types/legacy" "github.com/evmos/ethermint/x/evm/vm/geth" @@ -423,7 +422,7 @@ func NewEthermintApp( appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], authtypes.NewModuleAddress(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.FeeMarketKeeper, - nil, geth.NewEVM, statedb.New, tracer, evmSs, + nil, geth.NewEVM, tracer, evmSs, ) // Create IBC Keeper diff --git a/tests/importer/importer_test.go b/tests/importer/importer_test.go index 04e8918e29..a32a730206 100644 --- a/tests/importer/importer_test.go +++ b/tests/importer/importer_test.go @@ -18,8 +18,6 @@ import ( evmkeeper "github.com/evmos/ethermint/x/evm/keeper" "github.com/evmos/ethermint/x/evm/statedb" - evmtypes "github.com/evmos/ethermint/x/evm/types" - "github.com/evmos/ethermint/x/evm/vm" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus/ethash" @@ -142,7 +140,7 @@ func (suite *ImporterTestSuite) TestImportBlocks() { }) ctx := suite.app.NewContext(false, tmheader) ctx = ctx.WithBlockHeight(tmheader.Height) - vmdb := statedb.New(ctx, suite.app.EvmKeeper, evmtypes.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes()))) + vmdb := statedb.New(ctx, suite.app.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes()))) if chainConfig.DAOForkSupport && chainConfig.DAOForkBlock != nil && chainConfig.DAOForkBlock.Cmp(block.Number()) == 0 { applyDAOHardFork(vmdb) @@ -228,7 +226,7 @@ func applyDAOHardFork(vmdb ethvm.StateDB) { // Ref: https://github.com/ethereum/go-ethereum/blob/52f2461774bcb8cdd310f86b4bc501df5b783852/core/state_processor.go#L88 func applyTransaction( ctx sdk.Context, config *ethparams.ChainConfig, bc ethcore.ChainContext, author *common.Address, - gp *ethcore.GasPool, evmKeeper *evmkeeper.Keeper, vmdb vm.StateDB, header *ethtypes.Header, + gp *ethcore.GasPool, evmKeeper *evmkeeper.Keeper, vmdb *statedb.StateDB, header *ethtypes.Header, tx *ethtypes.Transaction, usedGas *uint64, cfg ethvm.Config, ) (*ethtypes.Receipt, uint64, error) { msg, err := tx.AsMessage(ethtypes.MakeSigner(config, header.Number), sdk.ZeroInt().BigInt()) diff --git a/x/evm/genesis_test.go b/x/evm/genesis_test.go index 72262472e9..e060c5d965 100644 --- a/x/evm/genesis_test.go +++ b/x/evm/genesis_test.go @@ -9,8 +9,8 @@ import ( "github.com/evmos/ethermint/crypto/ethsecp256k1" etherminttypes "github.com/evmos/ethermint/types" "github.com/evmos/ethermint/x/evm" + "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/types" - "github.com/evmos/ethermint/x/evm/vm" ) func (suite *EvmTestSuite) TestInitGenesis() { @@ -19,7 +19,7 @@ func (suite *EvmTestSuite) TestInitGenesis() { address := common.HexToAddress(privkey.PubKey().Address().String()) - var vmdb vm.StateDB + var vmdb *statedb.StateDB testCases := []struct { name string diff --git a/x/evm/handler_test.go b/x/evm/handler_test.go index 68b2b74a1b..a554c6ee6a 100644 --- a/x/evm/handler_test.go +++ b/x/evm/handler_test.go @@ -7,7 +7,6 @@ import ( "time" "github.com/evmos/ethermint/x/evm/keeper" - "github.com/evmos/ethermint/x/evm/vm" sdkmath "cosmossdk.io/math" "github.com/gogo/protobuf/proto" @@ -182,8 +181,8 @@ func (suite *EvmTestSuite) SignTx(tx *types.MsgEthereumTx) { suite.Require().NoError(err) } -func (suite *EvmTestSuite) StateDB() vm.StateDB { - return statedb.New(suite.ctx, suite.app.EvmKeeper, types.NewEmptyTxConfig(common.BytesToHash(suite.ctx.HeaderHash().Bytes()))) +func (suite *EvmTestSuite) StateDB() *statedb.StateDB { + return statedb.New(suite.ctx, suite.app.EvmKeeper, statedb.NewEmptyTxConfig(common.BytesToHash(suite.ctx.HeaderHash().Bytes()))) } func TestEvmTestSuite(t *testing.T) { diff --git a/x/evm/keeper/config.go b/x/evm/keeper/config.go index 1d76fd0d06..3debb895de 100644 --- a/x/evm/keeper/config.go +++ b/x/evm/keeper/config.go @@ -48,8 +48,8 @@ func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress, cha } // TxConfig loads `TxConfig` from current transient storage -func (k *Keeper) TxConfig(ctx sdk.Context, txHash common.Hash) types.TxConfig { - return types.NewTxConfig( +func (k *Keeper) TxConfig(ctx sdk.Context, txHash common.Hash) statedb.TxConfig { + return statedb.NewTxConfig( common.BytesToHash(ctx.HeaderHash()), // BlockHash txHash, // TxHash uint(k.GetTxIndexTransient(ctx)), // TxIndex diff --git a/x/evm/keeper/grpc_query.go b/x/evm/keeper/grpc_query.go index f9d5b5e56f..5e09153b59 100644 --- a/x/evm/keeper/grpc_query.go +++ b/x/evm/keeper/grpc_query.go @@ -255,7 +255,7 @@ func (k Keeper) EthCall(c context.Context, req *types.EthCallRequest) (*types.Ms return nil, status.Error(codes.InvalidArgument, err.Error()) } - txConfig := types.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash())) + txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash())) // pass false to not commit StateDB res, err := k.ApplyMessageWithConfig(ctx, msg, nil, false, cfg, txConfig) @@ -324,7 +324,7 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type nonce := k.GetNonce(ctx, args.GetFrom()) args.Nonce = (*hexutil.Uint64)(&nonce) - txConfig := types.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())) + txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())) // convert the tx args to an ethereum message msg, err := args.ToMessage(req.GasCap, cfg.BaseFee) @@ -423,7 +423,7 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ } signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight())) - txConfig := types.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())) + txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())) for i, tx := range req.Predecessors { ethTx := tx.AsTransaction() msg, err := ethTx.AsMessage(signer, cfg.BaseFee) @@ -503,7 +503,7 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest) txsLength := len(req.Txs) results := make([]*types.TxTraceResult, 0, txsLength) - txConfig := types.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())) + txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash().Bytes())) for i, tx := range req.Txs { result := types.TxTraceResult{} ethTx := tx.AsTransaction() @@ -533,7 +533,7 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest) func (k *Keeper) traceTx( ctx sdk.Context, cfg *statedb.EVMConfig, - txConfig types.TxConfig, + txConfig statedb.TxConfig, signer ethtypes.Signer, tx *ethtypes.Transaction, traceConfig *types.TraceConfig, diff --git a/x/evm/keeper/grpc_query_test.go b/x/evm/keeper/grpc_query_test.go index e0f7248475..520dc79f67 100644 --- a/x/evm/keeper/grpc_query_test.go +++ b/x/evm/keeper/grpc_query_test.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" ethlogger "github.com/ethereum/go-ethereum/eth/tracers/logger" ethparams "github.com/ethereum/go-ethereum/params" @@ -238,12 +237,12 @@ func (suite *KeeperTestSuite) TestQueryStorage() { testCases := []struct { msg string - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) expPass bool }{ { "invalid address", - func(vm.StateDB) { + func(*statedb.StateDB) { req = &types.QueryStorageRequest{ Address: invalidAddress, } @@ -252,7 +251,7 @@ func (suite *KeeperTestSuite) TestQueryStorage() { }, { "success", - func(vmdb vm.StateDB) { + func(vmdb *statedb.StateDB) { key := common.BytesToHash([]byte("key")) value := common.BytesToHash([]byte("value")) expValue = value.String() @@ -297,12 +296,12 @@ func (suite *KeeperTestSuite) TestQueryCode() { testCases := []struct { msg string - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) expPass bool }{ { "invalid address", - func(vm.StateDB) { + func(*statedb.StateDB) { req = &types.QueryCodeRequest{ Address: invalidAddress, } @@ -313,7 +312,7 @@ func (suite *KeeperTestSuite) TestQueryCode() { }, { "success", - func(vmdb vm.StateDB) { + func(vmdb *statedb.StateDB) { expCode = []byte("code") vmdb.SetCode(suite.Address, expCode) @@ -356,17 +355,17 @@ func (suite *KeeperTestSuite) TestQueryTxLogs() { testCases := []struct { msg string - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) }{ { "empty logs", - func(vm.StateDB) { + func(*statedb.StateDB) { expLogs = nil }, }, { "success", - func(vmdb vm.StateDB) { + func(vmdb *statedb.StateDB) { expLogs = []*types.Log{ { Address: suite.Address.String(), @@ -392,7 +391,7 @@ func (suite *KeeperTestSuite) TestQueryTxLogs() { suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { suite.SetupTest() // reset - vmdb := statedb.New(suite.Ctx, suite.App.EvmKeeper, types.NewTxConfig(common.BytesToHash(suite.Ctx.HeaderHash().Bytes()), txHash, txIndex, logIndex)) + vmdb := statedb.New(suite.Ctx, suite.App.EvmKeeper, statedb.NewTxConfig(common.BytesToHash(suite.Ctx.HeaderHash().Bytes()), txHash, txIndex, logIndex)) tc.malleate(vmdb) suite.Require().NoError(vmdb.Commit()) diff --git a/x/evm/keeper/hooks_test.go b/x/evm/keeper/hooks_test.go index d3d198d9fa..d8d0dafd35 100644 --- a/x/evm/keeper/hooks_test.go +++ b/x/evm/keeper/hooks_test.go @@ -66,7 +66,7 @@ func (suite *KeeperTestSuite) TestEvmHooks() { k := suite.App.EvmKeeper ctx := suite.Ctx txHash := common.BigToHash(big.NewInt(1)) - vmdb := statedb.New(ctx, k, types.NewTxConfig( + vmdb := statedb.New(ctx, k, statedb.NewTxConfig( common.BytesToHash(ctx.HeaderHash().Bytes()), txHash, 0, diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 42400ee27b..187d547274 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -32,6 +32,7 @@ import ( "github.com/tendermint/tendermint/libs/log" ethermint "github.com/evmos/ethermint/types" + "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/types" legacytypes "github.com/evmos/ethermint/x/evm/types/legacy" evm "github.com/evmos/ethermint/x/evm/vm" @@ -77,9 +78,6 @@ type Keeper struct { // evm constructor function evmConstructor evm.Constructor - // stateDB constructor function - stateDBConstructor evm.StateDBConstructor - // Legacy subspace ss paramstypes.Subspace } @@ -95,7 +93,6 @@ func NewKeeper( fmk types.FeeMarketKeeper, customPrecompiles evm.PrecompiledContracts, evmConstructor evm.Constructor, - stateDBConstructor evm.StateDBConstructor, tracer string, ss paramstypes.Subspace, ) *Keeper { @@ -115,19 +112,18 @@ func NewKeeper( // NOTE: we pass in the parameter space to the CommitStateDB in order to use custom denominations for the EVM operations return &Keeper{ - cdc: cdc, - authority: authority, - accountKeeper: ak, - bankKeeper: bankKeeper, - stakingKeeper: sk, - feeMarketKeeper: fmk, - storeKey: storeKey, - transientKey: transientKey, - customPrecompiles: customPrecompiles, - evmConstructor: evmConstructor, - stateDBConstructor: stateDBConstructor, - tracer: tracer, - ss: ss, + cdc: cdc, + authority: authority, + accountKeeper: ak, + bankKeeper: bankKeeper, + stakingKeeper: sk, + feeMarketKeeper: fmk, + storeKey: storeKey, + transientKey: transientKey, + customPrecompiles: customPrecompiles, + evmConstructor: evmConstructor, + tracer: tracer, + ss: ss, } } @@ -284,7 +280,7 @@ func (k Keeper) Tracer(ctx sdk.Context, msg core.Message, ethCfg *params.ChainCo // GetAccountWithoutBalance load nonce and codehash without balance, // more efficient in cases where balance is not needed. -func (k *Keeper) GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) *types.StateDBAccount { +func (k *Keeper) GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) *statedb.Account { cosmosAddr := sdk.AccAddress(addr.Bytes()) acct := k.accountKeeper.GetAccount(ctx, cosmosAddr) if acct == nil { @@ -297,7 +293,7 @@ func (k *Keeper) GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) codeHash = ethAcct.GetCodeHash().Bytes() } - return &types.StateDBAccount{ + return &statedb.Account{ Nonce: acct.GetSequence(), CodeHash: codeHash, Balance: nil, @@ -305,14 +301,14 @@ func (k *Keeper) GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) } // GetAccountOrEmpty returns empty account if not exist, returns error if it's not `EthAccount` -func (k *Keeper) GetAccountOrEmpty(ctx sdk.Context, addr common.Address) types.StateDBAccount { +func (k *Keeper) GetAccountOrEmpty(ctx sdk.Context, addr common.Address) statedb.Account { acct := k.GetAccount(ctx, addr) if acct != nil { return *acct } // empty account - return types.StateDBAccount{ + return statedb.Account{ Balance: new(big.Int), CodeHash: types.EmptyCodeHash, } diff --git a/x/evm/keeper/keeper_test.go b/x/evm/keeper/keeper_test.go index a27a724da9..549d103a5f 100644 --- a/x/evm/keeper/keeper_test.go +++ b/x/evm/keeper/keeper_test.go @@ -12,6 +12,7 @@ import ( sdkmath "cosmossdk.io/math" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/testutil" "github.com/stretchr/testify/suite" @@ -119,7 +120,7 @@ func (suite *KeeperTestSuite) TestGetAccountStorage() { } func (suite *KeeperTestSuite) TestGetAccountOrEmpty() { - empty := types.StateDBAccount{ + empty := statedb.Account{ Balance: new(big.Int), CodeHash: types.EmptyCodeHash, } diff --git a/x/evm/keeper/msg_server_test.go b/x/evm/keeper/msg_server_test.go index bf71af77df..756426442b 100644 --- a/x/evm/keeper/msg_server_test.go +++ b/x/evm/keeper/msg_server_test.go @@ -8,8 +8,8 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" + "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/types" - "github.com/evmos/ethermint/x/evm/vm" ) func (suite *KeeperTestSuite) TestEthereumTx() { @@ -17,7 +17,7 @@ func (suite *KeeperTestSuite) TestEthereumTx() { err error msg *types.MsgEthereumTx signer ethtypes.Signer - vmdb vm.StateDB + vmdb *statedb.StateDB chainCfg *params.ChainConfig expectedGasUsed uint64 ) diff --git a/x/evm/keeper/params_test.go b/x/evm/keeper/params_test.go index 9c110e4c03..f7e8926b22 100644 --- a/x/evm/keeper/params_test.go +++ b/x/evm/keeper/params_test.go @@ -11,7 +11,6 @@ import ( "github.com/evmos/ethermint/app" "github.com/evmos/ethermint/encoding" "github.com/evmos/ethermint/x/evm/keeper" - "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/types" legacytypes "github.com/evmos/ethermint/x/evm/types/legacy" legacytestutil "github.com/evmos/ethermint/x/evm/types/legacy/testutil" @@ -153,7 +152,6 @@ func (suite *KeeperTestSuite) TestLegacyParamsKeyTableRegistration() { ak, nil, nil, nil, nil, // OK to pass nil in for these since we only instantiate and use params geth.NewEVM, - statedb.New, "", unregisteredSubspace, ) @@ -211,7 +209,6 @@ func (suite *KeeperTestSuite) TestRenamedFieldReturnsProperValueForLegacyParams( ak, nil, nil, nil, nil, geth.NewEVM, - statedb.New, "", subspace, ) @@ -244,7 +241,6 @@ func (suite *KeeperTestSuite) TestNilLegacyParamsDoNotPanic() { ak, nil, nil, nil, nil, // OK to pass nil in for these since we only instantiate and use params geth.NewEVM, - statedb.New, "", subspace, ) diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go index ef02cdc3c3..ad90dba5fd 100644 --- a/x/evm/keeper/state_transition.go +++ b/x/evm/keeper/state_transition.go @@ -268,7 +268,7 @@ func (k *Keeper) ApplyMessage(ctx sdk.Context, msg core.Message, tracer vm.EVMLo return nil, errorsmod.Wrap(err, "failed to load evm config") } - txConfig := types.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash())) + txConfig := statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash())) return k.ApplyMessageWithConfig(ctx, msg, tracer, commit, cfg, txConfig) } @@ -315,7 +315,7 @@ func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context, tracer vm.EVMLogger, commit bool, cfg *statedb.EVMConfig, - txConfig types.TxConfig, + txConfig statedb.TxConfig, ) (*types.MsgEthereumTxResponse, error) { var ( ret []byte // return bytes from evm execution @@ -329,7 +329,7 @@ func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context, return nil, errorsmod.Wrap(types.ErrCallDisabled, "failed to call contract") } - stateDB := k.stateDBConstructor(ctx, k, txConfig) + stateDB := statedb.New(ctx, k, txConfig) evm := k.NewEVM(ctx, msg, cfg, tracer, stateDB) leftoverGas := msg.Gas() diff --git a/x/evm/keeper/state_transition_test.go b/x/evm/keeper/state_transition_test.go index 9fd2a707d1..76334d40fd 100644 --- a/x/evm/keeper/state_transition_test.go +++ b/x/evm/keeper/state_transition_test.go @@ -11,7 +11,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" "github.com/evmos/ethermint/tests" "github.com/evmos/ethermint/x/evm/keeper" @@ -575,8 +574,8 @@ func (suite *KeeperTestSuite) TestApplyMessageWithConfig() { config *statedb.EVMConfig keeperParams types.Params signer ethtypes.Signer - vmdb vm.StateDB - txConfig types.TxConfig + vmdb *statedb.StateDB + txConfig statedb.TxConfig chainCfg *params.ChainConfig ) diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index 7644798354..c2cd893c5e 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -27,18 +27,18 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/ethereum/go-ethereum/common" ethermint "github.com/evmos/ethermint/types" + "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/types" - "github.com/evmos/ethermint/x/evm/vm" ) -var _ vm.StateDBKeeper = &Keeper{} +var _ statedb.Keeper = &Keeper{} // ---------------------------------------------------------------------------- // StateDB Keeper implementation // ---------------------------------------------------------------------------- // GetAccount returns nil if account is not exist, returns error if it's not `EthAccountI` -func (k *Keeper) GetAccount(ctx sdk.Context, addr common.Address) *types.StateDBAccount { +func (k *Keeper) GetAccount(ctx sdk.Context, addr common.Address) *statedb.Account { acct := k.GetAccountWithoutBalance(ctx, addr) if acct == nil { return nil @@ -119,7 +119,7 @@ func (k *Keeper) SetBalance(ctx sdk.Context, addr common.Address, amount *big.In } // SetAccount updates nonce/balance/codeHash together. -func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account types.StateDBAccount) error { +func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account statedb.Account) error { // update account cosmosAddr := sdk.AccAddress(addr.Bytes()) acct := k.accountKeeper.GetAccount(ctx, cosmosAddr) diff --git a/x/evm/keeper/statedb_test.go b/x/evm/keeper/statedb_test.go index a014566fc2..b34950d760 100644 --- a/x/evm/keeper/statedb_test.go +++ b/x/evm/keeper/statedb_test.go @@ -16,7 +16,6 @@ import ( "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/evmos/ethermint/crypto/ethsecp256k1" "github.com/evmos/ethermint/tests" @@ -29,27 +28,27 @@ func (suite *KeeperTestSuite) TestCreateAccount() { testCases := []struct { name string addr common.Address - malleate func(vm.StateDB, common.Address) - callback func(vm.StateDB, common.Address) + malleate func(*statedb.StateDB, common.Address) + callback func(*statedb.StateDB, common.Address) }{ { "reset account (keep balance)", suite.Address, - func(vmdb vm.StateDB, addr common.Address) { + func(vmdb *statedb.StateDB, addr common.Address) { vmdb.AddBalance(addr, big.NewInt(100)) suite.Require().NotZero(vmdb.GetBalance(addr).Int64()) }, - func(vmdb vm.StateDB, addr common.Address) { + func(vmdb *statedb.StateDB, addr common.Address) { suite.Require().Equal(vmdb.GetBalance(addr).Int64(), int64(100)) }, }, { "create account", tests.GenerateAddress(), - func(vmdb vm.StateDB, addr common.Address) { + func(vmdb *statedb.StateDB, addr common.Address) { suite.Require().False(vmdb.Exist(addr)) }, - func(vmdb vm.StateDB, addr common.Address) { + func(vmdb *statedb.StateDB, addr common.Address) { suite.Require().True(vmdb.Exist(addr)) }, }, @@ -110,19 +109,19 @@ func (suite *KeeperTestSuite) TestSubBalance() { testCases := []struct { name string amount *big.Int - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) isNoOp bool }{ { "positive amount, below zero", big.NewInt(100), - func(vm.StateDB) {}, + func(*statedb.StateDB) {}, true, }, { "positive amount, above zero", big.NewInt(50), - func(vmdb vm.StateDB) { + func(vmdb *statedb.StateDB) { vmdb.AddBalance(suite.Address, big.NewInt(100)) }, false, @@ -130,13 +129,13 @@ func (suite *KeeperTestSuite) TestSubBalance() { { "zero amount", big.NewInt(0), - func(vm.StateDB) {}, + func(*statedb.StateDB) {}, true, }, { "negative amount", big.NewInt(-1), - func(vm.StateDB) {}, + func(*statedb.StateDB) {}, false, }, } @@ -164,19 +163,19 @@ func (suite *KeeperTestSuite) TestGetNonce() { name string address common.Address expectedNonce uint64 - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) }{ { "account not found", tests.GenerateAddress(), 0, - func(vm.StateDB) {}, + func(*statedb.StateDB) {}, }, { "existing account", suite.Address, 1, - func(vmdb vm.StateDB) { + func(vmdb *statedb.StateDB) { vmdb.SetNonce(suite.Address, 1) }, }, @@ -235,55 +234,55 @@ func (suite *KeeperTestSuite) TestSetAccount() { testCases := []struct { name string address common.Address - account types.StateDBAccount + account statedb.Account expectedErr error }{ { "new account, non-contract account", tests.GenerateAddress(), - types.StateDBAccount{10, big.NewInt(100), types.EmptyCodeHash}, + statedb.Account{10, big.NewInt(100), types.EmptyCodeHash}, nil, }, { "new account, contract account", tests.GenerateAddress(), - types.StateDBAccount{10, big.NewInt(100), crypto.Keccak256Hash([]byte("some code hash")).Bytes()}, + statedb.Account{10, big.NewInt(100), crypto.Keccak256Hash([]byte("some code hash")).Bytes()}, nil, }, { "existing eth account, non-contract account", ethAddr, - types.StateDBAccount{10, big.NewInt(1), types.EmptyCodeHash}, + statedb.Account{10, big.NewInt(1), types.EmptyCodeHash}, nil, }, { "existing eth account, contract account", ethAddr, - types.StateDBAccount{10, big.NewInt(0), crypto.Keccak256Hash([]byte("some code hash")).Bytes()}, + statedb.Account{10, big.NewInt(0), crypto.Keccak256Hash([]byte("some code hash")).Bytes()}, nil, }, { "existing base account, non-contract account", baseAddr, - types.StateDBAccount{10, big.NewInt(10), types.EmptyCodeHash}, + statedb.Account{10, big.NewInt(10), types.EmptyCodeHash}, nil, }, { "existing base account, contract account", baseAddr, - types.StateDBAccount{10, big.NewInt(99), crypto.Keccak256Hash([]byte("some code hash")).Bytes()}, + statedb.Account{10, big.NewInt(99), crypto.Keccak256Hash([]byte("some code hash")).Bytes()}, nil, }, { "existing vesting account, non-contract account", vestingAddr, - types.StateDBAccount{10, big.NewInt(1000), types.EmptyCodeHash}, + statedb.Account{10, big.NewInt(1000), types.EmptyCodeHash}, nil, }, { "existing vesting account, contract account", vestingAddr, - types.StateDBAccount{10, big.NewInt(1001), crypto.Keccak256Hash([]byte("some code hash")).Bytes()}, + statedb.Account{10, big.NewInt(1001), crypto.Keccak256Hash([]byte("some code hash")).Bytes()}, types.ErrInvalidAccount, }, } @@ -331,25 +330,25 @@ func (suite *KeeperTestSuite) TestGetCodeHash() { name string address common.Address expHash common.Hash - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) }{ { "account not found", tests.GenerateAddress(), common.Hash{}, - func(vm.StateDB) {}, + func(*statedb.StateDB) {}, }, { "account not EthAccount type, EmptyCodeHash", addr, common.BytesToHash(types.EmptyCodeHash), - func(vm.StateDB) {}, + func(*statedb.StateDB) {}, }, { "existing account", suite.Address, crypto.Keccak256Hash([]byte("codeHash")), - func(vmdb vm.StateDB) { + func(vmdb *statedb.StateDB) { vmdb.SetCode(suite.Address, []byte("codeHash")) }, }, @@ -458,13 +457,13 @@ func (suite *KeeperTestSuite) TestKeeperSetCode() { func (suite *KeeperTestSuite) TestRefund() { testCases := []struct { name string - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) expRefund uint64 expPanic bool }{ { "success - add and subtract refund", - func(vmdb vm.StateDB) { + func(vmdb *statedb.StateDB) { vmdb.AddRefund(11) }, 1, @@ -472,7 +471,7 @@ func (suite *KeeperTestSuite) TestRefund() { }, { "fail - subtract amount > current refund", - func(vm.StateDB) { + func(*statedb.StateDB) { }, 0, true, @@ -602,14 +601,14 @@ func (suite *KeeperTestSuite) TestExist() { testCases := []struct { name string address common.Address - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) exists bool }{ - {"success, account exists", suite.Address, func(vm.StateDB) {}, true}, - {"success, has suicided", suite.Address, func(vmdb vm.StateDB) { + {"success, account exists", suite.Address, func(*statedb.StateDB) {}, true}, + {"success, has suicided", suite.Address, func(vmdb *statedb.StateDB) { vmdb.Suicide(suite.Address) }, true}, - {"success, account doesn't exist", tests.GenerateAddress(), func(vm.StateDB) {}, false}, + {"success, account doesn't exist", tests.GenerateAddress(), func(*statedb.StateDB) {}, false}, } for _, tc := range testCases { @@ -626,17 +625,17 @@ func (suite *KeeperTestSuite) TestEmpty() { testCases := []struct { name string address common.Address - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) empty bool }{ - {"empty, account exists", suite.Address, func(vm.StateDB) {}, true}, + {"empty, account exists", suite.Address, func(*statedb.StateDB) {}, true}, { "not empty, positive balance", suite.Address, - func(vmdb vm.StateDB) { vmdb.AddBalance(suite.Address, big.NewInt(100)) }, + func(vmdb *statedb.StateDB) { vmdb.AddBalance(suite.Address, big.NewInt(100)) }, false, }, - {"empty, account doesn't exist", tests.GenerateAddress(), func(vm.StateDB) {}, true}, + {"empty, account doesn't exist", tests.GenerateAddress(), func(*statedb.StateDB) {}, true}, } for _, tc := range testCases { @@ -657,9 +656,9 @@ func (suite *KeeperTestSuite) TestSnapshot() { testCases := []struct { name string - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) }{ - {"simple revert", func(vmdb vm.StateDB) { + {"simple revert", func(vmdb *statedb.StateDB) { revision := vmdb.Snapshot() suite.Require().Zero(revision) @@ -671,7 +670,7 @@ func (suite *KeeperTestSuite) TestSnapshot() { // reverted suite.Require().Equal(common.Hash{}, vmdb.GetState(suite.Address, key)) }}, - {"nested snapshot/revert", func(vmdb vm.StateDB) { + {"nested snapshot/revert", func(vmdb *statedb.StateDB) { revision1 := vmdb.Snapshot() suite.Require().Zero(revision1) @@ -688,7 +687,7 @@ func (suite *KeeperTestSuite) TestSnapshot() { vmdb.RevertToSnapshot(revision1) suite.Require().Equal(common.Hash{}, vmdb.GetState(suite.Address, key)) }}, - {"jump revert", func(vmdb vm.StateDB) { + {"jump revert", func(vmdb *statedb.StateDB) { revision1 := vmdb.Snapshot() vmdb.SetState(suite.Address, key, value1) vmdb.Snapshot() @@ -758,7 +757,7 @@ func (suite *KeeperTestSuite) TestAddLog() { name string hash common.Hash log, expLog *ethtypes.Log // pre and post populating log fields - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) }{ { "tx hash from message", @@ -772,7 +771,7 @@ func (suite *KeeperTestSuite) TestAddLog() { TxHash: txHash, Topics: make([]common.Hash, 0), }, - func(vm.StateDB) {}, + func(*statedb.StateDB) {}, }, { "dynamicfee tx hash from message", @@ -786,14 +785,14 @@ func (suite *KeeperTestSuite) TestAddLog() { TxHash: txHash3, Topics: make([]common.Hash, 0), }, - func(vm.StateDB) {}, + func(*statedb.StateDB) {}, }, } for _, tc := range testCases { suite.Run(tc.name, func() { suite.SetupTest() - vmdb := statedb.New(suite.Ctx, suite.App.EvmKeeper, types.NewTxConfig( + vmdb := statedb.New(suite.Ctx, suite.App.EvmKeeper, statedb.NewTxConfig( common.BytesToHash(suite.Ctx.HeaderHash().Bytes()), tc.hash, 0, 0, @@ -883,13 +882,13 @@ func (suite *KeeperTestSuite) _TestForEachStorage() { testCase := []struct { name string - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) callback func(key, value common.Hash) (stop bool) expValues []common.Hash }{ { "aggregate state", - func(vmdb vm.StateDB) { + func(vmdb *statedb.StateDB) { for i := 0; i < 5; i++ { vmdb.SetState(suite.Address, common.BytesToHash([]byte(fmt.Sprintf("key%d", i))), common.BytesToHash([]byte(fmt.Sprintf("value%d", i)))) } @@ -908,7 +907,7 @@ func (suite *KeeperTestSuite) _TestForEachStorage() { }, { "filter state", - func(vmdb vm.StateDB) { + func(vmdb *statedb.StateDB) { vmdb.SetState(suite.Address, common.BytesToHash([]byte("key")), common.BytesToHash([]byte("value"))) vmdb.SetState(suite.Address, common.BytesToHash([]byte("filterkey")), common.BytesToHash([]byte("filtervalue"))) }, diff --git a/x/evm/migrations/v3/store_test.go b/x/evm/migrations/v3/store_test.go index 12ff79409a..a01916a6f7 100644 --- a/x/evm/migrations/v3/store_test.go +++ b/x/evm/migrations/v3/store_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/evmos/ethermint/x/evm/keeper" - "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/types" "github.com/evmos/ethermint/x/evm/vm/geth" "github.com/stretchr/testify/require" @@ -152,7 +151,6 @@ func TestKeyTableCompatiabilityWithKeeper(t *testing.T) { ak, nil, nil, nil, nil, geth.NewEVM, - statedb.New, "", subspace, ) diff --git a/x/evm/statedb/account.go b/x/evm/statedb/account.go new file mode 100644 index 0000000000..26ff52a574 --- /dev/null +++ b/x/evm/statedb/account.go @@ -0,0 +1,27 @@ +package statedb + +import ( + "bytes" + "math/big" +) + +// Account is the Ethereum consensus representation of accounts. +// These objects are stored in the storage of auth module. +type Account struct { + Nonce uint64 + Balance *big.Int + CodeHash []byte +} + +// NewEmptyAccount returns an empty account. +func NewEmptyAccount() *Account { + return &Account{ + Balance: new(big.Int), + CodeHash: emptyCodeHash, + } +} + +// IsContract returns if the account contains contract code. +func (acct Account) IsContract() bool { + return !bytes.Equal(acct.CodeHash, emptyCodeHash) +} diff --git a/x/evm/statedb/config.go b/x/evm/statedb/config.go index 445ae0d47c..d9baa5387f 100644 --- a/x/evm/statedb/config.go +++ b/x/evm/statedb/config.go @@ -23,6 +23,35 @@ import ( "github.com/evmos/ethermint/x/evm/types" ) +// TxConfig encapulates the readonly information of current tx for `StateDB`. +type TxConfig struct { + BlockHash common.Hash // hash of current block + TxHash common.Hash // hash of current tx + TxIndex uint // the index of current transaction + LogIndex uint // the index of next log within current block +} + +// NewTxConfig returns a TxConfig +func NewTxConfig(bhash, thash common.Hash, txIndex, logIndex uint) TxConfig { + return TxConfig{ + BlockHash: bhash, + TxHash: thash, + TxIndex: txIndex, + LogIndex: logIndex, + } +} + +// NewEmptyTxConfig construct an empty TxConfig, +// used in context where there's no transaction, e.g. `eth_call`/`eth_estimateGas`. +func NewEmptyTxConfig(bhash common.Hash) TxConfig { + return TxConfig{ + BlockHash: bhash, + TxHash: common.Hash{}, + TxIndex: 0, + LogIndex: 0, + } +} + // EVMConfig encapsulates common parameters needed to create an EVM to execute a message // It's mainly to reduce the number of method parameters type EVMConfig struct { diff --git a/x/evm/statedb/interfaces.go b/x/evm/statedb/interfaces.go index eb8494d719..6de9599406 100644 --- a/x/evm/statedb/interfaces.go +++ b/x/evm/statedb/interfaces.go @@ -16,6 +16,10 @@ package statedb import ( + "math/big" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/vm" ) @@ -28,3 +32,20 @@ type ExtStateDB interface { vm.StateDB AppendJournalEntry(JournalEntry) } + +// Keeper provide underlying storage of StateDB +type Keeper interface { + // Read methods + GetAccount(ctx sdk.Context, addr common.Address) *Account + GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash + GetCode(ctx sdk.Context, codeHash common.Hash) []byte + // the callback returns false to break early + ForEachStorage(ctx sdk.Context, addr common.Address, cb func(key, value common.Hash) bool) + + // Write methods, only called by `StateDB.Commit()` + SetAccount(ctx sdk.Context, addr common.Address, account Account) error + SetState(ctx sdk.Context, addr common.Address, key common.Hash, value []byte) + SetCode(ctx sdk.Context, codeHash []byte, code []byte) + SetBalance(ctx sdk.Context, addr common.Address, amount *big.Int) error + DeleteAccount(ctx sdk.Context, addr common.Address) error +} diff --git a/x/evm/statedb/statedb.go b/x/evm/statedb/statedb.go index d4d0a0b2aa..0bb391cad6 100644 --- a/x/evm/statedb/statedb.go +++ b/x/evm/statedb/statedb.go @@ -25,8 +25,6 @@ import ( ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" - "github.com/evmos/ethermint/x/evm/types" - evm "github.com/evmos/ethermint/x/evm/vm" ) var _ vm.StateDB = &StateDB{} @@ -37,8 +35,8 @@ var _ vm.StateDB = &StateDB{} // * Contracts // * Accounts type StateDB struct { - keeper evm.StateDBKeeper - txConfig types.TxConfig + keeper Keeper + txConfig TxConfig ctx *SnapshotCommitCtx // snapshot-able ctx manager ephemeralStore *EphemeralStore // in-memory temporary data @@ -51,7 +49,7 @@ type StateDB struct { } // New creates a new state from a given trie. -func New(ctx sdk.Context, keeper evm.StateDBKeeper, txConfig types.TxConfig) evm.StateDB { +func New(ctx sdk.Context, keeper Keeper, txConfig TxConfig) *StateDB { return &StateDB{ keeper: keeper, txConfig: txConfig, @@ -69,7 +67,7 @@ func New(ctx sdk.Context, keeper evm.StateDBKeeper, txConfig types.TxConfig) evm } // Keeper returns the underlying `Keeper` -func (s *StateDB) Keeper() evm.StateDBKeeper { +func (s *StateDB) Keeper() Keeper { return s.keeper } @@ -200,10 +198,10 @@ func (s *StateDB) HasSuicided(addr common.Address) bool { func (s *StateDB) AddPreimage(hash common.Hash, preimage []byte) {} //nolint: revive // getOrNewAccount retrieves a state account or create a new account if nil. -func (s *StateDB) getOrNewAccount(addr common.Address) *types.StateDBAccount { +func (s *StateDB) getOrNewAccount(addr common.Address) *Account { account := s.keeper.GetAccount(s.ctx.CurrentCtx(), addr) if account == nil { - account = types.NewEmptyAccount() + account = NewEmptyAccount() } return account @@ -223,7 +221,7 @@ func (s *StateDB) CreateAccount(addr common.Address) { account := s.keeper.GetAccount(s.ctx.CurrentCtx(), addr) if account == nil { // No account found, create a new one - if err := s.keeper.SetAccount(s.ctx.CurrentCtx(), addr, *types.NewEmptyAccount()); err != nil { + if err := s.keeper.SetAccount(s.ctx.CurrentCtx(), addr, *NewEmptyAccount()); err != nil { s.SetError(fmt.Errorf("failed to create account: %w", err)) } @@ -235,7 +233,7 @@ func (s *StateDB) CreateAccount(addr common.Address) { // Create a new account -- Must use NewEmptyAccount() so that the // CodeHash is the actual hash of nil, not an empty byte slice - newAccount := types.NewEmptyAccount() + newAccount := NewEmptyAccount() newAccount.Balance = account.Balance if err := s.keeper.SetAccount(s.ctx.CurrentCtx(), addr, *newAccount); err != nil { diff --git a/x/evm/statedb/statedb_test.go b/x/evm/statedb/statedb_test.go index bf34305b3c..08c8f48898 100644 --- a/x/evm/statedb/statedb_test.go +++ b/x/evm/statedb/statedb_test.go @@ -12,17 +12,15 @@ import ( "github.com/evmos/ethermint/x/evm/keeper" "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/testutil" - "github.com/evmos/ethermint/x/evm/types" - evm "github.com/evmos/ethermint/x/evm/vm" "github.com/stretchr/testify/suite" ) var ( - address common.Address = common.BigToAddress(big.NewInt(101)) - address2 common.Address = common.BigToAddress(big.NewInt(102)) - address3 common.Address = common.BigToAddress(big.NewInt(103)) - blockHash common.Hash = common.BigToHash(big.NewInt(9999)) - emptyTxConfig types.TxConfig = types.NewEmptyTxConfig(blockHash) + address common.Address = common.BigToAddress(big.NewInt(101)) + address2 common.Address = common.BigToAddress(big.NewInt(102)) + address3 common.Address = common.BigToAddress(big.NewInt(103)) + blockHash common.Hash = common.BigToHash(big.NewInt(9999)) + emptyTxConfig statedb.TxConfig = statedb.NewEmptyTxConfig(blockHash) emptyCodeHash = crypto.Keccak256(nil) ) @@ -38,9 +36,9 @@ func (suite *StateDBTestSuite) TestAccount() { value2 := common.BigToHash(big.NewInt(4)) testCases := []struct { name string - malleate func(evm.StateDB) + malleate func(*statedb.StateDB) }{ - {"non-exist account", func(db evm.StateDB) { + {"non-exist account", func(db *statedb.StateDB) { suite.Require().Equal(false, db.Exist(address)) suite.Require().Equal(true, db.Empty(address)) suite.Require().Equal(big.NewInt(0), db.GetBalance(address)) @@ -48,7 +46,7 @@ func (suite *StateDBTestSuite) TestAccount() { suite.Require().Equal(common.Hash{}, db.GetCodeHash(address)) suite.Require().Equal(uint64(0), db.GetNonce(address)) }}, - {"empty account", func(db evm.StateDB) { + {"empty account", func(db *statedb.StateDB) { db.CreateAccount(address) suite.Require().NoError(db.Commit()) @@ -56,7 +54,7 @@ func (suite *StateDBTestSuite) TestAccount() { acct := keeper.GetAccount(suite.Ctx, address) states := suite.GetAllAccountStorage(suite.Ctx, address) - suite.Require().Equal(types.NewEmptyAccount(), acct) + suite.Require().Equal(statedb.NewEmptyAccount(), acct) suite.Require().Empty(states) suite.Require().False(acct.IsContract()) @@ -68,7 +66,7 @@ func (suite *StateDBTestSuite) TestAccount() { suite.Require().Equal(common.BytesToHash(emptyCodeHash), db.GetCodeHash(address)) suite.Require().Equal(uint64(0), db.GetNonce(address)) }}, - {"suicide", func(db evm.StateDB) { + {"suicide", func(db *statedb.StateDB) { // non-exist account. suite.Require().False(db.Suicide(address)) suite.Require().False(db.HasSuicided(address)) @@ -142,19 +140,19 @@ func (suite *StateDBTestSuite) TestAccountOverride() { func (suite *StateDBTestSuite) TestDBError() { testCases := []struct { name string - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) errContains string }{ { "negative balance", - func(db vm.StateDB) { + func(db *statedb.StateDB) { db.SubBalance(address, big.NewInt(1)) }, "failed to set account for balance subtraction: 0aphoton is smaller than 1aphoton", }, { "multiple errors persist first error", - func(db vm.StateDB) { + func(db *statedb.StateDB) { db.SubBalance(address, big.NewInt(200)) db.SubBalance(address2, big.NewInt(500)) }, @@ -179,22 +177,22 @@ func (suite *StateDBTestSuite) TestBalance() { // NOTE: no need to test overflow/underflow, that is guaranteed by evm implementation. testCases := []struct { name string - malleate func(evm.StateDB) + malleate func(*statedb.StateDB) expBalance *big.Int }{ - {"add balance", func(db evm.StateDB) { + {"add balance", func(db *statedb.StateDB) { db.AddBalance(address, big.NewInt(10)) }, big.NewInt(10)}, - {"sub balance", func(db evm.StateDB) { + {"sub balance", func(db *statedb.StateDB) { db.AddBalance(address, big.NewInt(10)) // get dirty balance suite.Require().Equal(big.NewInt(10), db.GetBalance(address)) db.SubBalance(address, big.NewInt(2)) }, big.NewInt(8)}, - {"add zero balance", func(db evm.StateDB) { + {"add zero balance", func(db *statedb.StateDB) { db.AddBalance(address, big.NewInt(0)) }, big.NewInt(0)}, - {"sub zero balance", func(db evm.StateDB) { + {"sub zero balance", func(db *statedb.StateDB) { db.SubBalance(address, big.NewInt(0)) }, big.NewInt(0)}, } @@ -221,18 +219,18 @@ func (suite *StateDBTestSuite) TestState() { value1 := common.BigToHash(big.NewInt(1)) testCases := []struct { name string - malleate func(evm.StateDB) + malleate func(*statedb.StateDB) expStates map[common.Hash]common.Hash }{ - {"empty state", func(db evm.StateDB) { + {"empty state", func(db *statedb.StateDB) { }, nil}, - {"set empty value", func(db evm.StateDB) { + {"set empty value", func(db *statedb.StateDB) { db.SetState(address, key1, common.Hash{}) }, map[common.Hash]common.Hash{ // empty value still persisted key1: common.Hash{}, }}, - {"noop state change", func(db evm.StateDB) { + {"noop state change", func(db *statedb.StateDB) { // TODO: This doesn't actually change anything compared to committed state. // Is this okay? db.SetState(address, key1, value1) @@ -241,7 +239,7 @@ func (suite *StateDBTestSuite) TestState() { // Still sets the key to an empty value even if there is no overall change key1: common.Hash{}, }}, - {"set state", func(db evm.StateDB) { + {"set state", func(db *statedb.StateDB) { // check empty initial state suite.Require().Equal(common.Hash{}, db.GetState(address, key1)) suite.Require().Equal(common.Hash{}, db.GetCommittedState(address, key1)) @@ -296,15 +294,15 @@ func (suite *StateDBTestSuite) TestCode() { testCases := []struct { name string - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) expCode []byte expCodeHash common.Hash }{ - {"non-exist account", func(vm.StateDB) {}, nil, common.Hash{}}, - {"empty account", func(db vm.StateDB) { + {"non-exist account", func(*statedb.StateDB) {}, nil, common.Hash{}}, + {"empty account", func(db *statedb.StateDB) { db.CreateAccount(address) }, nil, common.BytesToHash(emptyCodeHash)}, - {"set code", func(db vm.StateDB) { + {"set code", func(db *statedb.StateDB) { db.SetCode(address, code) }, code, codeHash}, } @@ -337,39 +335,39 @@ func (suite *StateDBTestSuite) TestRevertSnapshot() { v3 := common.BigToHash(big.NewInt(3)) testCases := []struct { name string - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) }{ - {"set state", func(db vm.StateDB) { + {"set state", func(db *statedb.StateDB) { db.SetState(address, v1, v3) }}, - {"set nonce", func(db vm.StateDB) { + {"set nonce", func(db *statedb.StateDB) { db.SetNonce(address, 10) }}, - {"change balance", func(db vm.StateDB) { + {"change balance", func(db *statedb.StateDB) { db.AddBalance(address, big.NewInt(10)) db.SubBalance(address, big.NewInt(5)) }}, - {"override account", func(db vm.StateDB) { + {"override account", func(db *statedb.StateDB) { db.CreateAccount(address) }}, - {"set code", func(db vm.StateDB) { + {"set code", func(db *statedb.StateDB) { db.SetCode(address, []byte("hello world")) }}, - {"suicide", func(db vm.StateDB) { + {"suicide", func(db *statedb.StateDB) { db.SetState(address, v1, v2) db.SetCode(address, []byte("hello world")) suite.Require().True(db.Suicide(address)) }}, - {"add log", func(db vm.StateDB) { + {"add log", func(db *statedb.StateDB) { db.AddLog(ðtypes.Log{ Address: address, }) }}, - {"add refund", func(db vm.StateDB) { + {"add refund", func(db *statedb.StateDB) { db.AddRefund(10) db.SubRefund(5) }}, - {"access list", func(db vm.StateDB) { + {"access list", func(db *statedb.StateDB) { db.AddAddressToAccessList(address) db.AddSlotToAccessList(address, v1) }}, @@ -448,9 +446,9 @@ func (suite *StateDBTestSuite) TestAccessList() { testCases := []struct { name string - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) }{ - {"add address", func(db vm.StateDB) { + {"add address", func(db *statedb.StateDB) { suite.Require().False(db.AddressInAccessList(address)) db.AddAddressToAccessList(address) suite.Require().True(db.AddressInAccessList(address)) @@ -463,7 +461,7 @@ func (suite *StateDBTestSuite) TestAccessList() { db.AddAddressToAccessList(address) suite.Require().True(db.AddressInAccessList(address)) }}, - {"add slot", func(db vm.StateDB) { + {"add slot", func(db *statedb.StateDB) { addrPresent, slotPresent := db.SlotInAccessList(address, value1) suite.Require().False(addrPresent) suite.Require().False(slotPresent) @@ -484,7 +482,7 @@ func (suite *StateDBTestSuite) TestAccessList() { suite.Require().True(addrPresent) suite.Require().True(slotPresent) }}, - {"prepare access list", func(db vm.StateDB) { + {"prepare access list", func(db *statedb.StateDB) { suite.SetupTest() al := ethtypes.AccessList{{ @@ -518,7 +516,7 @@ func (suite *StateDBTestSuite) TestAccessList() { func (suite *StateDBTestSuite) TestLog() { txHash := common.BytesToHash([]byte("tx")) // use a non-default tx config - txConfig := types.NewTxConfig( + txConfig := statedb.NewTxConfig( blockHash, txHash, 1, 1, @@ -558,18 +556,18 @@ func (suite *StateDBTestSuite) TestLog() { func (suite *StateDBTestSuite) TestRefund() { testCases := []struct { name string - malleate func(vm.StateDB) + malleate func(*statedb.StateDB) expRefund uint64 expPanic bool }{ - {"add refund", func(db vm.StateDB) { + {"add refund", func(db *statedb.StateDB) { db.AddRefund(uint64(10)) }, 10, false}, - {"sub refund", func(db vm.StateDB) { + {"sub refund", func(db *statedb.StateDB) { db.AddRefund(uint64(10)) db.SubRefund(uint64(5)) }, 5, false}, - {"negative refund counter", func(db vm.StateDB) { + {"negative refund counter", func(db *statedb.StateDB) { db.AddRefund(uint64(5)) db.SubRefund(uint64(10)) }, 0, true}, @@ -621,7 +619,7 @@ func (suite *StateDBTestSuite) TestIterateStorage() { suite.Require().Equal(1, len(storage)) } -func CollectContractStorage(db vm.StateDB) map[common.Hash]common.Hash { +func CollectContractStorage(db *statedb.StateDB) map[common.Hash]common.Hash { storage := make(map[common.Hash]common.Hash) db.ForEachStorage(address, func(k, v common.Hash) bool { storage[k] = v diff --git a/x/evm/testutil/suite.go b/x/evm/testutil/suite.go index 9b14e01a83..93da489a21 100644 --- a/x/evm/testutil/suite.go +++ b/x/evm/testutil/suite.go @@ -30,7 +30,6 @@ import ( ethermint "github.com/evmos/ethermint/types" "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/types" - "github.com/evmos/ethermint/x/evm/vm" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -228,11 +227,11 @@ func (suite *TestSuite) Commit() { suite.QueryClient = types.NewQueryClient(queryHelper) } -func (suite *TestSuite) StateDB() vm.StateDB { +func (suite *TestSuite) StateDB() *statedb.StateDB { return statedb.New( suite.Ctx, suite.App.EvmKeeper, - types.NewEmptyTxConfig(common.BytesToHash(suite.Ctx.HeaderHash().Bytes())), + statedb.NewEmptyTxConfig(common.BytesToHash(suite.Ctx.HeaderHash().Bytes())), ) } diff --git a/x/evm/types/statedb.go b/x/evm/types/statedb.go deleted file mode 100644 index 866cfd3441..0000000000 --- a/x/evm/types/statedb.go +++ /dev/null @@ -1,61 +0,0 @@ -package types - -import ( - "bytes" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" -) - -var emptyCodeHash = crypto.Keccak256(nil) - -// StateDBAccount is the Ethereum consensus representation of accounts. -// These objects are stored in the storage of auth module. -type StateDBAccount struct { - Nonce uint64 - Balance *big.Int - CodeHash []byte -} - -// NewEmptyAccount returns an empty account. -func NewEmptyAccount() *StateDBAccount { - return &StateDBAccount{ - Balance: new(big.Int), - CodeHash: emptyCodeHash, - } -} - -// IsContract returns if the account contains contract code. -func (acct StateDBAccount) IsContract() bool { - return !bytes.Equal(acct.CodeHash, emptyCodeHash) -} - -// TxConfig encapulates the readonly information of current tx for `StateDB`. -type TxConfig struct { - BlockHash common.Hash // hash of current block - TxHash common.Hash // hash of current tx - TxIndex uint // the index of current transaction - LogIndex uint // the index of next log within current block -} - -// NewTxConfig returns a TxConfig -func NewTxConfig(bhash, thash common.Hash, txIndex, logIndex uint) TxConfig { - return TxConfig{ - BlockHash: bhash, - TxHash: thash, - TxIndex: txIndex, - LogIndex: logIndex, - } -} - -// NewEmptyTxConfig construct an empty TxConfig, -// used in context where there's no transaction, e.g. `eth_call`/`eth_estimateGas`. -func NewEmptyTxConfig(bhash common.Hash) TxConfig { - return TxConfig{ - BlockHash: bhash, - TxHash: common.Hash{}, - TxIndex: 0, - LogIndex: 0, - } -} diff --git a/x/evm/vm/interface.go b/x/evm/vm/interface.go index b9e4c22138..f1a6f4f707 100644 --- a/x/evm/vm/interface.go +++ b/x/evm/vm/interface.go @@ -18,11 +18,7 @@ package vm import ( "math/big" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/evmos/ethermint/x/evm/types" - "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" @@ -83,44 +79,3 @@ type Constructor func( config vm.Config, customPrecompiles PrecompiledContracts, ) EVM - -// StateDBKeeper provide underlying storage of StateDB -type StateDBKeeper interface { - // Read methods - GetAccount(ctx sdk.Context, addr common.Address) *types.StateDBAccount - GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash - GetCode(ctx sdk.Context, codeHash common.Hash) []byte - // the callback returns false to break early - ForEachStorage(ctx sdk.Context, addr common.Address, cb func(key, value common.Hash) bool) - - // Write methods, only called by `StateDB.Commit()` - SetAccount(ctx sdk.Context, addr common.Address, account types.StateDBAccount) error - SetState(ctx sdk.Context, addr common.Address, key common.Hash, value []byte) - SetCode(ctx sdk.Context, codeHash []byte, code []byte) - SetBalance(ctx sdk.Context, addr common.Address, amount *big.Int) error - DeleteAccount(ctx sdk.Context, addr common.Address) error -} - -type StateDB interface { - vm.StateDB - - Keeper() StateDBKeeper - - // Additional methods required by x/evm Keeper - Commit() error - Logs() []*ethtypes.Log -} - -// TxConfig provides readonly information of current tx for `StateDB`. -type TxConfig interface { - BlockHash() common.Hash // hash of current block - TxHash() common.Hash // hash of current tx - TxIndex() uint // the index of current transaction - LogIndex() uint // the index of next log within current block -} - -type StateDBConstructor func( - ctx sdk.Context, - keeper StateDBKeeper, - txConfig types.TxConfig, -) StateDB