Update ante handler unit tests

This commit is contained in:
Aleksandr Bezobchuk 2018-08-31 16:44:34 -04:00
parent e2c0645a10
commit e83a2b97f9
5 changed files with 177 additions and 206 deletions

View File

@ -21,14 +21,14 @@ const (
// must implementing. Internal ante handlers will be dependant upon the // must implementing. Internal ante handlers will be dependant upon the
// transaction type. // transaction type.
type internalAnteHandler func( type internalAnteHandler func(
sdkCtx sdk.Context, tx sdk.Tx, am auth.AccountMapper, sdkCtx sdk.Context, tx sdk.Tx, accMapper auth.AccountMapper,
) (newCtx sdk.Context, res sdk.Result, abort bool) ) (newCtx sdk.Context, res sdk.Result, abort bool)
// AnteHandler is responsible for attempting to route an Ethereum or SDK // AnteHandler is responsible for attempting to route an Ethereum or SDK
// transaction to an internal ante handler for performing transaction-level // transaction to an internal ante handler for performing transaction-level
// processing (e.g. fee payment, signature verification) before being passed // processing (e.g. fee payment, signature verification) before being passed
// onto it's respective handler. // onto it's respective handler.
func AnteHandler(am auth.AccountMapper, _ auth.FeeCollectionKeeper) sdk.AnteHandler { func AnteHandler(accMapper auth.AccountMapper, _ auth.FeeCollectionKeeper) sdk.AnteHandler {
return func(sdkCtx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) { return func(sdkCtx sdk.Context, tx sdk.Tx) (newCtx sdk.Context, res sdk.Result, abort bool) {
var ( var (
handler internalAnteHandler handler internalAnteHandler
@ -67,7 +67,7 @@ func AnteHandler(am auth.AccountMapper, _ auth.FeeCollectionKeeper) sdk.AnteHand
} }
}() }()
return handler(newCtx, tx, am) return handler(newCtx, tx, accMapper)
} }
} }
@ -76,7 +76,7 @@ func AnteHandler(am auth.AccountMapper, _ auth.FeeCollectionKeeper) sdk.AnteHand
// //
// TODO: Do we need to do any further validation or account manipulation // TODO: Do we need to do any further validation or account manipulation
// (e.g. increment nonce)? // (e.g. increment nonce)?
func handleEthTx(sdkCtx sdk.Context, tx sdk.Tx, am auth.AccountMapper) (sdk.Context, sdk.Result, bool) { func handleEthTx(sdkCtx sdk.Context, tx sdk.Tx, accMapper auth.AccountMapper) (sdk.Context, sdk.Result, bool) {
ethTx, ok := tx.(types.Transaction) ethTx, ok := tx.(types.Transaction)
if !ok { if !ok {
return sdkCtx, sdk.ErrInternal(fmt.Sprintf("invalid transaction: %T", tx)).Result(), true return sdkCtx, sdk.ErrInternal(fmt.Sprintf("invalid transaction: %T", tx)).Result(), true
@ -96,7 +96,7 @@ func handleEthTx(sdkCtx sdk.Context, tx sdk.Tx, am auth.AccountMapper) (sdk.Cont
return sdkCtx, sdk.ErrUnauthorized("signature verification failed").Result(), true return sdkCtx, sdk.ErrUnauthorized("signature verification failed").Result(), true
} }
acc := am.GetAccount(sdkCtx, addr.Bytes()) acc := accMapper.GetAccount(sdkCtx, addr.Bytes())
// validate the account nonce (referred to as sequence in the AccountMapper) // validate the account nonce (referred to as sequence in the AccountMapper)
seq := acc.GetSequence() seq := acc.GetSequence()
@ -109,13 +109,13 @@ func handleEthTx(sdkCtx sdk.Context, tx sdk.Tx, am auth.AccountMapper) (sdk.Cont
return sdkCtx, sdk.ErrInternal(err.Error()).Result(), true return sdkCtx, sdk.ErrInternal(err.Error()).Result(), true
} }
am.SetAccount(sdkCtx, acc) accMapper.SetAccount(sdkCtx, acc)
return sdkCtx, sdk.Result{GasWanted: int64(ethTx.Data().GasLimit)}, false return sdkCtx, sdk.Result{GasWanted: int64(ethTx.Data().GasLimit)}, false
} }
// handleEmbeddedTx implements an ante handler for an SDK transaction. It // handleEmbeddedTx implements an ante handler for an SDK transaction. It
// validates the signature and if valid returns an OK result. // validates the signature and if valid returns an OK result.
func handleEmbeddedTx(sdkCtx sdk.Context, tx sdk.Tx, am auth.AccountMapper) (sdk.Context, sdk.Result, bool) { func handleEmbeddedTx(sdkCtx sdk.Context, tx sdk.Tx, accMapper auth.AccountMapper) (sdk.Context, sdk.Result, bool) {
stdTx, ok := tx.(auth.StdTx) stdTx, ok := tx.(auth.StdTx)
if !ok { if !ok {
return sdkCtx, sdk.ErrInternal(fmt.Sprintf("invalid transaction: %T", tx)).Result(), true return sdkCtx, sdk.ErrInternal(fmt.Sprintf("invalid transaction: %T", tx)).Result(), true
@ -132,7 +132,7 @@ func handleEmbeddedTx(sdkCtx sdk.Context, tx sdk.Tx, am auth.AccountMapper) (sdk
for i, sig := range stdTx.Signatures { for i, sig := range stdTx.Signatures {
signer := ethcmn.BytesToAddress(signerAddrs[i].Bytes()) signer := ethcmn.BytesToAddress(signerAddrs[i].Bytes())
acc, err := validateSignature(sdkCtx, stdTx, signer, sig, am) acc, err := validateSignature(sdkCtx, stdTx, signer, sig, accMapper)
// err.Code() != sdk.CodeOK // err.Code() != sdk.CodeOK
if err != nil { if err != nil {
return sdkCtx, err.Result(), true return sdkCtx, err.Result(), true
@ -140,7 +140,7 @@ func handleEmbeddedTx(sdkCtx sdk.Context, tx sdk.Tx, am auth.AccountMapper) (sdk
// TODO: Fees! // TODO: Fees!
am.SetAccount(sdkCtx, acc) accMapper.SetAccount(sdkCtx, acc)
signerAccs[i] = acc signerAccs[i] = acc
} }
@ -167,12 +167,12 @@ func validateStdTxBasic(stdTx auth.StdTx) (err sdk.Error) {
func validateSignature( func validateSignature(
sdkCtx sdk.Context, stdTx auth.StdTx, signer ethcmn.Address, sdkCtx sdk.Context, stdTx auth.StdTx, signer ethcmn.Address,
sig auth.StdSignature, am auth.AccountMapper, sig auth.StdSignature, accMapper auth.AccountMapper,
) (acc auth.Account, sdkErr sdk.Error) { ) (acc auth.Account, sdkErr sdk.Error) {
chainID := sdkCtx.ChainID() chainID := sdkCtx.ChainID()
acc = am.GetAccount(sdkCtx, signer.Bytes()) acc = accMapper.GetAccount(sdkCtx, signer.Bytes())
if acc == nil { if acc == nil {
return nil, sdk.ErrUnknownAddress(fmt.Sprintf("no account with address %s found", signer)) return nil, sdk.ErrUnknownAddress(fmt.Sprintf("no account with address %s found", signer))
} }

View File

@ -1,266 +1,256 @@
package handlers package handlers
import ( import (
"fmt"
"testing"
"math/big"
"crypto/ecdsa" "crypto/ecdsa"
"fmt"
"math/big"
"testing"
"github.com/cosmos/ethermint/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth"
stake "github.com/cosmos/cosmos-sdk/x/stake/types" "github.com/cosmos/cosmos-sdk/x/stake"
"github.com/cosmos/ethermint/types"
ethcrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types" abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/log"
ethcmn "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
// Test EthTx Antehandler func TestEthTxBadSig(t *testing.T) {
// ----------------------------------------------------------------------------------------------------------------------------------- tx := types.NewTransaction(uint64(0), types.TestAddr1, big.NewInt(10), 1000, big.NewInt(100), []byte{})
func TestBadSig(t *testing.T) { // create bad signature
tx := types.NewTestEthTxs(types.TestChainID, []*ecdsa.PrivateKey{types.TestPrivKey1}, []ethcmn.Address{types.TestAddr1})[0] tx.Sign(big.NewInt(100), types.TestPrivKey2)
tx.Data.Signature = types.NewEthSignature(new(big.Int), new(big.Int), new(big.Int)) ms, key := createTestMultiStore()
ms, key := SetupMultiStore()
ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil)
accMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount)
accountMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount) handler := AnteHandler(accMapper, auth.FeeCollectionKeeper{})
handler := AnteHandler(accountMapper) _, res, abort := handler(ctx, *tx)
_, res, abort := handler(ctx, tx)
assert.True(t, abort, "Antehandler did not abort")
require.Equal(t, sdk.ABCICodeType(0x10004), res.Code, fmt.Sprintf("Result has wrong code on bad tx: %s", res.Log))
require.True(t, abort, "expected ante handler to abort")
require.Equal(t, sdk.ABCICodeType(0x10004), res.Code, fmt.Sprintf("invalid code returned on bad tx: %s", res.Log))
} }
func TestInsufficientGas(t *testing.T) { func TestEthTxInsufficientGas(t *testing.T) {
tx := types.NewTestEthTxs(types.TestChainID, []*ecdsa.PrivateKey{types.TestPrivKey1}, []ethcmn.Address{types.TestAddr1})[0] tx := types.NewTransaction(uint64(0), types.TestAddr1, big.NewInt(0), 0, big.NewInt(0), []byte{})
tx.Data.GasLimit = 0
ms, key := SetupMultiStore()
ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil)
accountMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount)
handler := AnteHandler(accountMapper)
_, res, abort := handler(ctx, tx)
assert.True(t, abort, "Antehandler did not abort")
require.Equal(t, sdk.ABCICodeType(0x1000c), res.Code, fmt.Sprintf("Result has wrong code on bad tx: %s", res.Log))
}
func TestIncorrectNonce(t *testing.T) {
// Create transaction with wrong nonce 12
tx := types.NewTransaction(12, types.TestAddr2, sdk.NewInt(50), 1000, sdk.NewInt(1000), []byte("test_bytes"))
tx.Sign(types.TestChainID, types.TestPrivKey1) tx.Sign(types.TestChainID, types.TestPrivKey1)
ms, key := SetupMultiStore() ms, key := createTestMultiStore()
ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil)
accMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount)
handler := AnteHandler(accMapper, auth.FeeCollectionKeeper{})
_, res, abort := handler(ctx, *tx)
require.True(t, abort, "expected ante handler to abort")
require.Equal(t, sdk.ABCICodeType(0x1000c), res.Code, fmt.Sprintf("invalid code returned on bad tx: %s", res.Log))
}
func TestEthTxIncorrectNonce(t *testing.T) {
// create transaction with wrong nonce 12
tx := types.NewTransaction(12, types.TestAddr2, big.NewInt(50), 1000, big.NewInt(1000), []byte("test_bytes"))
tx.Sign(types.TestChainID, types.TestPrivKey1)
ms, key := createTestMultiStore()
ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, log.NewNopLogger()) ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, log.NewNopLogger())
accMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount)
accountMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount) // set account in accountMapper
acc := accMapper.NewAccountWithAddress(ctx, types.TestAddr1.Bytes())
accMapper.SetAccount(ctx, acc)
// Set account in accountMapper handler := AnteHandler(accMapper, auth.FeeCollectionKeeper{})
acc := accountMapper.NewAccountWithAddress(ctx, types.TestAddr1[:]) _, res, abort := handler(ctx, *tx)
accountMapper.SetAccount(ctx, acc)
handler := AnteHandler(accountMapper)
_, res, abort := handler(ctx, tx)
assert.True(t, abort, "Antehandler did not abort")
require.Equal(t, sdk.ABCICodeType(0x10003), res.Code, fmt.Sprintf("Result has wrong code on bad tx: %s", res.Log))
require.True(t, abort, "expected ante handler to abort")
require.Equal(t, sdk.ABCICodeType(0x10003), res.Code, fmt.Sprintf("invalid code returned on bad tx: %s", res.Log))
} }
func TestValidTx(t *testing.T) { func TestEthTxValidTx(t *testing.T) {
tx := types.NewTestEthTxs(types.TestChainID, []*ecdsa.PrivateKey{types.TestPrivKey1}, []ethcmn.Address{types.TestAddr1})[0] tx := types.NewTransaction(0, types.TestAddr1, big.NewInt(50), 1000, big.NewInt(1000), []byte{})
tx.Sign(types.TestChainID, types.TestPrivKey1)
ms, key := SetupMultiStore() ms, key := createTestMultiStore()
ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil)
accMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount)
accountMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount) // set account in accountMapper
acc := accMapper.NewAccountWithAddress(ctx, types.TestAddr1.Bytes())
accMapper.SetAccount(ctx, acc)
// Set account in accountMapper handler := AnteHandler(accMapper, auth.FeeCollectionKeeper{})
acc := accountMapper.NewAccountWithAddress(ctx, types.TestAddr1[:]) _, res, abort := handler(ctx, *tx)
accountMapper.SetAccount(ctx, acc)
handler := AnteHandler(accountMapper) require.False(t, abort, "expected ante handler to not abort")
require.True(t, res.IsOK(), fmt.Sprintf("result not OK on valid Tx: %s", res.Log))
_, res, abort := handler(ctx, tx) // ensure account state updated correctly
seq, _ := accMapper.GetSequence(ctx, types.TestAddr1[:])
assert.False(t, abort, "Antehandler abort on valid tx") require.Equal(t, int64(1), seq, "account nonce did not increment correctly")
require.True(t, res.IsOK(), fmt.Sprintf("Result not OK on valid Tx: %s", res.Log))
// Ensure account state updated correctly
seq, _ := accountMapper.GetSequence(ctx, types.TestAddr1[:])
require.Equal(t, int64(1), seq, "AccountNonce did not increment correctly")
} }
// Test EmbeddedTx Antehandler func TestEmbeddedTxBadSig(t *testing.T) {
// ----------------------------------------------------------------------------------------------------------------------------------- testCodec := types.NewTestCodec()
testFee := types.NewTestStdFee()
func TestInvalidSigEmbeddedTx(t *testing.T) { msgs := []sdk.Msg{sdk.NewTestMsg()}
// Create msg to be embedded tx := types.NewTestStdTx(
msgs := []sdk.Msg{stake.NewMsgDelegate(types.TestAddr1[:], types.TestAddr2[:], sdk.Coin{"steak", sdk.NewInt(50)})} types.TestChainID, msgs, []int64{0}, []int64{0}, []*ecdsa.PrivateKey{types.TestPrivKey1}, testFee,
)
// Create transaction with incorrect signer // create bad signature
tx := types.NewTestEmbeddedTx(types.TestChainID, msgs, []*ecdsa.PrivateKey{types.TestPrivKey2}, signBytes := types.GetStdTxSignBytes(big.NewInt(100).String(), 1, 1, testFee, msgs, "")
[]int64{0}, []int64{0}, types.NewStdFee()) sig, _ := ethcrypto.Sign(signBytes, types.TestPrivKey1)
(tx.(auth.StdTx)).Signatures[0].Signature = sig
ms, key := SetupMultiStore() ms, key := createTestMultiStore()
ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil)
accMapper := auth.NewAccountMapper(testCodec, key, auth.ProtoBaseAccount)
accountMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount) // set account in accountMapper
acc := accMapper.NewAccountWithAddress(ctx, types.TestAddr1.Bytes())
// Set account in accountMapper accMapper.SetAccount(ctx, acc)
acc := accountMapper.NewAccountWithAddress(ctx, types.TestAddr1[:])
accountMapper.SetAccount(ctx, acc)
handler := AnteHandler(accountMapper)
handler := AnteHandler(accMapper, auth.FeeCollectionKeeper{})
_, res, abort := handler(ctx, tx) _, res, abort := handler(ctx, tx)
assert.True(t, abort, "Antehandler did not abort on invalid embedded tx") require.True(t, abort, "expected ante handler to abort")
require.Equal(t, sdk.ABCICodeType(0x10004), res.Code, "Result is OK on bad tx") require.Equal(t, sdk.ABCICodeType(0x10004), res.Code, fmt.Sprintf("invalid code returned on bad tx: %s", res.Log))
} }
func TestInvalidMultiMsgEmbeddedTx(t *testing.T) { func TestEmbeddedTxInvalidMultiMsg(t *testing.T) {
// Create msg to be embedded testCodec := types.NewTestCodec()
testCodec.RegisterConcrete(stake.MsgDelegate{}, "test/MsgDelegate", nil)
msgs := []sdk.Msg{ msgs := []sdk.Msg{
stake.NewMsgDelegate(types.TestAddr1[:], types.TestAddr2[:], sdk.Coin{"steak", sdk.NewInt(50)}), stake.NewMsgDelegate(types.TestAddr1.Bytes(), types.TestAddr2.Bytes(), sdk.NewCoin("steak", sdk.NewInt(50))),
stake.NewMsgDelegate(types.TestAddr2[:], types.TestAddr2[:], sdk.Coin{"steak", sdk.NewInt(50)}), stake.NewMsgDelegate(types.TestAddr2.Bytes(), types.TestAddr2.Bytes(), sdk.NewCoin("steak", sdk.NewInt(50))),
} }
// Create transaction with only one signer // create transaction with only one signer
tx := types.NewTestEmbeddedTx(types.TestChainID, msgs, []*ecdsa.PrivateKey{types.TestPrivKey1}, tx := types.NewTestStdTx(
[]int64{0}, []int64{0}, types.NewStdFee()) types.TestChainID, msgs, []int64{0}, []int64{0}, []*ecdsa.PrivateKey{types.TestPrivKey1}, types.NewTestStdFee(),
)
ms, key := SetupMultiStore() ms, key := createTestMultiStore()
ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil)
accMapper := auth.NewAccountMapper(testCodec, key, auth.ProtoBaseAccount)
accountMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount) // set accounts in accountMapper
acc1 := accMapper.NewAccountWithAddress(ctx, types.TestAddr1.Bytes())
accMapper.SetAccount(ctx, acc1)
// Set account in accountMapper acc2 := accMapper.NewAccountWithAddress(ctx, types.TestAddr1.Bytes())
acc1 := accountMapper.NewAccountWithAddress(ctx, types.TestAddr1[:]) accMapper.SetAccount(ctx, acc2)
accountMapper.SetAccount(ctx, acc1)
acc2 := accountMapper.NewAccountWithAddress(ctx, types.TestAddr1[:])
accountMapper.SetAccount(ctx, acc2)
handler := AnteHandler(accountMapper)
handler := AnteHandler(accMapper, auth.FeeCollectionKeeper{})
_, res, abort := handler(ctx, tx) _, res, abort := handler(ctx, tx)
assert.True(t, abort, "Antehandler did not abort on invalid embedded tx") require.True(t, abort, "expected ante handler to abort")
require.Equal(t, sdk.ABCICodeType(0x10004), res.Code, "Result is OK on bad tx") require.Equal(t, sdk.ABCICodeType(0x10004), res.Code, fmt.Sprintf("invalid code returned on bad tx: %s", res.Log))
} }
func TestInvalidAccountNumberEmbeddedTx(t *testing.T) { func TestEmbeddedTxInvalidAccountNumber(t *testing.T) {
// Create msg to be embedded testCodec := types.NewTestCodec()
testCodec.RegisterConcrete(stake.MsgDelegate{}, "test/MsgDelegate", nil)
msgs := []sdk.Msg{ msgs := []sdk.Msg{
stake.NewMsgDelegate(types.TestAddr1[:], types.TestAddr2[:], sdk.Coin{"steak", sdk.NewInt(50)}), stake.NewMsgDelegate(types.TestAddr1.Bytes(), types.TestAddr2.Bytes(), sdk.NewCoin("steak", sdk.NewInt(50))),
} }
// Create transaction with wrong account number // create a transaction with an invalid account number
tx := types.NewTestEmbeddedTx(types.TestChainID, msgs, []*ecdsa.PrivateKey{types.TestPrivKey1}, tx := types.NewTestStdTx(
[]int64{3}, []int64{0}, types.NewStdFee()) types.TestChainID, msgs, []int64{3}, []int64{0}, []*ecdsa.PrivateKey{types.TestPrivKey1}, types.NewTestStdFee(),
)
ms, key := SetupMultiStore() ms, key := createTestMultiStore()
ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil)
accMapper := auth.NewAccountMapper(testCodec, key, auth.ProtoBaseAccount)
accountMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount) // set account in accountMapper
acc := accMapper.NewAccountWithAddress(ctx, types.TestAddr1.Bytes())
// Set account in accountMapper
acc := accountMapper.NewAccountWithAddress(ctx, types.TestAddr1[:])
acc.SetAccountNumber(4) acc.SetAccountNumber(4)
accountMapper.SetAccount(ctx, acc) accMapper.SetAccount(ctx, acc)
handler := AnteHandler(accountMapper)
handler := AnteHandler(accMapper, auth.FeeCollectionKeeper{})
_, res, abort := handler(ctx, tx) _, res, abort := handler(ctx, tx)
assert.True(t, abort, "Antehandler did not abort on invalid embedded tx") require.True(t, abort, "expected ante handler to abort")
require.Equal(t, sdk.ABCICodeType(0x10004), res.Code, "Result is OK on bad tx") require.Equal(t, sdk.ABCICodeType(0x10003), res.Code, fmt.Sprintf("invalid code returned on bad tx: %s", res.Log))
} }
func TestInvalidSequenceEmbeddedTx(t *testing.T) { func TestEmbeddedTxInvalidSequence(t *testing.T) {
// Create msg to be embedded testCodec := types.NewTestCodec()
testCodec.RegisterConcrete(stake.MsgDelegate{}, "test/MsgDelegate", nil)
msgs := []sdk.Msg{ msgs := []sdk.Msg{
stake.NewMsgDelegate(types.TestAddr1[:], types.TestAddr2[:], sdk.Coin{"steak", sdk.NewInt(50)}), stake.NewMsgDelegate(types.TestAddr1.Bytes(), types.TestAddr2.Bytes(), sdk.NewCoin("steak", sdk.NewInt(50))),
} }
// Create transaction with wrong account number // create transaction with an invalid sequence (nonce)
tx := types.NewTestEmbeddedTx(types.TestChainID, msgs, []*ecdsa.PrivateKey{types.TestPrivKey1}, tx := types.NewTestStdTx(
[]int64{4}, []int64{2}, types.NewStdFee()) types.TestChainID, msgs, []int64{4}, []int64{2}, []*ecdsa.PrivateKey{types.TestPrivKey1}, types.NewTestStdFee(),
)
ms, key := SetupMultiStore() ms, key := createTestMultiStore()
ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil)
accMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount)
accountMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount) // set account in accountMapper
acc := accMapper.NewAccountWithAddress(ctx, types.TestAddr1.Bytes())
// Set account in accountMapper
acc := accountMapper.NewAccountWithAddress(ctx, types.TestAddr1[:])
acc.SetAccountNumber(4) acc.SetAccountNumber(4)
acc.SetSequence(3) acc.SetSequence(3)
accountMapper.SetAccount(ctx, acc) accMapper.SetAccount(ctx, acc)
handler := AnteHandler(accountMapper)
handler := AnteHandler(accMapper, auth.FeeCollectionKeeper{})
_, res, abort := handler(ctx, tx) _, res, abort := handler(ctx, tx)
assert.True(t, abort, "Antehandler did not abort on invalid embedded tx") require.True(t, abort, "expected ante handler to abort")
require.Equal(t, sdk.ABCICodeType(0x10004), res.Code, "Result is OK on bad tx") require.Equal(t, sdk.ABCICodeType(0x10003), res.Code, fmt.Sprintf("invalid code returned on bad tx: %s", res.Log))
} }
func TestValidEmbeddedTx(t *testing.T) { func TestEmbeddedTxValid(t *testing.T) {
// Create msg to be embedded testCodec := types.NewTestCodec()
testCodec.RegisterConcrete(stake.MsgDelegate{}, "test/MsgDelegate", nil)
msgs := []sdk.Msg{ msgs := []sdk.Msg{
stake.NewMsgDelegate(types.TestAddr1[:], types.TestAddr2[:], sdk.Coin{"steak", sdk.NewInt(50)}), stake.NewMsgDelegate(types.TestAddr1.Bytes(), types.TestAddr2.Bytes(), sdk.NewCoin("steak", sdk.NewInt(50))),
stake.NewMsgDelegate(types.TestAddr2[:], types.TestAddr2[:], sdk.Coin{"steak", sdk.NewInt(50)}), stake.NewMsgDelegate(types.TestAddr2.Bytes(), types.TestAddr2.Bytes(), sdk.NewCoin("steak", sdk.NewInt(50))),
} }
tx := types.NewTestEmbeddedTx(types.TestChainID, msgs, []*ecdsa.PrivateKey{types.TestPrivKey1, types.TestPrivKey2}, // create a valid transaction
[]int64{4, 5}, []int64{3, 1}, types.NewStdFee()) tx := types.NewTestStdTx(
types.TestChainID, msgs, []int64{4, 5}, []int64{3, 1},
[]*ecdsa.PrivateKey{types.TestPrivKey1, types.TestPrivKey2}, types.NewTestStdFee(),
)
ms, key := SetupMultiStore() ms, key := createTestMultiStore()
ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil) ctx := sdk.NewContext(ms, abci.Header{ChainID: types.TestChainID.String()}, false, nil)
accMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount)
accountMapper := auth.NewAccountMapper(types.NewTestCodec(), key, auth.ProtoBaseAccount) // set accounts in the accountMapper
acc1 := accMapper.NewAccountWithAddress(ctx, types.TestAddr1.Bytes())
// Set account in accountMapper
acc1 := accountMapper.NewAccountWithAddress(ctx, types.TestAddr1[:])
acc1.SetAccountNumber(4) acc1.SetAccountNumber(4)
acc1.SetSequence(3) acc1.SetSequence(3)
accountMapper.SetAccount(ctx, acc1) accMapper.SetAccount(ctx, acc1)
acc2 := accountMapper.NewAccountWithAddress(ctx, types.TestAddr2[:])
acc2 := accMapper.NewAccountWithAddress(ctx, types.TestAddr2.Bytes())
acc2.SetAccountNumber(5) acc2.SetAccountNumber(5)
acc2.SetSequence(1) acc2.SetSequence(1)
accountMapper.SetAccount(ctx, acc2) accMapper.SetAccount(ctx, acc2)
handler := AnteHandler(accountMapper)
handler := AnteHandler(accMapper, auth.FeeCollectionKeeper{})
_, res, abort := handler(ctx, tx) _, res, abort := handler(ctx, tx)
require.False(t, abort, "Antehandler abort on valid embedded tx") require.False(t, abort, "expected ante handler to not abort")
require.True(t, res.IsOK(), fmt.Sprintf("Result not OK on valid Tx: %s", res.Log)) require.True(t, res.IsOK(), fmt.Sprintf("result not OK on valid Tx: %s", res.Log))
// Ensure account state updated correctly // Ensure account state updated correctly
seq1, _ := accountMapper.GetSequence(ctx, types.TestAddr1[:]) seq1, _ := accMapper.GetSequence(ctx, types.TestAddr1.Bytes())
seq2, _ := accountMapper.GetSequence(ctx, types.TestAddr2[:]) seq2, _ := accMapper.GetSequence(ctx, types.TestAddr2.Bytes())
assert.Equal(t, int64(4), seq1, "Sequence1 did not increment correctly")
assert.Equal(t, int64(2), seq2, "Sequence2 did not increment correctly")
require.Equal(t, int64(4), seq1, "account nonce did not increment correctly")
require.Equal(t, int64(2), seq2, "account nonce did not increment correctly")
} }

