keeper: StateDB
unit tests (#47)
* keeper: statedb unit tests * evm: balance tests * evm: nonce and code tests * evm: refund test * evm: fix tx encoding * storage and access list tests
This commit is contained in:
parent
8e7ebe80e9
commit
c08dcfad0c
@ -7,9 +7,11 @@ import (
|
|||||||
"github.com/cosmos/cosmos-sdk/simapp/params"
|
"github.com/cosmos/cosmos-sdk/simapp/params"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||||
evmtypes "github.com/cosmos/ethermint/x/evm/types"
|
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
||||||
"github.com/cosmos/ethermint/codec"
|
"github.com/cosmos/ethermint/codec"
|
||||||
|
evmtypes "github.com/cosmos/ethermint/x/evm/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MakeEncodingConfig creates an EncodingConfig for testing
|
// MakeEncodingConfig creates an EncodingConfig for testing
|
||||||
@ -49,9 +51,9 @@ func NewTxConfig(marshaler amino.ProtoCodecMarshaler) client.TxConfig {
|
|||||||
// TxEncoder overwrites sdk.TxEncoder to support MsgEthereumTx
|
// TxEncoder overwrites sdk.TxEncoder to support MsgEthereumTx
|
||||||
func (g txConfig) TxEncoder() sdk.TxEncoder {
|
func (g txConfig) TxEncoder() sdk.TxEncoder {
|
||||||
return func(tx sdk.Tx) ([]byte, error) {
|
return func(tx sdk.Tx) ([]byte, error) {
|
||||||
ethtx, ok := tx.(*evmtypes.MsgEthereumTx)
|
msg, ok := tx.(*evmtypes.MsgEthereumTx)
|
||||||
if ok {
|
if ok {
|
||||||
return g.cdc.MarshalBinaryBare(ethtx)
|
return msg.AsTransaction().MarshalBinary()
|
||||||
}
|
}
|
||||||
return g.TxConfig.TxEncoder()(tx)
|
return g.TxConfig.TxEncoder()(tx)
|
||||||
}
|
}
|
||||||
@ -60,11 +62,13 @@ func (g txConfig) TxEncoder() sdk.TxEncoder {
|
|||||||
// TxDecoder overwrites sdk.TxDecoder to support MsgEthereumTx
|
// TxDecoder overwrites sdk.TxDecoder to support MsgEthereumTx
|
||||||
func (g txConfig) TxDecoder() sdk.TxDecoder {
|
func (g txConfig) TxDecoder() sdk.TxDecoder {
|
||||||
return func(txBytes []byte) (sdk.Tx, error) {
|
return func(txBytes []byte) (sdk.Tx, error) {
|
||||||
var ethtx evmtypes.MsgEthereumTx
|
tx := ðtypes.Transaction{}
|
||||||
|
|
||||||
err := g.cdc.UnmarshalBinaryBare(txBytes, ðtx)
|
err := tx.UnmarshalBinary(txBytes)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return ðtx, nil
|
msg := &evmtypes.MsgEthereumTx{}
|
||||||
|
msg.FromEthereumTx(tx)
|
||||||
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return g.TxConfig.TxDecoder()(txBytes)
|
return g.TxConfig.TxDecoder()(txBytes)
|
||||||
|
@ -3,6 +3,9 @@ package tests
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
@ -10,6 +13,20 @@ import (
|
|||||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewAddrKey generates an Ethereum address and its corresponding private key.
|
||||||
|
func NewAddrKey() (common.Address, cryptotypes.PrivKey) {
|
||||||
|
privkey, _ := ethsecp256k1.GenerateKey()
|
||||||
|
addr := crypto.PubkeyToAddress(privkey.ToECDSA().PublicKey)
|
||||||
|
|
||||||
|
return addr, privkey
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateAddress generates an Ethereum address.
|
||||||
|
func GenerateAddress() common.Address {
|
||||||
|
addr, _ := NewAddrKey()
|
||||||
|
return addr
|
||||||
|
}
|
||||||
|
|
||||||
var _ keyring.Signer = &Signer{}
|
var _ keyring.Signer = &Signer{}
|
||||||
|
|
||||||
// Signer defines a type that is used on testing for signing MsgEthereumTx
|
// Signer defines a type that is used on testing for signing MsgEthereumTx
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package keeper_test
|
package keeper_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math/big"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -16,7 +15,6 @@ import (
|
|||||||
"github.com/cosmos/ethermint/x/evm/types"
|
"github.com/cosmos/ethermint/x/evm/types"
|
||||||
|
|
||||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
|
||||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
|
|
||||||
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
||||||
@ -43,7 +41,7 @@ func (suite *KeeperTestSuite) SetupTest() {
|
|||||||
|
|
||||||
suite.app = app.Setup(checkTx)
|
suite.app = app.Setup(checkTx)
|
||||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "ethermint-1", Time: time.Now().UTC()})
|
suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "ethermint-1", Time: time.Now().UTC()})
|
||||||
suite.app.EvmKeeper.CommitStateDB.WithContext(suite.ctx)
|
suite.app.EvmKeeper.WithContext(suite.ctx)
|
||||||
|
|
||||||
suite.address = ethcmn.HexToAddress(addrHex)
|
suite.address = ethcmn.HexToAddress(addrHex)
|
||||||
|
|
||||||
@ -65,82 +63,6 @@ func TestKeeperTestSuite(t *testing.T) {
|
|||||||
suite.Run(t, new(KeeperTestSuite))
|
suite.Run(t, new(KeeperTestSuite))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestTransactionLogs() {
|
|
||||||
ethHash := ethcmn.BytesToHash(hash)
|
|
||||||
log := ðtypes.Log{
|
|
||||||
Address: suite.address,
|
|
||||||
Data: []byte("log"),
|
|
||||||
BlockNumber: 10,
|
|
||||||
}
|
|
||||||
log2 := ðtypes.Log{
|
|
||||||
Address: suite.address,
|
|
||||||
Data: []byte("log2"),
|
|
||||||
BlockNumber: 11,
|
|
||||||
}
|
|
||||||
expLogs := []*ethtypes.Log{log}
|
|
||||||
|
|
||||||
err := suite.app.EvmKeeper.CommitStateDB.SetLogs(ethHash, expLogs)
|
|
||||||
suite.Require().NoError(err)
|
|
||||||
|
|
||||||
logs, err := suite.app.EvmKeeper.CommitStateDB.GetLogs(ethHash)
|
|
||||||
suite.Require().NoError(err)
|
|
||||||
suite.Require().Equal(expLogs, logs)
|
|
||||||
|
|
||||||
expLogs = []*ethtypes.Log{log2, log}
|
|
||||||
|
|
||||||
// add another log under the zero hash
|
|
||||||
suite.app.EvmKeeper.CommitStateDB.AddLog(log2)
|
|
||||||
logs = suite.app.EvmKeeper.CommitStateDB.AllLogs()
|
|
||||||
suite.Require().Equal(expLogs, logs)
|
|
||||||
|
|
||||||
// add another log under the zero hash
|
|
||||||
log3 := ðtypes.Log{
|
|
||||||
Address: suite.address,
|
|
||||||
Data: []byte("log3"),
|
|
||||||
BlockNumber: 10,
|
|
||||||
}
|
|
||||||
suite.app.EvmKeeper.CommitStateDB.AddLog(log3)
|
|
||||||
|
|
||||||
txLogs := suite.app.EvmKeeper.GetAllTxLogs(suite.ctx)
|
|
||||||
suite.Require().Equal(2, len(txLogs))
|
|
||||||
|
|
||||||
suite.Require().Equal(ethcmn.Hash{}.String(), txLogs[0].Hash)
|
|
||||||
suite.Require().Equal([]*ethtypes.Log{log2, log3}, txLogs[0].Logs)
|
|
||||||
|
|
||||||
suite.Require().Equal(ethHash.String(), txLogs[1].Hash)
|
|
||||||
suite.Require().Equal([]*ethtypes.Log{log}, txLogs[1].Logs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestDBStorage() {
|
|
||||||
// Perform state transitions
|
|
||||||
suite.app.EvmKeeper.CommitStateDB.CreateAccount(suite.address)
|
|
||||||
suite.app.EvmKeeper.CommitStateDB.SetBalance(suite.address, big.NewInt(5))
|
|
||||||
suite.app.EvmKeeper.CommitStateDB.SetNonce(suite.address, 4)
|
|
||||||
suite.app.EvmKeeper.CommitStateDB.SetState(suite.address, ethcmn.HexToHash("0x2"), ethcmn.HexToHash("0x3"))
|
|
||||||
suite.app.EvmKeeper.CommitStateDB.SetCode(suite.address, []byte{0x1})
|
|
||||||
|
|
||||||
// Test block height mapping functionality
|
|
||||||
testBloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
|
|
||||||
suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 4, testBloom)
|
|
||||||
|
|
||||||
// Get those state transitions
|
|
||||||
suite.Require().Equal(suite.app.EvmKeeper.CommitStateDB.GetBalance(suite.address).Cmp(big.NewInt(5)), 0)
|
|
||||||
suite.Require().Equal(suite.app.EvmKeeper.CommitStateDB.GetNonce(suite.address), uint64(4))
|
|
||||||
suite.Require().Equal(suite.app.EvmKeeper.CommitStateDB.GetState(suite.address, ethcmn.HexToHash("0x2")), ethcmn.HexToHash("0x3"))
|
|
||||||
suite.Require().Equal(suite.app.EvmKeeper.CommitStateDB.GetCode(suite.address), []byte{0x1})
|
|
||||||
|
|
||||||
bloom, found := suite.app.EvmKeeper.GetBlockBloom(suite.ctx, 4)
|
|
||||||
suite.Require().True(found)
|
|
||||||
suite.Require().Equal(bloom, testBloom)
|
|
||||||
|
|
||||||
// commit stateDB
|
|
||||||
_, err := suite.app.EvmKeeper.CommitStateDB.Commit(false)
|
|
||||||
suite.Require().NoError(err, "failed to commit StateDB")
|
|
||||||
|
|
||||||
// simulate BaseApp EndBlocker commitment
|
|
||||||
suite.app.Commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) TestChainConfig() {
|
func (suite *KeeperTestSuite) TestChainConfig() {
|
||||||
config, found := suite.app.EvmKeeper.GetChainConfig(suite.ctx)
|
config, found := suite.app.EvmKeeper.GetChainConfig(suite.ctx)
|
||||||
suite.Require().True(found)
|
suite.Require().True(found)
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
tmtypes "github.com/tendermint/tendermint/types"
|
|
||||||
|
|
||||||
"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"
|
||||||
@ -37,7 +36,8 @@ func (k *Keeper) CreateAccount(addr common.Address) {
|
|||||||
k.ResetAccount(addr)
|
k.ResetAccount(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = k.accountKeeper.NewAccountWithAddress(k.ctx, cosmosAddr)
|
account = k.accountKeeper.NewAccountWithAddress(k.ctx, cosmosAddr)
|
||||||
|
k.accountKeeper.SetAccount(k.ctx, account)
|
||||||
|
|
||||||
k.Logger(k.ctx).Debug(
|
k.Logger(k.ctx).Debug(
|
||||||
log,
|
log,
|
||||||
@ -52,6 +52,15 @@ func (k *Keeper) CreateAccount(addr common.Address) {
|
|||||||
|
|
||||||
// AddBalance calls CommitStateDB.AddBalance using the passed in context
|
// AddBalance calls CommitStateDB.AddBalance using the passed in context
|
||||||
func (k *Keeper) AddBalance(addr common.Address, amount *big.Int) {
|
func (k *Keeper) AddBalance(addr common.Address, amount *big.Int) {
|
||||||
|
if amount.Sign() != 1 {
|
||||||
|
k.Logger(k.ctx).Debug(
|
||||||
|
"ignored non-positive amount addition",
|
||||||
|
"ethereum-address", addr.Hex(),
|
||||||
|
"amount", amount.Int64(),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
cosmosAddr := sdk.AccAddress(addr.Bytes())
|
cosmosAddr := sdk.AccAddress(addr.Bytes())
|
||||||
|
|
||||||
params := k.GetParams(k.ctx)
|
params := k.GetParams(k.ctx)
|
||||||
@ -76,6 +85,15 @@ func (k *Keeper) AddBalance(addr common.Address, amount *big.Int) {
|
|||||||
|
|
||||||
// SubBalance calls CommitStateDB.SubBalance using the passed in context
|
// SubBalance calls CommitStateDB.SubBalance using the passed in context
|
||||||
func (k *Keeper) SubBalance(addr common.Address, amount *big.Int) {
|
func (k *Keeper) SubBalance(addr common.Address, amount *big.Int) {
|
||||||
|
if amount.Sign() != 1 {
|
||||||
|
k.Logger(k.ctx).Debug(
|
||||||
|
"ignored non-positive amount addition",
|
||||||
|
"ethereum-address", addr.Hex(),
|
||||||
|
"amount", amount.Int64(),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
cosmosAddr := sdk.AccAddress(addr.Bytes())
|
cosmosAddr := sdk.AccAddress(addr.Bytes())
|
||||||
|
|
||||||
params := k.GetParams(k.ctx)
|
params := k.GetParams(k.ctx)
|
||||||
@ -128,7 +146,8 @@ func (k *Keeper) GetNonce(addr common.Address) uint64 {
|
|||||||
return nonce
|
return nonce
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetNonce calls CommitStateDB.SetNonce using the passed in context
|
// SetNonce sets the given nonce as the sequence of the address' account. If the
|
||||||
|
// account doesn't exist, a new one will be created from the address.
|
||||||
func (k *Keeper) SetNonce(addr common.Address, nonce uint64) {
|
func (k *Keeper) SetNonce(addr common.Address, nonce uint64) {
|
||||||
cosmosAddr := sdk.AccAddress(addr.Bytes())
|
cosmosAddr := sdk.AccAddress(addr.Bytes())
|
||||||
account := k.accountKeeper.GetAccount(k.ctx, cosmosAddr)
|
account := k.accountKeeper.GetAccount(k.ctx, cosmosAddr)
|
||||||
@ -215,6 +234,7 @@ func (k *Keeper) SetCode(addr common.Address, code []byte) {
|
|||||||
account := k.accountKeeper.GetAccount(k.ctx, addr.Bytes())
|
account := k.accountKeeper.GetAccount(k.ctx, addr.Bytes())
|
||||||
if account == nil {
|
if account == nil {
|
||||||
account = k.accountKeeper.NewAccountWithAddress(k.ctx, addr.Bytes())
|
account = k.accountKeeper.NewAccountWithAddress(k.ctx, addr.Bytes())
|
||||||
|
k.accountKeeper.SetAccount(k.ctx, account)
|
||||||
}
|
}
|
||||||
|
|
||||||
ethAccount, isEthAccount := account.(*ethermint.EthAccount)
|
ethAccount, isEthAccount := account.(*ethermint.EthAccount)
|
||||||
@ -306,7 +326,8 @@ func (k *Keeper) GetRefund() uint64 {
|
|||||||
// State
|
// State
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// GetCommittedState calls CommitStateDB.GetCommittedState using the passed in context
|
// GetCommittedState returns the value set in store for the given key hash. If the key is not registered
|
||||||
|
// this function returns the empty hash.
|
||||||
func (k *Keeper) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
|
func (k *Keeper) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
|
||||||
store := prefix.NewStore(k.ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr))
|
store := prefix.NewStore(k.ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr))
|
||||||
|
|
||||||
@ -319,13 +340,14 @@ func (k *Keeper) GetCommittedState(addr common.Address, hash common.Hash) common
|
|||||||
return common.BytesToHash(value)
|
return common.BytesToHash(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetState calls CommitStateDB.GetState using the passed in context
|
// GetState returns the commited state for the given key hash, as all changes are commited directly
|
||||||
|
// to the KVStore.
|
||||||
func (k *Keeper) GetState(addr common.Address, hash common.Hash) common.Hash {
|
func (k *Keeper) GetState(addr common.Address, hash common.Hash) common.Hash {
|
||||||
// All state is committed directly
|
|
||||||
return k.GetCommittedState(addr, hash)
|
return k.GetCommittedState(addr, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetState calls CommitStateDB.SetState using the passed in context
|
// SetState sets the given hashes (key, value) to the KVStore. If the value hash is empty, this
|
||||||
|
// function deletes the key from the store.
|
||||||
func (k *Keeper) SetState(addr common.Address, key, value common.Hash) {
|
func (k *Keeper) SetState(addr common.Address, key, value common.Hash) {
|
||||||
store := prefix.NewStore(k.ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr))
|
store := prefix.NewStore(k.ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr))
|
||||||
key = types.KeyAddressStorage(addr, key)
|
key = types.KeyAddressStorage(addr, key)
|
||||||
@ -415,6 +437,8 @@ func (k *Keeper) Exist(addr common.Address) bool {
|
|||||||
// - nonce is 0
|
// - nonce is 0
|
||||||
// - balance amount for evm denom is 0
|
// - balance amount for evm denom is 0
|
||||||
// - account code hash is empty
|
// - account code hash is empty
|
||||||
|
//
|
||||||
|
// Non-ethereum accounts are considered not empty
|
||||||
func (k *Keeper) Empty(addr common.Address) bool {
|
func (k *Keeper) Empty(addr common.Address) bool {
|
||||||
nonce := uint64(0)
|
nonce := uint64(0)
|
||||||
codeHash := types.EmptyCodeHash
|
codeHash := types.EmptyCodeHash
|
||||||
@ -426,7 +450,6 @@ func (k *Keeper) Empty(addr common.Address) bool {
|
|||||||
nonce = account.GetSequence()
|
nonce = account.GetSequence()
|
||||||
ethAccount, isEthAccount := account.(*ethermint.EthAccount)
|
ethAccount, isEthAccount := account.(*ethermint.EthAccount)
|
||||||
if !isEthAccount {
|
if !isEthAccount {
|
||||||
// NOTE: non-ethereum accounts are considered not empty
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,20 +549,31 @@ func (k *Keeper) RevertToSnapshot(_ int) {}
|
|||||||
// context. This function also fills in the tx hash, block hash, tx index and log index fields before setting the log
|
// context. This function also fills in the tx hash, block hash, tx index and log index fields before setting the log
|
||||||
// to store.
|
// to store.
|
||||||
func (k *Keeper) AddLog(log *ethtypes.Log) {
|
func (k *Keeper) AddLog(log *ethtypes.Log) {
|
||||||
txHash := common.BytesToHash(tmtypes.Tx(k.ctx.TxBytes()).Hash())
|
if len(k.ctx.TxBytes()) > 0 {
|
||||||
|
tx := ðtypes.Transaction{}
|
||||||
|
if err := tx.UnmarshalBinary(k.ctx.TxBytes()); err != nil {
|
||||||
|
k.Logger(k.ctx).Error(
|
||||||
|
"ethereum tx unmarshaling failed",
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.TxHash = tx.Hash()
|
||||||
|
}
|
||||||
|
|
||||||
log.BlockHash = k.headerHash
|
log.BlockHash = k.headerHash
|
||||||
log.TxHash = txHash
|
|
||||||
log.TxIndex = uint(k.GetTxIndexTransient())
|
log.TxIndex = uint(k.GetTxIndexTransient())
|
||||||
|
|
||||||
logs := k.GetTxLogs(txHash)
|
logs := k.GetTxLogs(log.TxHash)
|
||||||
|
|
||||||
log.Index = uint(len(logs))
|
log.Index = uint(len(logs))
|
||||||
logs = append(logs, log)
|
logs = append(logs, log)
|
||||||
k.SetLogs(txHash, logs)
|
k.SetLogs(log.TxHash, logs)
|
||||||
|
|
||||||
k.Logger(k.ctx).Debug(
|
k.Logger(k.ctx).Debug(
|
||||||
"log added",
|
"log added",
|
||||||
"tx-hash", txHash.Hex(),
|
"tx-hash", log.TxHash.Hex(),
|
||||||
"log-index", int(log.Index),
|
"log-index", int(log.Index),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1 +1,601 @@
|
|||||||
package keeper_test
|
package keeper_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||||
|
|
||||||
|
"github.com/cosmos/ethermint/tests"
|
||||||
|
"github.com/cosmos/ethermint/x/evm/types"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestCreateAccount() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
addr common.Address
|
||||||
|
malleate func(common.Address)
|
||||||
|
callback func(common.Address)
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"reset account",
|
||||||
|
suite.address,
|
||||||
|
func(addr common.Address) {
|
||||||
|
suite.app.EvmKeeper.AddBalance(addr, big.NewInt(100))
|
||||||
|
suite.Require().NotZero(suite.app.EvmKeeper.GetBalance(addr).Int64())
|
||||||
|
},
|
||||||
|
func(addr common.Address) {
|
||||||
|
suite.Require().Zero(suite.app.EvmKeeper.GetBalance(addr).Int64())
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create account",
|
||||||
|
tests.GenerateAddress(),
|
||||||
|
func(addr common.Address) {
|
||||||
|
acc := suite.app.AccountKeeper.GetAccount(suite.ctx, addr.Bytes())
|
||||||
|
suite.Require().Nil(acc)
|
||||||
|
},
|
||||||
|
func(addr common.Address) {
|
||||||
|
acc := suite.app.AccountKeeper.GetAccount(suite.ctx, addr.Bytes())
|
||||||
|
suite.Require().NotNil(acc)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
tc.malleate(tc.addr)
|
||||||
|
suite.app.EvmKeeper.CreateAccount(tc.addr)
|
||||||
|
tc.callback(tc.addr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestAddBalance() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
amount *big.Int
|
||||||
|
isNoOp bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"positive amount",
|
||||||
|
big.NewInt(100),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"zero amount",
|
||||||
|
big.NewInt(0),
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"negative amount",
|
||||||
|
big.NewInt(-1),
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
prev := suite.app.EvmKeeper.GetBalance(suite.address)
|
||||||
|
suite.app.EvmKeeper.AddBalance(suite.address, tc.amount)
|
||||||
|
post := suite.app.EvmKeeper.GetBalance(suite.address)
|
||||||
|
|
||||||
|
if tc.isNoOp {
|
||||||
|
suite.Require().Equal(prev.Int64(), post.Int64())
|
||||||
|
} else {
|
||||||
|
suite.Require().Equal(new(big.Int).Add(prev, tc.amount).Int64(), post.Int64())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestSubBalance() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
amount *big.Int
|
||||||
|
malleate func()
|
||||||
|
isNoOp bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"positive amount, below zero",
|
||||||
|
big.NewInt(100),
|
||||||
|
func() {},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"positive amount, below zero",
|
||||||
|
big.NewInt(50),
|
||||||
|
func() {
|
||||||
|
suite.app.EvmKeeper.AddBalance(suite.address, big.NewInt(100))
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"zero amount",
|
||||||
|
big.NewInt(0),
|
||||||
|
func() {},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"negative amount",
|
||||||
|
big.NewInt(-1),
|
||||||
|
func() {},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
tc.malleate()
|
||||||
|
|
||||||
|
prev := suite.app.EvmKeeper.GetBalance(suite.address)
|
||||||
|
suite.app.EvmKeeper.SubBalance(suite.address, tc.amount)
|
||||||
|
post := suite.app.EvmKeeper.GetBalance(suite.address)
|
||||||
|
|
||||||
|
if tc.isNoOp {
|
||||||
|
suite.Require().Equal(prev.Int64(), post.Int64())
|
||||||
|
} else {
|
||||||
|
suite.Require().Equal(new(big.Int).Sub(prev, tc.amount).Int64(), post.Int64())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestGetNonce() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
address common.Address
|
||||||
|
expectedNonce uint64
|
||||||
|
malleate func()
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"account not found",
|
||||||
|
tests.GenerateAddress(),
|
||||||
|
0,
|
||||||
|
func() {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"existing account",
|
||||||
|
suite.address,
|
||||||
|
1,
|
||||||
|
func() {
|
||||||
|
suite.app.EvmKeeper.SetNonce(suite.address, 1)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
tc.malleate()
|
||||||
|
|
||||||
|
nonce := suite.app.EvmKeeper.GetNonce(tc.address)
|
||||||
|
suite.Require().Equal(tc.expectedNonce, nonce)
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestSetNonce() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
address common.Address
|
||||||
|
nonce uint64
|
||||||
|
malleate func()
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"new account",
|
||||||
|
tests.GenerateAddress(),
|
||||||
|
10,
|
||||||
|
func() {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"existing account",
|
||||||
|
suite.address,
|
||||||
|
99,
|
||||||
|
func() {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
suite.app.EvmKeeper.SetNonce(tc.address, tc.nonce)
|
||||||
|
nonce := suite.app.EvmKeeper.GetNonce(tc.address)
|
||||||
|
suite.Require().Equal(tc.nonce, nonce)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestGetCodeHash() {
|
||||||
|
addr := tests.GenerateAddress()
|
||||||
|
baseAcc := &authtypes.BaseAccount{Address: sdk.AccAddress(addr.Bytes()).String()}
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, baseAcc)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
address common.Address
|
||||||
|
expHash common.Hash
|
||||||
|
malleate func()
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"account not found",
|
||||||
|
tests.GenerateAddress(),
|
||||||
|
common.BytesToHash(types.EmptyCodeHash),
|
||||||
|
func() {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account not EthAccount type",
|
||||||
|
addr,
|
||||||
|
common.BytesToHash(types.EmptyCodeHash),
|
||||||
|
func() {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"existing account",
|
||||||
|
suite.address,
|
||||||
|
crypto.Keccak256Hash([]byte("codeHash")),
|
||||||
|
func() {
|
||||||
|
suite.app.EvmKeeper.SetCode(suite.address, []byte("codeHash"))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
|
||||||
|
tc.malleate()
|
||||||
|
|
||||||
|
hash := suite.app.EvmKeeper.GetCodeHash(tc.address)
|
||||||
|
suite.Require().Equal(tc.expHash, hash)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestSetCode() {
|
||||||
|
addr := tests.GenerateAddress()
|
||||||
|
baseAcc := &authtypes.BaseAccount{Address: sdk.AccAddress(addr.Bytes()).String()}
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, baseAcc)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
address common.Address
|
||||||
|
code []byte
|
||||||
|
isNoOp bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"account not found",
|
||||||
|
tests.GenerateAddress(),
|
||||||
|
[]byte("code"),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"account not EthAccount type",
|
||||||
|
addr,
|
||||||
|
nil,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"existing account",
|
||||||
|
suite.address,
|
||||||
|
[]byte("code"),
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"existing account, code deleted from store",
|
||||||
|
suite.address,
|
||||||
|
nil,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
|
||||||
|
prev := suite.app.EvmKeeper.GetCode(tc.address)
|
||||||
|
suite.app.EvmKeeper.SetCode(tc.address, tc.code)
|
||||||
|
post := suite.app.EvmKeeper.GetCode(tc.address)
|
||||||
|
|
||||||
|
if tc.isNoOp {
|
||||||
|
suite.Require().Equal(prev, post)
|
||||||
|
} else {
|
||||||
|
suite.Require().Equal(tc.code, post)
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.Require().Equal(len(post), suite.app.EvmKeeper.GetCodeSize(tc.address))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestRefund() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
malleate func()
|
||||||
|
expRefund uint64
|
||||||
|
expPanic bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"success - add and subtract refund",
|
||||||
|
func() {
|
||||||
|
suite.app.EvmKeeper.AddRefund(11)
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fail - subtract amount > current refund",
|
||||||
|
func() {
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
|
||||||
|
tc.malleate()
|
||||||
|
|
||||||
|
if tc.expPanic {
|
||||||
|
suite.Require().Panics(func() { suite.app.EvmKeeper.SubRefund(10) })
|
||||||
|
} else {
|
||||||
|
suite.app.EvmKeeper.SubRefund(10)
|
||||||
|
suite.Require().Equal(tc.expRefund, suite.app.EvmKeeper.GetRefund())
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear and reset refund from store
|
||||||
|
suite.app.EvmKeeper.ResetRefundTransient(suite.ctx)
|
||||||
|
suite.Require().Zero(suite.app.EvmKeeper.GetRefund())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestState() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
key, value common.Hash
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"set state - delete from store",
|
||||||
|
common.BytesToHash([]byte("key")),
|
||||||
|
common.Hash{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"set state - update value",
|
||||||
|
common.BytesToHash([]byte("key")),
|
||||||
|
common.BytesToHash([]byte("value")),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
|
||||||
|
suite.app.EvmKeeper.SetState(suite.address, tc.key, tc.value)
|
||||||
|
value := suite.app.EvmKeeper.GetState(suite.address, tc.key)
|
||||||
|
suite.Require().Equal(tc.value, value)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestSuicide() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
suicided bool
|
||||||
|
}{
|
||||||
|
{"success, first time suicided", true},
|
||||||
|
{"success, already suicided", true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
suite.Require().Equal(tc.suicided, suite.app.EvmKeeper.Suicide(suite.address))
|
||||||
|
suite.Require().Equal(tc.suicided, suite.app.EvmKeeper.HasSuicided(suite.address))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestExist() {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
address common.Address
|
||||||
|
malleate func()
|
||||||
|
exists bool
|
||||||
|
}{
|
||||||
|
{"success, account exists", suite.address, func() {}, true},
|
||||||
|
{"success, has suicided", suite.address, func() {
|
||||||
|
suite.app.EvmKeeper.Suicide(suite.address)
|
||||||
|
}, true},
|
||||||
|
{"success, account doesn't exist", tests.GenerateAddress(), func() {}, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
tc.malleate()
|
||||||
|
|
||||||
|
suite.Require().Equal(tc.exists, suite.app.EvmKeeper.Exist(tc.address))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestEmpty() {
|
||||||
|
addr := tests.GenerateAddress()
|
||||||
|
baseAcc := &authtypes.BaseAccount{Address: sdk.AccAddress(addr.Bytes()).String()}
|
||||||
|
suite.app.AccountKeeper.SetAccount(suite.ctx, baseAcc)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
address common.Address
|
||||||
|
malleate func()
|
||||||
|
empty bool
|
||||||
|
}{
|
||||||
|
{"empty, account exists", suite.address, func() {}, true},
|
||||||
|
{"not empty, non ethereum account", addr, func() {}, false},
|
||||||
|
{"not empty, positive balance", suite.address, func() {
|
||||||
|
suite.app.EvmKeeper.AddBalance(suite.address, big.NewInt(100))
|
||||||
|
}, false},
|
||||||
|
{"empty, account doesn't exist", tests.GenerateAddress(), func() {}, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
tc.malleate()
|
||||||
|
|
||||||
|
suite.Require().Equal(tc.empty, suite.app.EvmKeeper.Empty(tc.address))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestSnapshot() {
|
||||||
|
revision := suite.app.EvmKeeper.Snapshot()
|
||||||
|
suite.Require().Zero(revision)
|
||||||
|
suite.app.EvmKeeper.RevertToSnapshot(revision) // no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestAddLog() {
|
||||||
|
addr := tests.GenerateAddress()
|
||||||
|
msg := types.NewMsgEthereumTx(big.NewInt(1), 0, &suite.address, big.NewInt(1), 100000, big.NewInt(1), []byte("test"), nil)
|
||||||
|
tx := msg.AsTransaction()
|
||||||
|
txBz, err := tx.MarshalBinary()
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
txHash := tx.Hash()
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
log, expLog *ethtypes.Log // pre and post populating log fields
|
||||||
|
malleate func()
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"block hash not found",
|
||||||
|
ðtypes.Log{
|
||||||
|
Address: addr,
|
||||||
|
},
|
||||||
|
ðtypes.Log{
|
||||||
|
Address: addr,
|
||||||
|
},
|
||||||
|
func() {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tx hash from message",
|
||||||
|
ðtypes.Log{
|
||||||
|
Address: addr,
|
||||||
|
},
|
||||||
|
ðtypes.Log{
|
||||||
|
Address: addr,
|
||||||
|
TxHash: txHash,
|
||||||
|
},
|
||||||
|
func() {
|
||||||
|
suite.app.EvmKeeper.WithContext(suite.ctx.WithTxBytes(txBz))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
tc.malleate()
|
||||||
|
|
||||||
|
prev := suite.app.EvmKeeper.GetTxLogs(tc.expLog.TxHash)
|
||||||
|
suite.app.EvmKeeper.AddLog(tc.log)
|
||||||
|
post := suite.app.EvmKeeper.GetTxLogs(tc.expLog.TxHash)
|
||||||
|
|
||||||
|
suite.Require().NotZero(len(post), tc.expLog.TxHash.Hex())
|
||||||
|
suite.Require().Equal(len(prev)+1, len(post))
|
||||||
|
suite.Require().NotNil(post[len(post)-1])
|
||||||
|
suite.Require().Equal(tc.log, post[len(post)-1])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestAccessList() {
|
||||||
|
dest := tests.GenerateAddress()
|
||||||
|
precompiles := []common.Address{tests.GenerateAddress(), tests.GenerateAddress()}
|
||||||
|
accesses := ethtypes.AccessList{
|
||||||
|
{Address: tests.GenerateAddress(), StorageKeys: []common.Hash{common.BytesToHash([]byte("key"))}},
|
||||||
|
{Address: tests.GenerateAddress(), StorageKeys: []common.Hash{common.BytesToHash([]byte("key1"))}},
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.app.EvmKeeper.PrepareAccessList(suite.address, &dest, precompiles, accesses)
|
||||||
|
|
||||||
|
suite.Require().True(suite.app.EvmKeeper.AddressInAccessList(suite.address))
|
||||||
|
suite.Require().True(suite.app.EvmKeeper.AddressInAccessList(dest))
|
||||||
|
|
||||||
|
for _, precompile := range precompiles {
|
||||||
|
suite.Require().True(suite.app.EvmKeeper.AddressInAccessList(precompile))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, access := range accesses {
|
||||||
|
for _, key := range access.StorageKeys {
|
||||||
|
addrOK, slotOK := suite.app.EvmKeeper.SlotInAccessList(access.Address, key)
|
||||||
|
suite.Require().True(addrOK)
|
||||||
|
suite.Require().True(slotOK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *KeeperTestSuite) TestForEachStorage() {
|
||||||
|
var storage types.Storage
|
||||||
|
|
||||||
|
testCase := []struct {
|
||||||
|
name string
|
||||||
|
malleate func()
|
||||||
|
callback func(key, value common.Hash) (stop bool)
|
||||||
|
expValues []common.Hash
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"aggregate state",
|
||||||
|
func() {
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
suite.app.EvmKeeper.SetState(suite.address, common.BytesToHash([]byte(fmt.Sprintf("key%d", i))), common.BytesToHash([]byte(fmt.Sprintf("value%d", i))))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
func(key, value common.Hash) bool {
|
||||||
|
storage = append(storage, types.NewState(key, value))
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
[]common.Hash{
|
||||||
|
common.BytesToHash([]byte("value0")),
|
||||||
|
common.BytesToHash([]byte("value1")),
|
||||||
|
common.BytesToHash([]byte("value2")),
|
||||||
|
common.BytesToHash([]byte("value3")),
|
||||||
|
common.BytesToHash([]byte("value4")),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filter state",
|
||||||
|
func() {
|
||||||
|
suite.app.EvmKeeper.SetState(suite.address, common.BytesToHash([]byte("key")), common.BytesToHash([]byte("value")))
|
||||||
|
suite.app.EvmKeeper.SetState(suite.address, common.BytesToHash([]byte("filterkey")), common.BytesToHash([]byte("filtervalue")))
|
||||||
|
},
|
||||||
|
func(key, value common.Hash) bool {
|
||||||
|
if value == common.BytesToHash([]byte("filtervalue")) {
|
||||||
|
storage = append(storage, types.NewState(key, value))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
[]common.Hash{
|
||||||
|
common.BytesToHash([]byte("filtervalue")),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCase {
|
||||||
|
suite.Run(tc.name, func() {
|
||||||
|
suite.SetupTest() // reset
|
||||||
|
tc.malleate()
|
||||||
|
|
||||||
|
err := suite.app.EvmKeeper.ForEachStorage(suite.address, tc.callback)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Require().Equal(len(tc.expValues), len(storage), fmt.Sprintf("Expected values:\n%v\nStorage Values\n%v", tc.expValues, storage))
|
||||||
|
|
||||||
|
vals := make([]common.Hash, len(storage))
|
||||||
|
for i := range storage {
|
||||||
|
vals[i] = common.HexToHash(storage[i].Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: not sure why Equals fails
|
||||||
|
suite.Require().ElementsMatch(tc.expValues, vals)
|
||||||
|
})
|
||||||
|
storage = types.Storage{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
log "github.com/xlab/suplog"
|
|
||||||
|
|
||||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
||||||
@ -77,9 +75,9 @@ func (log *Log) Validate() error {
|
|||||||
|
|
||||||
// ToEthereum returns the Ethereum type Log from a Ethermint-proto compatible Log.
|
// ToEthereum returns the Ethereum type Log from a Ethermint-proto compatible Log.
|
||||||
func (log *Log) ToEthereum() *ethtypes.Log {
|
func (log *Log) ToEthereum() *ethtypes.Log {
|
||||||
topics := make([]ethcmn.Hash, len(log.Topics))
|
var topics []ethcmn.Hash // nolint: prealloc
|
||||||
for i := range log.Topics {
|
for i := range log.Topics {
|
||||||
topics[i] = ethcmn.HexToHash(log.Topics[i])
|
topics = append(topics, ethcmn.HexToHash(log.Topics[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
return ðtypes.Log{
|
return ðtypes.Log{
|
||||||
@ -97,24 +95,18 @@ func (log *Log) ToEthereum() *ethtypes.Log {
|
|||||||
|
|
||||||
// LogsToEthereum casts the Ethermint Logs to a slice of Ethereum Logs.
|
// LogsToEthereum casts the Ethermint Logs to a slice of Ethereum Logs.
|
||||||
func LogsToEthereum(logs []*Log) []*ethtypes.Log {
|
func LogsToEthereum(logs []*Log) []*ethtypes.Log {
|
||||||
ethLogs := make([]*ethtypes.Log, len(logs))
|
var ethLogs []*ethtypes.Log // nolint: prealloc
|
||||||
for i := range logs {
|
for i := range logs {
|
||||||
err := logs[i].Validate()
|
ethLogs = append(ethLogs, logs[i].ToEthereum())
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Errorln("failed log validation", logs[i].String())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ethLogs[i] = logs[i].ToEthereum()
|
|
||||||
}
|
}
|
||||||
return ethLogs
|
return ethLogs
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLogFromEth creates a new Log instance from a Ethereum type Log.
|
// NewLogFromEth creates a new Log instance from a Ethereum type Log.
|
||||||
func NewLogFromEth(log *ethtypes.Log) *Log {
|
func NewLogFromEth(log *ethtypes.Log) *Log {
|
||||||
topics := make([]string, len(log.Topics))
|
var topics []string // nolint: prealloc
|
||||||
for i := range log.Topics {
|
for _, topic := range log.Topics {
|
||||||
topics[i] = log.Topics[i].String()
|
topics = append(topics, topic.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Log{
|
return &Log{
|
||||||
|
@ -89,7 +89,7 @@ func newMsgEthereumTx(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fromEthereumTx populates the message fields from the given ethereum transaction
|
// fromEthereumTx populates the message fields from the given ethereum transaction
|
||||||
func (msg *MsgEthereumTx) fromEthereumTx(tx *ethtypes.Transaction) {
|
func (msg *MsgEthereumTx) FromEthereumTx(tx *ethtypes.Transaction) {
|
||||||
to := ""
|
to := ""
|
||||||
if tx.To() != nil {
|
if tx.To() != nil {
|
||||||
to = tx.To().Hex()
|
to = tx.To().Hex()
|
||||||
@ -227,7 +227,7 @@ func (msg *MsgEthereumTx) DecodeRLP(stream *rlp.Stream) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.fromEthereumTx(tx)
|
msg.FromEthereumTx(tx)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -258,7 +258,7 @@ func (msg *MsgEthereumTx) Sign(ethSigner ethtypes.Signer, keyringSigner keyring.
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.fromEthereumTx(tx)
|
msg.FromEthereumTx(tx)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user