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:
parent
90f39390bc
commit
6bc80c5357
@ -19,10 +19,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const addrHex = "0x756F45E3FA69347A9A973A725E3C98bC4db0b4c1"
|
const addrHex = "0x756F45E3FA69347A9A973A725E3C98bC4db0b4c1"
|
||||||
|
const hex = "0x0d87a3a5f73140f46aac1bf419263e4e94e87c292f25007700ab7f2060e2af68"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
address = ethcmn.HexToAddress(addrHex)
|
hash = ethcmn.FromHex(hex)
|
||||||
hash = ethcmn.FromHex("0x0d87a3a5f73140f46aac1bf419263e4e94e87c292f25007700ab7f2060e2af68")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type KeeperTestSuite struct {
|
type KeeperTestSuite struct {
|
||||||
@ -31,6 +31,7 @@ type KeeperTestSuite struct {
|
|||||||
ctx sdk.Context
|
ctx sdk.Context
|
||||||
querier sdk.Querier
|
querier sdk.Querier
|
||||||
app *app.EthermintApp
|
app *app.EthermintApp
|
||||||
|
address ethcmn.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KeeperTestSuite) SetupTest() {
|
func (suite *KeeperTestSuite) SetupTest() {
|
||||||
@ -39,6 +40,7 @@ func (suite *KeeperTestSuite) SetupTest() {
|
|||||||
suite.app = app.Setup(checkTx)
|
suite.app = app.Setup(checkTx)
|
||||||
suite.ctx = suite.app.BaseApp.NewContext(checkTx, abci.Header{Height: 1, ChainID: "3", Time: time.Now().UTC()})
|
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.querier = keeper.NewQuerier(suite.app.EvmKeeper)
|
||||||
|
suite.address = ethcmn.HexToAddress(addrHex)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeeperTestSuite(t *testing.T) {
|
func TestKeeperTestSuite(t *testing.T) {
|
||||||
@ -48,12 +50,12 @@ func TestKeeperTestSuite(t *testing.T) {
|
|||||||
func (suite *KeeperTestSuite) TestTransactionLogs() {
|
func (suite *KeeperTestSuite) TestTransactionLogs() {
|
||||||
ethHash := ethcmn.BytesToHash(hash)
|
ethHash := ethcmn.BytesToHash(hash)
|
||||||
log := ðtypes.Log{
|
log := ðtypes.Log{
|
||||||
Address: address,
|
Address: suite.address,
|
||||||
Data: []byte("log"),
|
Data: []byte("log"),
|
||||||
BlockNumber: 10,
|
BlockNumber: 10,
|
||||||
}
|
}
|
||||||
log2 := ðtypes.Log{
|
log2 := ðtypes.Log{
|
||||||
Address: address,
|
Address: suite.address,
|
||||||
Data: []byte("log2"),
|
Data: []byte("log2"),
|
||||||
BlockNumber: 11,
|
BlockNumber: 11,
|
||||||
}
|
}
|
||||||
@ -75,7 +77,7 @@ func (suite *KeeperTestSuite) TestTransactionLogs() {
|
|||||||
|
|
||||||
// add another log under the zero hash
|
// add another log under the zero hash
|
||||||
log3 := ðtypes.Log{
|
log3 := ðtypes.Log{
|
||||||
Address: address,
|
Address: suite.address,
|
||||||
Data: []byte("log3"),
|
Data: []byte("log3"),
|
||||||
BlockNumber: 10,
|
BlockNumber: 10,
|
||||||
}
|
}
|
||||||
@ -93,11 +95,11 @@ func (suite *KeeperTestSuite) TestTransactionLogs() {
|
|||||||
|
|
||||||
func (suite *KeeperTestSuite) TestDBStorage() {
|
func (suite *KeeperTestSuite) TestDBStorage() {
|
||||||
// Perform state transitions
|
// Perform state transitions
|
||||||
suite.app.EvmKeeper.CreateAccount(suite.ctx, address)
|
suite.app.EvmKeeper.CreateAccount(suite.ctx, suite.address)
|
||||||
suite.app.EvmKeeper.SetBalance(suite.ctx, address, big.NewInt(5))
|
suite.app.EvmKeeper.SetBalance(suite.ctx, suite.address, big.NewInt(5))
|
||||||
suite.app.EvmKeeper.SetNonce(suite.ctx, address, 4)
|
suite.app.EvmKeeper.SetNonce(suite.ctx, suite.address, 4)
|
||||||
suite.app.EvmKeeper.SetState(suite.ctx, address, ethcmn.HexToHash("0x2"), ethcmn.HexToHash("0x3"))
|
suite.app.EvmKeeper.SetState(suite.ctx, suite.address, ethcmn.HexToHash("0x2"), ethcmn.HexToHash("0x3"))
|
||||||
suite.app.EvmKeeper.SetCode(suite.ctx, address, []byte{0x1})
|
suite.app.EvmKeeper.SetCode(suite.ctx, suite.address, []byte{0x1})
|
||||||
|
|
||||||
// Test block hash mapping functionality
|
// Test block hash mapping functionality
|
||||||
suite.app.EvmKeeper.SetBlockHash(suite.ctx, hash, 7)
|
suite.app.EvmKeeper.SetBlockHash(suite.ctx, hash, 7)
|
||||||
@ -112,10 +114,10 @@ func (suite *KeeperTestSuite) TestDBStorage() {
|
|||||||
suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 4, testBloom)
|
suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 4, testBloom)
|
||||||
|
|
||||||
// Get those state transitions
|
// 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.GetBalance(suite.ctx, suite.address).Cmp(big.NewInt(5)), 0)
|
||||||
suite.Require().Equal(suite.app.EvmKeeper.GetNonce(suite.ctx, address), uint64(4))
|
suite.Require().Equal(suite.app.EvmKeeper.GetNonce(suite.ctx, suite.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.GetState(suite.ctx, suite.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.GetCode(suite.ctx, suite.address), []byte{0x1})
|
||||||
|
|
||||||
height, found = suite.app.EvmKeeper.GetBlockHash(suite.ctx, hash)
|
height, found = suite.app.EvmKeeper.GetBlockHash(suite.ctx, hash)
|
||||||
suite.Require().True(found)
|
suite.Require().True(found)
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/cosmos/ethermint/x/evm/types"
|
"github.com/cosmos/ethermint/x/evm/types"
|
||||||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
|
|
||||||
abci "github.com/tendermint/tendermint/abci/types"
|
abci "github.com/tendermint/tendermint/abci/types"
|
||||||
)
|
)
|
||||||
@ -18,15 +19,20 @@ func (suite *KeeperTestSuite) TestQuerier() {
|
|||||||
}{
|
}{
|
||||||
{"protocol version", []string{types.QueryProtocolVersion}, func() {}, true},
|
{"protocol version", []string{types.QueryProtocolVersion}, func() {}, true},
|
||||||
{"balance", []string{types.QueryBalance, addrHex}, func() {
|
{"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},
|
}, true},
|
||||||
// {"balance", []string{types.QueryBalance, "0x01232"}, func() {}, false},
|
// {"balance fail", []string{types.QueryBalance, "0x01232"}, func() {}, false},
|
||||||
{"block number", []string{types.QueryBlockNumber, "0x0"}, func() {}, true},
|
{"block number", []string{types.QueryBlockNumber, "0x0"}, func() {}, true},
|
||||||
{"storage", []string{types.QueryStorage, "0x0", "0x0"}, func() {}, true},
|
{"storage", []string{types.QueryStorage, "0x0", "0x0"}, func() {}, true},
|
||||||
{"code", []string{types.QueryCode, "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},
|
{"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},
|
{"logs", []string{types.QueryLogs, "0x0"}, func() {}, true},
|
||||||
{"account", []string{types.QueryAccount, "0x0"}, func() {}, true},
|
{"account", []string{types.QueryAccount, "0x0"}, func() {}, true},
|
||||||
{"exportAccount", []string{types.QueryExportAccount, "0x0"}, func() {}, true},
|
{"exportAccount", []string{types.QueryExportAccount, "0x0"}, func() {}, true},
|
||||||
|
163
x/evm/types/state_transition_test.go
Normal file
163
x/evm/types/state_transition_test.go
Normal 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: ðcmn.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: ðcmn.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: ðcmn.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: ðcmn.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: ðcmn.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: ðcmn.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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user