types, evm: refactor accounts (#884)
* types,evm: refactor accounts * fix * fix panic * changelog * fix * lint, rm dbErr
This commit is contained in:
parent
eea80d50c3
commit
4320f46fc8
@ -56,6 +56,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
|
|
||||||
|
* (types) [tharsis#884](https://github.com/tharsis/ethermint/pull/884) Introduce a new `EthAccountI` interface for EVM-compatible account types.
|
||||||
* (types) [tharsis#849](https://github.com/tharsis/ethermint/pull/849) Add `Type` function to distinguish EOAs from Contract accounts.
|
* (types) [tharsis#849](https://github.com/tharsis/ethermint/pull/849) Add `Type` function to distinguish EOAs from Contract accounts.
|
||||||
* (evm) [tharsis#826](https://github.com/tharsis/ethermint/issues/826) Improve allocation of bytes of `tx.To` address.
|
* (evm) [tharsis#826](https://github.com/tharsis/ethermint/issues/826) Improve allocation of bytes of `tx.To` address.
|
||||||
* (evm) [tharsis#827](https://github.com/tharsis/ethermint/issues/827) Speed up creation of event logs by using the slice insertion idiom with indices.
|
* (evm) [tharsis#827](https://github.com/tharsis/ethermint/issues/827) Speed up creation of event logs by using the slice insertion idiom with indices.
|
||||||
@ -64,6 +65,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
* (evm) [tharsis#884](https://github.com/tharsis/ethermint/pull/884) Support multiple account types on the EVM `StateDB`.
|
||||||
* (rpc) [tharsis#831](https://github.com/tharsis/ethermint/pull/831) Fix BaseFee value when height is specified.
|
* (rpc) [tharsis#831](https://github.com/tharsis/ethermint/pull/831) Fix BaseFee value when height is specified.
|
||||||
* (evm) [tharsis#838](https://github.com/tharsis/ethermint/pull/838) Fix splitting of trace.Memory into 32 chunks.
|
* (evm) [tharsis#838](https://github.com/tharsis/ethermint/pull/838) Fix splitting of trace.Memory into 32 chunks.
|
||||||
* (rpc) [tharsis#860](https://github.com/tharsis/ethermint/pull/860) Fix `eth_getLogs` when specify blockHash without address/topics, and limit the response size.
|
* (rpc) [tharsis#860](https://github.com/tharsis/ethermint/pull/860) Fix `eth_getLogs` when specify blockHash without address/topics, and limit the response size.
|
||||||
|
@ -115,11 +115,8 @@ func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx
|
|||||||
|
|
||||||
// check whether the sender address is EOA
|
// check whether the sender address is EOA
|
||||||
fromAddr := common.BytesToAddress(from)
|
fromAddr := common.BytesToAddress(from)
|
||||||
acct, err := avd.evmKeeper.GetAccount(ctx, fromAddr)
|
acct := avd.evmKeeper.GetAccount(ctx, fromAddr)
|
||||||
if err != nil {
|
|
||||||
return ctx, sdkerrors.Wrapf(sdkerrors.ErrInvalidType,
|
|
||||||
"the sender is not EthAccount: address %s", fromAddr)
|
|
||||||
}
|
|
||||||
if acct == nil {
|
if acct == nil {
|
||||||
acc := avd.ak.NewAccountWithAddress(ctx, from)
|
acc := avd.ak.NewAccountWithAddress(ctx, from)
|
||||||
avd.ak.SetAccount(ctx, acc)
|
avd.ak.SetAccount(ctx, acc)
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
tx "github.com/cosmos/cosmos-sdk/types/tx"
|
tx "github.com/cosmos/cosmos-sdk/types/tx"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
@ -23,6 +24,7 @@ type EVMKeeper interface {
|
|||||||
ctx sdk.Context, msgEthTx evmtypes.MsgEthereumTx, txData evmtypes.TxData, denom string, homestead, istanbul, london bool,
|
ctx sdk.Context, msgEthTx evmtypes.MsgEthereumTx, txData evmtypes.TxData, denom string, homestead, istanbul, london bool,
|
||||||
) (sdk.Coins, error)
|
) (sdk.Coins, error)
|
||||||
BaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) *big.Int
|
BaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) *big.Int
|
||||||
|
GetBalance(ctx sdk.Context, addr common.Address) *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
type protoTxProvider interface {
|
type protoTxProvider interface {
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
_ authtypes.AccountI = (*EthAccount)(nil)
|
_ authtypes.AccountI = (*EthAccount)(nil)
|
||||||
|
_ EthAccountI = (*EthAccount)(nil)
|
||||||
_ authtypes.GenesisAccount = (*EthAccount)(nil)
|
_ authtypes.GenesisAccount = (*EthAccount)(nil)
|
||||||
_ codectypes.UnpackInterfacesMessage = (*EthAccount)(nil)
|
_ codectypes.UnpackInterfacesMessage = (*EthAccount)(nil)
|
||||||
)
|
)
|
||||||
@ -25,6 +26,19 @@ const (
|
|||||||
AccountTypeContract
|
AccountTypeContract
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EthAccountI represents the interface of an EVM compatible account
|
||||||
|
type EthAccountI interface {
|
||||||
|
authtypes.AccountI
|
||||||
|
// EthAddress returns the ethereum Address representation of the AccAddress
|
||||||
|
EthAddress() common.Address
|
||||||
|
// CodeHash is the keccak256 hash of the contract code (if any)
|
||||||
|
GetCodeHash() common.Hash
|
||||||
|
// SetCodeHash sets the code hash to the account fields
|
||||||
|
SetCodeHash(code common.Hash) error
|
||||||
|
// Type returns the type of Ethereum Account (EOA or Contract)
|
||||||
|
Type() int8
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Main Ethermint account
|
// Main Ethermint account
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -48,6 +62,12 @@ func (acc EthAccount) GetCodeHash() common.Hash {
|
|||||||
return common.HexToHash(acc.CodeHash)
|
return common.HexToHash(acc.CodeHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCodeHash sets the account code hash to the EthAccount fields
|
||||||
|
func (acc *EthAccount) SetCodeHash(codeHash common.Hash) error {
|
||||||
|
acc.CodeHash = codeHash.Hex()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Type returns the type of Ethereum Account (EOA or Contract)
|
// Type returns the type of Ethereum Account (EOA or Contract)
|
||||||
func (acc EthAccount) Type() int8 {
|
func (acc EthAccount) Type() int8 {
|
||||||
if bytes.Equal(emptyCodeHash, common.Hex2Bytes(acc.CodeHash)) {
|
if bytes.Equal(emptyCodeHash, common.Hex2Bytes(acc.CodeHash)) {
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
package types
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Code
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Code is account Code type alias
|
|
||||||
type Code []byte
|
|
||||||
|
|
||||||
func (c Code) String() string {
|
|
||||||
return string(c)
|
|
||||||
}
|
|
@ -40,20 +40,21 @@ func InitGenesis(
|
|||||||
panic(fmt.Errorf("account not found for address %s", account.Address))
|
panic(fmt.Errorf("account not found for address %s", account.Address))
|
||||||
}
|
}
|
||||||
|
|
||||||
ethAcct, ok := acc.(*ethermint.EthAccount)
|
ethAcct, ok := acc.(ethermint.EthAccountI)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(
|
panic(
|
||||||
fmt.Errorf("account %s must be an %T type, got %T",
|
fmt.Errorf("account %s must be an EthAccount interface, got %T",
|
||||||
account.Address, ðermint.EthAccount{}, acc,
|
account.Address, acc,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
code := common.Hex2Bytes(account.Code)
|
code := common.Hex2Bytes(account.Code)
|
||||||
codeHash := crypto.Keccak256Hash(code)
|
codeHash := crypto.Keccak256Hash(code)
|
||||||
if !bytes.Equal(common.HexToHash(ethAcct.CodeHash).Bytes(), codeHash.Bytes()) {
|
if !bytes.Equal(ethAcct.GetCodeHash().Bytes(), codeHash.Bytes()) {
|
||||||
panic("code don't match codeHash")
|
panic("code don't match codeHash")
|
||||||
}
|
}
|
||||||
|
|
||||||
k.SetCode(ctx, codeHash.Bytes(), code)
|
k.SetCode(ctx, codeHash.Bytes(), code)
|
||||||
|
|
||||||
for _, storage := range account.Storage {
|
for _, storage := range account.Storage {
|
||||||
@ -68,7 +69,7 @@ func InitGenesis(
|
|||||||
func ExportGenesis(ctx sdk.Context, k *keeper.Keeper, ak types.AccountKeeper) *types.GenesisState {
|
func ExportGenesis(ctx sdk.Context, k *keeper.Keeper, ak types.AccountKeeper) *types.GenesisState {
|
||||||
var ethGenAccounts []types.GenesisAccount
|
var ethGenAccounts []types.GenesisAccount
|
||||||
ak.IterateAccounts(ctx, func(account authtypes.AccountI) bool {
|
ak.IterateAccounts(ctx, func(account authtypes.AccountI) bool {
|
||||||
ethAccount, ok := account.(*ethermint.EthAccount)
|
ethAccount, ok := account.(ethermint.EthAccountI)
|
||||||
if !ok {
|
if !ok {
|
||||||
// ignore non EthAccounts
|
// ignore non EthAccounts
|
||||||
return false
|
return false
|
||||||
|
@ -48,10 +48,8 @@ func (k Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*typ
|
|||||||
addr := common.HexToAddress(req.Address)
|
addr := common.HexToAddress(req.Address)
|
||||||
|
|
||||||
ctx := sdk.UnwrapSDKContext(c)
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
acct, err := k.GetAccountOrEmpty(ctx, addr)
|
acct := k.GetAccountOrEmpty(ctx, addr)
|
||||||
if err != nil {
|
|
||||||
return nil, status.Error(codes.InvalidArgument, err.Error())
|
|
||||||
}
|
|
||||||
return &types.QueryAccountResponse{
|
return &types.QueryAccountResponse{
|
||||||
Balance: acct.Balance.String(),
|
Balance: acct.Balance.String(),
|
||||||
CodeHash: common.BytesToHash(acct.CodeHash).Hex(),
|
CodeHash: common.BytesToHash(acct.CodeHash).Hex(),
|
||||||
@ -186,10 +184,7 @@ func (k Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.Que
|
|||||||
ctx := sdk.UnwrapSDKContext(c)
|
ctx := sdk.UnwrapSDKContext(c)
|
||||||
|
|
||||||
address := common.HexToAddress(req.Address)
|
address := common.HexToAddress(req.Address)
|
||||||
acct, err := k.GetAccountWithoutBalance(ctx, address)
|
acct := k.GetAccountWithoutBalance(ctx, address)
|
||||||
if err != nil {
|
|
||||||
return nil, status.Error(codes.InvalidArgument, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
var code []byte
|
var code []byte
|
||||||
if acct != nil && acct.IsContract() {
|
if acct != nil && acct.IsContract() {
|
||||||
|
@ -345,9 +345,7 @@ func (suite *KeeperTestSuite) TestQueryCode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestQueryTxLogs() {
|
func (suite *KeeperTestSuite) TestQueryTxLogs() {
|
||||||
var (
|
var expLogs []*types.Log
|
||||||
expLogs []*types.Log
|
|
||||||
)
|
|
||||||
txHash := common.BytesToHash([]byte("tx_hash"))
|
txHash := common.BytesToHash([]byte("tx_hash"))
|
||||||
txIndex := uint(1)
|
txIndex := uint(1)
|
||||||
logIndex := uint(1)
|
logIndex := uint(1)
|
||||||
@ -593,7 +591,7 @@ func (suite *KeeperTestSuite) TestEstimateGas() {
|
|||||||
rsp, err := suite.queryClient.EstimateGas(sdk.WrapSDKContext(suite.ctx), &req)
|
rsp, err := suite.queryClient.EstimateGas(sdk.WrapSDKContext(suite.ctx), &req)
|
||||||
if tc.expPass {
|
if tc.expPass {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
suite.Require().Equal(tc.expGas, rsp.Gas)
|
suite.Require().Equal(int64(tc.expGas), int64(rsp.Gas))
|
||||||
} else {
|
} else {
|
||||||
suite.Require().Error(err)
|
suite.Require().Error(err)
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
|
||||||
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
@ -235,38 +234,37 @@ func (k Keeper) Tracer(ctx sdk.Context, msg core.Message, ethCfg *params.ChainCo
|
|||||||
|
|
||||||
// GetAccountWithoutBalance load nonce and codehash without balance,
|
// GetAccountWithoutBalance load nonce and codehash without balance,
|
||||||
// more efficient in cases where balance is not needed.
|
// more efficient in cases where balance is not needed.
|
||||||
func (k *Keeper) GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) (*statedb.Account, error) {
|
func (k *Keeper) GetAccountWithoutBalance(ctx sdk.Context, addr common.Address) *statedb.Account {
|
||||||
cosmosAddr := sdk.AccAddress(addr.Bytes())
|
cosmosAddr := sdk.AccAddress(addr.Bytes())
|
||||||
acct := k.accountKeeper.GetAccount(ctx, cosmosAddr)
|
acct := k.accountKeeper.GetAccount(ctx, cosmosAddr)
|
||||||
if acct == nil {
|
if acct == nil {
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ethAcct, ok := acct.(*ethermint.EthAccount)
|
codeHash := types.EmptyCodeHash
|
||||||
if !ok {
|
ethAcct, ok := acct.(ethermint.EthAccountI)
|
||||||
return nil, sdkerrors.Wrapf(types.ErrInvalidAccount, "type %T, address %s", acct, addr)
|
if ok {
|
||||||
|
codeHash = ethAcct.GetCodeHash().Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
return &statedb.Account{
|
return &statedb.Account{
|
||||||
Nonce: ethAcct.Sequence,
|
Nonce: acct.GetSequence(),
|
||||||
CodeHash: common.FromHex(ethAcct.CodeHash),
|
CodeHash: codeHash,
|
||||||
}, nil
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAccountOrEmpty returns empty account if not exist, returns error if it's not `EthAccount`
|
// GetAccountOrEmpty returns empty account if not exist, returns error if it's not `EthAccount`
|
||||||
func (k *Keeper) GetAccountOrEmpty(ctx sdk.Context, addr common.Address) (statedb.Account, error) {
|
func (k *Keeper) GetAccountOrEmpty(ctx sdk.Context, addr common.Address) statedb.Account {
|
||||||
acct, err := k.GetAccount(ctx, addr)
|
acct := k.GetAccount(ctx, addr)
|
||||||
if err != nil {
|
if acct != nil {
|
||||||
return statedb.Account{}, err
|
return *acct
|
||||||
}
|
}
|
||||||
if acct == nil {
|
|
||||||
// empty account
|
// empty account
|
||||||
return statedb.Account{
|
return statedb.Account{
|
||||||
Balance: new(big.Int),
|
Balance: new(big.Int),
|
||||||
CodeHash: types.EmptyCodeHash,
|
CodeHash: types.EmptyCodeHash,
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
return *acct, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNonce returns the sequence number of an account, returns 0 if not exists.
|
// GetNonce returns the sequence number of an account, returns 0 if not exists.
|
||||||
@ -277,12 +275,7 @@ func (k *Keeper) GetNonce(ctx sdk.Context, addr common.Address) uint64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
ethAcct, ok := acct.(*ethermint.EthAccount)
|
return acct.GetSequence()
|
||||||
if !ok {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return ethAcct.Sequence
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBalance load account's balance of gas token
|
// GetBalance load account's balance of gas token
|
||||||
|
@ -17,18 +17,18 @@ import (
|
|||||||
var _ statedb.Keeper = &Keeper{}
|
var _ statedb.Keeper = &Keeper{}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// statedb.Keeper implementation
|
// StateDB Keeper implementation
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// GetAccount returns nil if account is not exist, returns error if it's not `EthAccount`
|
// 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) (*statedb.Account, error) {
|
func (k *Keeper) GetAccount(ctx sdk.Context, addr common.Address) *statedb.Account {
|
||||||
acct, err := k.GetAccountWithoutBalance(ctx, addr)
|
acct := k.GetAccountWithoutBalance(ctx, addr)
|
||||||
if acct == nil || err != nil {
|
if acct == nil {
|
||||||
return acct, err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
acct.Balance = k.GetBalance(ctx, addr)
|
acct.Balance = k.GetBalance(ctx, addr)
|
||||||
return acct, nil
|
return acct
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetState loads contract state from database, implements `statedb.Keeper` interface.
|
// GetState loads contract state from database, implements `statedb.Keeper` interface.
|
||||||
@ -109,25 +109,33 @@ func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account stated
|
|||||||
if acct == nil {
|
if acct == nil {
|
||||||
acct = k.accountKeeper.NewAccountWithAddress(ctx, cosmosAddr)
|
acct = k.accountKeeper.NewAccountWithAddress(ctx, cosmosAddr)
|
||||||
}
|
}
|
||||||
ethAcct, ok := acct.(*ethermint.EthAccount)
|
|
||||||
if !ok {
|
if err := acct.SetSequence(account.Nonce); err != nil {
|
||||||
return sdkerrors.Wrapf(types.ErrInvalidAccount, "type %T, address %s", acct, addr)
|
return err
|
||||||
}
|
}
|
||||||
if err := ethAcct.SetSequence(account.Nonce); err != nil {
|
|
||||||
|
codeHash := common.BytesToHash(account.CodeHash)
|
||||||
|
|
||||||
|
if ethAcct, ok := acct.(ethermint.EthAccountI); ok {
|
||||||
|
if err := ethAcct.SetCodeHash(codeHash); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k.accountKeeper.SetAccount(ctx, acct)
|
||||||
|
|
||||||
|
if err := k.SetBalance(ctx, addr, account.Balance); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ethAcct.CodeHash = common.BytesToHash(account.CodeHash).Hex()
|
|
||||||
k.accountKeeper.SetAccount(ctx, ethAcct)
|
|
||||||
|
|
||||||
err := k.SetBalance(ctx, addr, account.Balance)
|
|
||||||
k.Logger(ctx).Debug(
|
k.Logger(ctx).Debug(
|
||||||
"account updated",
|
"account updated",
|
||||||
"ethereum-address", addr.Hex(),
|
"ethereum-address", addr.Hex(),
|
||||||
"nonce", account.Nonce,
|
"nonce", account.Nonce,
|
||||||
"codeHash", common.BytesToHash(account.CodeHash).Hex(),
|
"codeHash", codeHash.Hex(),
|
||||||
"balance", account.Balance,
|
"balance", account.Balance,
|
||||||
)
|
)
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetState update contract storage, delete if value is empty.
|
// SetState update contract storage, delete if value is empty.
|
||||||
@ -177,7 +185,8 @@ func (k *Keeper) DeleteAccount(ctx sdk.Context, addr common.Address) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ethAcct, ok := acct.(*ethermint.EthAccount)
|
// NOTE: only Ethereum accounts (contracts) can be selfdestructed
|
||||||
|
ethAcct, ok := acct.(ethermint.EthAccountI)
|
||||||
if !ok {
|
if !ok {
|
||||||
return sdkerrors.Wrapf(types.ErrInvalidAccount, "type %T, address %s", acct, addr)
|
return sdkerrors.Wrapf(types.ErrInvalidAccount, "type %T, address %s", acct, addr)
|
||||||
}
|
}
|
||||||
@ -188,9 +197,9 @@ func (k *Keeper) DeleteAccount(ctx sdk.Context, addr common.Address) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove code
|
// remove code
|
||||||
codeHash := common.HexToHash(ethAcct.CodeHash).Bytes()
|
codeHashBz := ethAcct.GetCodeHash().Bytes()
|
||||||
if !bytes.Equal(codeHash, types.EmptyCodeHash) {
|
if !bytes.Equal(codeHashBz, types.EmptyCodeHash) {
|
||||||
k.SetCode(ctx, codeHash, nil)
|
k.SetCode(ctx, codeHashBz, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear storage
|
// clear storage
|
||||||
|
@ -235,9 +235,9 @@ func (suite *KeeperTestSuite) TestGetCodeHash() {
|
|||||||
func(vm.StateDB) {},
|
func(vm.StateDB) {},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"account not EthAccount type, error",
|
"account not EthAccount type, EmptyCodeHash",
|
||||||
addr,
|
addr,
|
||||||
common.Hash{},
|
common.BytesToHash(types.EmptyCodeHash),
|
||||||
func(vm.StateDB) {},
|
func(vm.StateDB) {},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -469,27 +469,21 @@ func (suite *KeeperTestSuite) TestExist() {
|
|||||||
|
|
||||||
func (suite *KeeperTestSuite) TestEmpty() {
|
func (suite *KeeperTestSuite) TestEmpty() {
|
||||||
suite.SetupTest()
|
suite.SetupTest()
|
||||||
addr := tests.GenerateAddress()
|
|
||||||
baseAcc := &authtypes.BaseAccount{Address: sdk.AccAddress(addr.Bytes()).String()}
|
|
||||||
suite.app.AccountKeeper.SetAccount(suite.ctx, baseAcc)
|
|
||||||
|
|
||||||
acct, err := suite.app.EvmKeeper.GetAccount(suite.ctx, suite.address)
|
|
||||||
suite.Require().NoError(err)
|
|
||||||
fmt.Println("default address", acct)
|
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
address common.Address
|
address common.Address
|
||||||
malleate func(vm.StateDB)
|
malleate func(vm.StateDB)
|
||||||
empty bool
|
empty bool
|
||||||
expErr bool
|
|
||||||
}{
|
}{
|
||||||
{"empty, account exists", suite.address, func(vm.StateDB) {}, true, false},
|
{"empty, account exists", suite.address, func(vm.StateDB) {}, true},
|
||||||
{"error, non ethereum account", addr, func(vm.StateDB) {}, true, true},
|
{
|
||||||
{"not empty, positive balance", suite.address, func(vmdb vm.StateDB) {
|
"not empty, positive balance",
|
||||||
vmdb.AddBalance(suite.address, big.NewInt(100))
|
suite.address,
|
||||||
}, false, false},
|
func(vmdb vm.StateDB) { vmdb.AddBalance(suite.address, big.NewInt(100)) },
|
||||||
{"empty, account doesn't exist", tests.GenerateAddress(), func(vm.StateDB) {}, true, false},
|
false,
|
||||||
|
},
|
||||||
|
{"empty, account doesn't exist", tests.GenerateAddress(), func(vm.StateDB) {}, true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
@ -498,11 +492,6 @@ func (suite *KeeperTestSuite) TestEmpty() {
|
|||||||
tc.malleate(vmdb)
|
tc.malleate(vmdb)
|
||||||
|
|
||||||
suite.Require().Equal(tc.empty, vmdb.Empty(tc.address))
|
suite.Require().Equal(tc.empty, vmdb.Empty(tc.address))
|
||||||
if tc.expErr {
|
|
||||||
suite.Require().Error(vmdb.Error())
|
|
||||||
} else {
|
|
||||||
suite.Require().NoError(vmdb.Error())
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,9 +235,8 @@ func (suite *KeeperTestSuite) TestCheckSenderBalance() {
|
|||||||
|
|
||||||
txData, _ := evmtypes.UnpackTxData(tx.Data)
|
txData, _ := evmtypes.UnpackTxData(tx.Data)
|
||||||
|
|
||||||
acct, err := suite.app.EvmKeeper.GetAccountOrEmpty(suite.ctx, suite.address)
|
acct := suite.app.EvmKeeper.GetAccountOrEmpty(suite.ctx, suite.address)
|
||||||
suite.Require().NoError(err)
|
err := evmkeeper.CheckSenderBalance(
|
||||||
err = evmkeeper.CheckSenderBalance(
|
|
||||||
sdk.NewIntFromBigInt(acct.Balance),
|
sdk.NewIntFromBigInt(acct.Balance),
|
||||||
txData,
|
txData,
|
||||||
)
|
)
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
// Keeper provide underlying storage of StateDB
|
// Keeper provide underlying storage of StateDB
|
||||||
type Keeper interface {
|
type Keeper interface {
|
||||||
// Read methods
|
// Read methods
|
||||||
GetAccount(ctx sdk.Context, addr common.Address) (*Account, error)
|
GetAccount(ctx sdk.Context, addr common.Address) *Account
|
||||||
GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash
|
GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash
|
||||||
GetCode(ctx sdk.Context, codeHash common.Hash) []byte
|
GetCode(ctx sdk.Context, codeHash common.Hash) []byte
|
||||||
// the callback returns false to break early
|
// the callback returns false to break early
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package statedb_test
|
package statedb_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
@ -29,15 +28,12 @@ func NewMockKeeper() *MockKeeper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k MockKeeper) GetAccount(ctx sdk.Context, addr common.Address) (*statedb.Account, error) {
|
func (k MockKeeper) GetAccount(ctx sdk.Context, addr common.Address) *statedb.Account {
|
||||||
if addr == k.errAddress {
|
|
||||||
return nil, errors.New("mock db error")
|
|
||||||
}
|
|
||||||
acct, ok := k.accounts[addr]
|
acct, ok := k.accounts[addr]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
return &acct, nil
|
return &acct
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k MockKeeper) GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash {
|
func (k MockKeeper) GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash {
|
||||||
|
@ -31,7 +31,6 @@ var _ vm.StateDB = &StateDB{}
|
|||||||
type StateDB struct {
|
type StateDB struct {
|
||||||
keeper Keeper
|
keeper Keeper
|
||||||
ctx sdk.Context
|
ctx sdk.Context
|
||||||
dbErr error
|
|
||||||
|
|
||||||
// Journal of state modifications. This is the backbone of
|
// Journal of state modifications. This is the backbone of
|
||||||
// Snapshot and RevertToSnapshot.
|
// Snapshot and RevertToSnapshot.
|
||||||
@ -76,18 +75,6 @@ func (s *StateDB) Context() sdk.Context {
|
|||||||
return s.ctx
|
return s.ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// setError remembers the first non-nil error it is called with.
|
|
||||||
func (s *StateDB) setError(err error) {
|
|
||||||
if s.dbErr == nil {
|
|
||||||
s.dbErr = err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns the database error recorded.
|
|
||||||
func (s *StateDB) Error() error {
|
|
||||||
return s.dbErr
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddLog adds a log, called by evm.
|
// AddLog adds a log, called by evm.
|
||||||
func (s *StateDB) AddLog(log *ethtypes.Log) {
|
func (s *StateDB) AddLog(log *ethtypes.Log) {
|
||||||
s.journal.append(addLogChange{})
|
s.journal.append(addLogChange{})
|
||||||
@ -235,11 +222,7 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject {
|
|||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
// If no live objects are available, load it from keeper
|
// If no live objects are available, load it from keeper
|
||||||
account, err := s.keeper.GetAccount(s.ctx, addr)
|
account := s.keeper.GetAccount(s.ctx, addr)
|
||||||
if err != nil {
|
|
||||||
s.setError(err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if account == nil {
|
if account == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -468,9 +451,6 @@ func (s *StateDB) RevertToSnapshot(revid int) {
|
|||||||
// Commit writes the dirty states to keeper
|
// Commit writes the dirty states to keeper
|
||||||
// the StateDB object should be discarded after committed.
|
// the StateDB object should be discarded after committed.
|
||||||
func (s *StateDB) Commit() error {
|
func (s *StateDB) Commit() error {
|
||||||
if s.dbErr != nil {
|
|
||||||
return fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr)
|
|
||||||
}
|
|
||||||
for _, addr := range s.journal.sortedDirties() {
|
for _, addr := range s.journal.sortedDirties() {
|
||||||
obj := s.stateObjects[addr]
|
obj := s.stateObjects[addr]
|
||||||
if obj.suicided {
|
if obj.suicided {
|
||||||
|
@ -17,7 +17,6 @@ type StateDBTestSuite struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StateDBTestSuite) TestAccounts() {
|
func (suite *StateDBTestSuite) TestAccounts() {
|
||||||
addrErr := common.BigToAddress(big.NewInt(1))
|
|
||||||
addr2 := common.BigToAddress(big.NewInt(2))
|
addr2 := common.BigToAddress(big.NewInt(2))
|
||||||
testTxConfig := statedb.NewTxConfig(
|
testTxConfig := statedb.NewTxConfig(
|
||||||
common.BigToHash(big.NewInt(10)), // tx hash
|
common.BigToHash(big.NewInt(10)), // tx hash
|
||||||
@ -31,7 +30,7 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
test func(*statedb.StateDB)
|
test func(*statedb.StateDB)
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"success,empty account",
|
"success, empty account",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
suite.Require().Equal(true, db.Empty(addr2))
|
suite.Require().Equal(true, db.Empty(addr2))
|
||||||
suite.Require().Equal(big.NewInt(0), db.GetBalance(addr2))
|
suite.Require().Equal(big.NewInt(0), db.GetBalance(addr2))
|
||||||
@ -40,21 +39,14 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"success,GetBalance",
|
"success, GetBalance",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
db.AddBalance(addr2, big.NewInt(1))
|
db.AddBalance(addr2, big.NewInt(1))
|
||||||
suite.Require().Equal(big.NewInt(1), db.GetBalance(addr2))
|
suite.Require().Equal(big.NewInt(1), db.GetBalance(addr2))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fail,GetBalance dbErr",
|
"success, change balance",
|
||||||
func(db *statedb.StateDB) {
|
|
||||||
suite.Require().Equal(big.NewInt(0), db.GetBalance(addrErr))
|
|
||||||
suite.Require().Error(db.Commit())
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"success,change balance",
|
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
db.AddBalance(addr2, big.NewInt(2))
|
db.AddBalance(addr2, big.NewInt(2))
|
||||||
suite.Require().Equal(big.NewInt(2), db.GetBalance(addr2))
|
suite.Require().Equal(big.NewInt(2), db.GetBalance(addr2))
|
||||||
@ -69,7 +61,7 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"success,SetState",
|
"success, SetState",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
key := common.BigToHash(big.NewInt(1))
|
key := common.BigToHash(big.NewInt(1))
|
||||||
value := common.BigToHash(big.NewInt(1))
|
value := common.BigToHash(big.NewInt(1))
|
||||||
@ -81,7 +73,7 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"success,SetCode",
|
"success, SetCode",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
code := []byte("hello world")
|
code := []byte("hello world")
|
||||||
codeHash := crypto.Keccak256Hash(code)
|
codeHash := crypto.Keccak256Hash(code)
|
||||||
@ -98,7 +90,7 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"success,CreateAccount",
|
"success, CreateAccount",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
// test balance carry over when overwritten
|
// test balance carry over when overwritten
|
||||||
amount := big.NewInt(1)
|
amount := big.NewInt(1)
|
||||||
@ -131,7 +123,7 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"success,nested snapshot revert",
|
"success, nested snapshot revert",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
key := common.BigToHash(big.NewInt(1))
|
key := common.BigToHash(big.NewInt(1))
|
||||||
value1 := common.BigToHash(big.NewInt(1))
|
value1 := common.BigToHash(big.NewInt(1))
|
||||||
@ -152,7 +144,7 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"success,nonce",
|
"success, nonce",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
suite.Require().Equal(uint64(0), db.GetNonce(addr2))
|
suite.Require().Equal(uint64(0), db.GetNonce(addr2))
|
||||||
db.SetNonce(addr2, 1)
|
db.SetNonce(addr2, 1)
|
||||||
@ -165,7 +157,7 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"success,logs",
|
"success, logs",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
data := []byte("hello world")
|
data := []byte("hello world")
|
||||||
db.AddLog(ðtypes.Log{
|
db.AddLog(ðtypes.Log{
|
||||||
@ -203,7 +195,7 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"success,refund",
|
"success, refund",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
db.AddRefund(uint64(10))
|
db.AddRefund(uint64(10))
|
||||||
suite.Require().Equal(uint64(10), db.GetRefund())
|
suite.Require().Equal(uint64(10), db.GetRefund())
|
||||||
@ -218,7 +210,7 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"success,empty",
|
"success, empty",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
suite.Require().False(db.Exist(addr2))
|
suite.Require().False(db.Exist(addr2))
|
||||||
suite.Require().True(db.Empty(addr2))
|
suite.Require().True(db.Empty(addr2))
|
||||||
@ -233,7 +225,7 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"success,suicide commit",
|
"success, suicide commit",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
code := []byte("hello world")
|
code := []byte("hello world")
|
||||||
db.SetCode(addr2, code)
|
db.SetCode(addr2, code)
|
||||||
@ -253,7 +245,7 @@ func (suite *StateDBTestSuite) TestAccounts() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"success,suicide revert",
|
"success, suicide revert",
|
||||||
func(db *statedb.StateDB) {
|
func(db *statedb.StateDB) {
|
||||||
code := []byte("hello world")
|
code := []byte("hello world")
|
||||||
db.SetCode(addr2, code)
|
db.SetCode(addr2, code)
|
||||||
|
Loading…
Reference in New Issue
Block a user