x/evm: state_transition test (#389)

* draft state_transition

* working test

* keeper test

* Update x/evm/types/state_transition_test.go

* update state_transition_test.go

* failed Finalize test case

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Federico Kunze <federico.kunze94@gmail.com>
This commit is contained in:
Justin Thompson 2020-07-15 04:36:55 -06:00 committed by GitHub
parent 90f39390bc
commit 6bc80c5357
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 189 additions and 18 deletions

View File

@ -19,10 +19,10 @@ import (
)
const addrHex = "0x756F45E3FA69347A9A973A725E3C98bC4db0b4c1"
const hex = "0x0d87a3a5f73140f46aac1bf419263e4e94e87c292f25007700ab7f2060e2af68"
var (
address = ethcmn.HexToAddress(addrHex)
hash = ethcmn.FromHex("0x0d87a3a5f73140f46aac1bf419263e4e94e87c292f25007700ab7f2060e2af68")
hash = ethcmn.FromHex(hex)
)
type KeeperTestSuite struct {
@ -31,6 +31,7 @@ type KeeperTestSuite struct {
ctx sdk.Context
querier sdk.Querier
app *app.EthermintApp
address ethcmn.Address
}
func (suite *KeeperTestSuite) SetupTest() {
@ -39,6 +40,7 @@ func (suite *KeeperTestSuite) SetupTest() {
suite.app = app.Setup(checkTx)
suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "3", Time: time.Now().UTC()})
suite.querier = keeper.NewQuerier(suite.app.EvmKeeper)
suite.address = ethcmn.HexToAddress(addrHex)
}
func TestKeeperTestSuite(t *testing.T) {
@ -48,12 +50,12 @@ func TestKeeperTestSuite(t *testing.T) {
func (suite *KeeperTestSuite) TestTransactionLogs() {
ethHash := ethcmn.BytesToHash(hash)
log := &ethtypes.Log{
Address: address,
Address: suite.address,
Data: []byte("log"),
BlockNumber: 10,
}
log2 := &ethtypes.Log{
Address: address,
Address: suite.address,
Data: []byte("log2"),
BlockNumber: 11,
}
@ -75,7 +77,7 @@ func (suite *KeeperTestSuite) TestTransactionLogs() {
// add another log under the zero hash
log3 := &ethtypes.Log{
Address: address,
Address: suite.address,
Data: []byte("log3"),
BlockNumber: 10,
}
@ -93,11 +95,11 @@ func (suite *KeeperTestSuite) TestTransactionLogs() {
func (suite *KeeperTestSuite) TestDBStorage() {
// Perform state transitions
suite.app.EvmKeeper.CreateAccount(suite.ctx, address)
suite.app.EvmKeeper.SetBalance(suite.ctx, address, big.NewInt(5))
suite.app.EvmKeeper.SetNonce(suite.ctx, address, 4)
suite.app.EvmKeeper.SetState(suite.ctx, address, ethcmn.HexToHash("0x2"), ethcmn.HexToHash("0x3"))
suite.app.EvmKeeper.SetCode(suite.ctx, address, []byte{0x1})
suite.app.EvmKeeper.CreateAccount(suite.ctx, suite.address)
suite.app.EvmKeeper.SetBalance(suite.ctx, suite.address, big.NewInt(5))
suite.app.EvmKeeper.SetNonce(suite.ctx, suite.address, 4)
suite.app.EvmKeeper.SetState(suite.ctx, suite.address, ethcmn.HexToHash("0x2"), ethcmn.HexToHash("0x3"))
suite.app.EvmKeeper.SetCode(suite.ctx, suite.address, []byte{0x1})
// Test block hash mapping functionality
suite.app.EvmKeeper.SetBlockHash(suite.ctx, hash, 7)
@ -112,10 +114,10 @@ func (suite *KeeperTestSuite) TestDBStorage() {
suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 4, testBloom)
// Get those state transitions
suite.Require().Equal(suite.app.EvmKeeper.GetBalance(suite.ctx, address).Cmp(big.NewInt(5)), 0)
suite.Require().Equal(suite.app.EvmKeeper.GetNonce(suite.ctx, address), uint64(4))
suite.Require().Equal(suite.app.EvmKeeper.GetState(suite.ctx, address, ethcmn.HexToHash("0x2")), ethcmn.HexToHash("0x3"))
suite.Require().Equal(suite.app.EvmKeeper.GetCode(suite.ctx, address), []byte{0x1})
suite.Require().Equal(suite.app.EvmKeeper.GetBalance(suite.ctx, suite.address).Cmp(big.NewInt(5)), 0)
suite.Require().Equal(suite.app.EvmKeeper.GetNonce(suite.ctx, suite.address), uint64(4))
suite.Require().Equal(suite.app.EvmKeeper.GetState(suite.ctx, suite.address, ethcmn.HexToHash("0x2")), ethcmn.HexToHash("0x3"))
suite.Require().Equal(suite.app.EvmKeeper.GetCode(suite.ctx, suite.address), []byte{0x1})
height, found = suite.app.EvmKeeper.GetBlockHash(suite.ctx, hash)
suite.Require().True(found)

View File

@ -4,6 +4,7 @@ import (
"math/big"
"github.com/cosmos/ethermint/x/evm/types"
ethtypes "github.com/ethereum/go-ethereum/core/types"
abci "github.com/tendermint/tendermint/abci/types"
)
@ -18,15 +19,20 @@ func (suite *KeeperTestSuite) TestQuerier() {
}{
{"protocol version", []string{types.QueryProtocolVersion}, func() {}, true},
{"balance", []string{types.QueryBalance, addrHex}, func() {
suite.app.EvmKeeper.SetBalance(suite.ctx, address, big.NewInt(5))
suite.app.EvmKeeper.SetBalance(suite.ctx, suite.address, big.NewInt(5))
}, true},
// {"balance", []string{types.QueryBalance, "0x01232"}, func() {}, false},
// {"balance fail", []string{types.QueryBalance, "0x01232"}, func() {}, false},
{"block number", []string{types.QueryBlockNumber, "0x0"}, func() {}, true},
{"storage", []string{types.QueryStorage, "0x0", "0x0"}, func() {}, true},
{"code", []string{types.QueryCode, "0x0"}, func() {}, true},
// {"hash to height", []string{types.QueryHashToHeight, "0x0"}, func() {}, true},
{"hash to height", []string{types.QueryHashToHeight, hex}, func() {
suite.app.EvmKeeper.SetBlockHash(suite.ctx, hash, 8)
}, true},
{"tx logs", []string{types.QueryTransactionLogs, "0x0"}, func() {}, true},
// {"logs bloom", []string{types.QueryLogsBloom, "0x0"}, func() {}, true},
{"bloom", []string{types.QueryBloom, "4"}, func() {
testBloom := ethtypes.BytesToBloom([]byte{0x1, 0x3})
suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 4, testBloom)
}, true},
{"logs", []string{types.QueryLogs, "0x0"}, func() {}, true},
{"account", []string{types.QueryAccount, "0x0"}, func() {}, true},
{"exportAccount", []string{types.QueryExportAccount, "0x0"}, func() {}, true},

View File

@ -0,0 +1,163 @@
package types_test
import (
"math/big"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/ethermint/crypto"
ethermint "github.com/cosmos/ethermint/types"
"github.com/cosmos/ethermint/x/evm/types"
ethcmn "github.com/ethereum/go-ethereum/common"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
)
func (suite *StateDBTestSuite) TestTransitionDb() {
suite.stateDB.SetNonce(suite.address, 123)
addr := sdk.AccAddress(suite.address.Bytes())
balance := sdk.NewCoin(ethermint.DenomDefault, sdk.NewInt(5000))
suite.app.BankKeeper.SetBalance(suite.ctx, addr, balance)
priv, err := crypto.GenerateKey()
suite.Require().NoError(err)
recipient := ethcrypto.PubkeyToAddress(priv.ToECDSA().PublicKey)
testCase := []struct {
name string
malleate func()
state types.StateTransition
expPass bool
}{
{
"passing state transition",
func() {},
types.StateTransition{
AccountNonce: 123,
Price: big.NewInt(10),
GasLimit: 11,
Recipient: &recipient,
Amount: big.NewInt(50),
Payload: []byte("data"),
ChainID: big.NewInt(1),
Csdb: suite.stateDB,
TxHash: &ethcmn.Hash{},
Sender: suite.address,
Simulate: suite.ctx.IsCheckTx(),
},
true,
},
{
"contract creation",
func() {},
types.StateTransition{
AccountNonce: 123,
Price: big.NewInt(10),
GasLimit: 11,
Recipient: nil,
Amount: big.NewInt(10),
Payload: []byte("data"),
ChainID: big.NewInt(1),
Csdb: suite.stateDB,
TxHash: &ethcmn.Hash{},
Sender: suite.address,
Simulate: true,
},
true,
},
{
"state transition simulation",
func() {},
types.StateTransition{
AccountNonce: 123,
Price: big.NewInt(10),
GasLimit: 11,
Recipient: &recipient,
Amount: big.NewInt(10),
Payload: []byte("data"),
ChainID: big.NewInt(1),
Csdb: suite.stateDB,
TxHash: &ethcmn.Hash{},
Sender: suite.address,
Simulate: true,
},
true,
},
{
"fail by sending more than balance",
func() {},
types.StateTransition{
AccountNonce: 123,
Price: big.NewInt(10),
GasLimit: 11,
Recipient: &recipient,
Amount: big.NewInt(4951),
Payload: []byte("data"),
ChainID: big.NewInt(1),
Csdb: suite.stateDB,
TxHash: &ethcmn.Hash{},
Sender: suite.address,
Simulate: suite.ctx.IsCheckTx(),
},
false,
},
{
"failed to Finalize",
func() {},
types.StateTransition{
AccountNonce: 123,
Price: big.NewInt(10),
GasLimit: 11,
Recipient: &recipient,
Amount: big.NewInt(-5000),
Payload: []byte("data"),
ChainID: big.NewInt(1),
Csdb: suite.stateDB,
TxHash: &ethcmn.Hash{},
Sender: suite.address,
Simulate: false,
},
false,
},
{
"nil gas price",
func() {
invalidGas := sdk.DecCoins{
{Denom: ethermint.DenomDefault},
}
suite.ctx = suite.ctx.WithMinGasPrices(invalidGas)
},
types.StateTransition{
AccountNonce: 123,
Price: big.NewInt(10),
GasLimit: 11,
Recipient: &recipient,
Amount: big.NewInt(10),
Payload: []byte("data"),
ChainID: big.NewInt(1),
Csdb: suite.stateDB,
TxHash: &ethcmn.Hash{},
Sender: suite.address,
Simulate: suite.ctx.IsCheckTx(),
},
false,
},
}
for _, tc := range testCase {
tc.malleate()
_, err = tc.state.TransitionDb(suite.ctx)
if tc.expPass {
suite.Require().NoError(err, tc.name)
fromBalance := suite.app.EvmKeeper.GetBalance(suite.ctx, suite.address)
toBalance := suite.app.EvmKeeper.GetBalance(suite.ctx, recipient)
suite.Require().Equal(fromBalance, big.NewInt(4950), tc.name)
suite.Require().Equal(toBalance, big.NewInt(50), tc.name)
} else {
suite.Require().Error(err, tc.name)
}
}
}