View File

@ -6,11 +6,13 @@ import (
dbm "github.com/tendermint/tendermint/libs/db" dbm "github.com/tendermint/tendermint/libs/db"
) )
func SetupMultiStore() (sdk.MultiStore, *sdk.KVStoreKey) { func createTestMultiStore() (sdk.MultiStore, *sdk.KVStoreKey) {
db := dbm.NewMemDB() db := dbm.NewMemDB()
capKey := sdk.NewKVStoreKey("capkey") capKey := sdk.NewKVStoreKey("capkey")
ms := store.NewCommitMultiStore(db) ms := store.NewCommitMultiStore(db)
ms.MountStoreWithDB(capKey, sdk.StoreTypeIAVL, db) ms.MountStoreWithDB(capKey, sdk.StoreTypeIAVL, db)
ms.LoadLatestVersion() ms.LoadLatestVersion()
return ms, capKey return ms, capKey
} }

View File

@ -40,7 +40,7 @@ func NewTestStdFee() auth.StdFee {
} }
func NewTestStdTx( func NewTestStdTx(
chainID *big.Int, msgs []sdk.Msg, accNums []int64, seqs []int64, pKeys []*ecdsa.PrivateKey, fee auth.StdFee, chainID *big.Int, msgs []sdk.Msg, accNums, seqs []int64, pKeys []*ecdsa.PrivateKey, fee auth.StdFee,
) sdk.Tx { ) sdk.Tx {
sigs := make([]auth.StdSignature, len(pKeys)) sigs := make([]auth.StdSignature, len(pKeys))
@ -100,22 +100,3 @@ func NewTestEthTxs(
return txs return txs
} }
func NewTestSDKTxs(
codec *wire.Codec, chainID *big.Int, to ethcmn.Address, msgs []sdk.Msg,
accNums []int64, seqs []int64, pKeys []*ecdsa.PrivateKey, fee auth.StdFee,
) []*Transaction {
txs := make([]*Transaction, len(pKeys))
stdTx := NewTestStdTx(chainID, msgs, accNums, seqs, pKeys, fee)
payload := codec.MustMarshalBinary(stdTx)
for i, privKey := range pKeys {
ethTx := NewTransaction(uint64(seqs[i]), to, big.NewInt(10), 1000, big.NewInt(100), payload)
ethTx.Sign(chainID, privKey)
txs[i] = ethTx
}
return txs
}

View File

@ -120,16 +120,14 @@ func TestTxDecoder(t *testing.T) {
require.Equal(t, txs[0].data, (decodedTx.(Transaction)).data) require.Equal(t, txs[0].data, (decodedTx.(Transaction)).data)
// create a SDK (auth.StdTx) transaction and encode // create a SDK (auth.StdTx) transaction and encode
txs = NewTestSDKTxs( stdTx := NewTestStdTx(TestChainID, msgs, []int64{0}, []int64{0}, []*ecdsa.PrivateKey{TestPrivKey1}, NewTestStdFee())
testCodec, TestChainID, TestSDKAddr, msgs, []int64{0}, []int64{0}, payload := testCodec.MustMarshalBinary(stdTx)
[]*ecdsa.PrivateKey{TestPrivKey1}, NewTestStdFee(), tx := NewTransaction(0, TestSDKAddr, big.NewInt(10), 1000, big.NewInt(100), payload)
)
txBytes, err = rlp.EncodeToBytes(txs[0]) txBytes, err = rlp.EncodeToBytes(tx)
require.NoError(t, err) require.NoError(t, err)
// require the transaction to properly decode into a Transaction // require the transaction to properly decode into a Transaction
stdTx := NewTestStdTx(TestChainID, msgs, []int64{0}, []int64{0}, []*ecdsa.PrivateKey{TestPrivKey1}, NewTestStdFee())
decodedTx, err = txDecoder(txBytes) decodedTx, err = txDecoder(txBytes)
require.NoError(t, err) require.NoError(t, err)
require.IsType(t, auth.StdTx{}, decodedTx) require.IsType(t, auth.StdTx{}, decodedTx)