test: [ENG-758]: Tx config testing (#91)

Co-authored-by: Aleksandr Bezobchuk <alexanderbez@users.noreply.github.com>
This commit is contained in:
David Terpay 2023-04-26 14:02:11 -04:00 committed by GitHub
parent 328d28dc3f
commit 57a63932ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 590 additions and 7 deletions

View File

@ -4,6 +4,7 @@ import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth/signing"
)
type (
@ -94,11 +95,14 @@ func (config *DefaultConfig) GetTransactionSigners(tx []byte) (map[string]struct
return nil, err
}
sigTx, ok := sdkTx.(signing.SigVerifiableTx)
if !ok {
return nil, fmt.Errorf("transaction is not valid")
}
signers := make(map[string]struct{})
for _, msg := range sdkTx.GetMsgs() {
for _, signer := range msg.GetSigners() {
signers[signer.String()] = struct{}{}
}
for _, signer := range sigTx.GetSigners() {
signers[signer.String()] = struct{}{}
}
return signers, nil

548
mempool/config_test.go Normal file
View File

@ -0,0 +1,548 @@
package mempool_test
import (
sdk "github.com/cosmos/cosmos-sdk/types"
testutils "github.com/skip-mev/pob/testutils"
)
func (suite *IntegrationTestSuite) TestIsAuctionTx() {
testCases := []struct {
name string
createTx func() sdk.Tx
isAuctionTx bool
expectedError bool
}{
{
"normal sdk tx",
func() sdk.Tx {
tx, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 2, 0)
suite.Require().NoError(err)
return tx
},
false,
false,
},
{
"malformed auction bid tx",
func() sdk.Tx {
msgAuctionBid, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 0, 2)
suite.Require().NoError(err)
msgs := testutils.CreateRandomMsgs(suite.accounts[0].Address, 2)
msgs = append(msgs, msgAuctionBid)
tx, err := testutils.CreateTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 0, msgs)
suite.Require().NoError(err)
return tx
},
false,
true,
},
{
"valid auction bid tx",
func() sdk.Tx {
msgAuctionBid, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 0, 2)
suite.Require().NoError(err)
msgs := []sdk.Msg{msgAuctionBid}
tx, err := testutils.CreateTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 0, msgs)
suite.Require().NoError(err)
return tx
},
true,
false,
},
{
"tx with multiple MsgAuctionBid messages",
func() sdk.Tx {
bid1, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 0, 2)
suite.Require().NoError(err)
bid2, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 1, 2)
suite.Require().NoError(err)
msgs := []sdk.Msg{bid1, bid2}
tx, err := testutils.CreateTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 0, msgs)
suite.Require().NoError(err)
return tx
},
false,
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
tx := tc.createTx()
isAuctionTx, err := suite.config.IsAuctionTx(tx)
suite.Require().Equal(tc.isAuctionTx, isAuctionTx)
if tc.expectedError {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
}
})
}
}
func (suite *IntegrationTestSuite) TestGetTransactionSigners() {
testCases := []struct {
name string
createTx func() []byte
expectedSigners []string
}{
{
"normal sdk tx",
func() []byte {
tx, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 1, 0)
suite.Require().NoError(err)
bz, err := suite.encCfg.TxConfig.TxEncoder()(tx)
suite.Require().NoError(err)
return bz
},
[]string{suite.accounts[0].Address.String()},
},
{
"normal sdk tx with several messages",
func() []byte {
tx, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 10, 0)
suite.Require().NoError(err)
bz, err := suite.encCfg.TxConfig.TxEncoder()(tx)
suite.Require().NoError(err)
return bz
},
[]string{suite.accounts[0].Address.String()},
},
{
"multiple signers on tx",
func() []byte {
tx, err := testutils.CreateTxWithSigners(suite.encCfg.TxConfig, 0, 0, suite.accounts[0:3])
suite.Require().NoError(err)
bz, err := suite.encCfg.TxConfig.TxEncoder()(tx)
suite.Require().NoError(err)
return bz
},
[]string{suite.accounts[0].Address.String(), suite.accounts[1].Address.String(), suite.accounts[2].Address.String()},
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
tx := tc.createTx()
signers, err := suite.config.GetTransactionSigners(tx)
suite.Require().NoError(err)
suite.Require().Equal(len(tc.expectedSigners), len(signers))
for _, signer := range tc.expectedSigners {
suite.Require().Contains(signers, signer)
}
})
}
}
func (suite *IntegrationTestSuite) TestGetBundleSigners() {
testCases := []struct {
name string
createBundle func() [][]byte
expectedSigners [][]string
}{
{
"single bundle with one signer",
func() [][]byte {
tx, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 1, 0)
suite.Require().NoError(err)
bz, err := suite.encCfg.TxConfig.TxEncoder()(tx)
suite.Require().NoError(err)
return [][]byte{bz}
},
[][]string{{suite.accounts[0].Address.String()}},
},
{
"single bundle with multiple signers",
func() [][]byte {
tx, err := testutils.CreateTxWithSigners(suite.encCfg.TxConfig, 0, 0, suite.accounts[0:3])
suite.Require().NoError(err)
bz, err := suite.encCfg.TxConfig.TxEncoder()(tx)
suite.Require().NoError(err)
return [][]byte{bz}
},
[][]string{{suite.accounts[0].Address.String(), suite.accounts[1].Address.String(), suite.accounts[2].Address.String()}},
},
{
"multiple bundles with one signer",
func() [][]byte {
tx1, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 1, 0)
suite.Require().NoError(err)
bz1, err := suite.encCfg.TxConfig.TxEncoder()(tx1)
suite.Require().NoError(err)
tx2, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, suite.accounts[1], 0, 1, 0)
suite.Require().NoError(err)
bz2, err := suite.encCfg.TxConfig.TxEncoder()(tx2)
suite.Require().NoError(err)
return [][]byte{bz1, bz2}
},
[][]string{{suite.accounts[0].Address.String()}, {suite.accounts[1].Address.String()}},
},
{
"multiple bundles with multiple signers",
func() [][]byte {
tx1, err := testutils.CreateTxWithSigners(suite.encCfg.TxConfig, 0, 0, suite.accounts[0:3])
suite.Require().NoError(err)
bz1, err := suite.encCfg.TxConfig.TxEncoder()(tx1)
suite.Require().NoError(err)
tx2, err := testutils.CreateTxWithSigners(suite.encCfg.TxConfig, 0, 0, suite.accounts[3:6])
suite.Require().NoError(err)
bz2, err := suite.encCfg.TxConfig.TxEncoder()(tx2)
suite.Require().NoError(err)
return [][]byte{bz1, bz2}
},
[][]string{{suite.accounts[0].Address.String(), suite.accounts[1].Address.String(), suite.accounts[2].Address.String()}, {suite.accounts[3].Address.String(), suite.accounts[4].Address.String(), suite.accounts[5].Address.String()}},
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
bundle := tc.createBundle()
signers, err := suite.config.GetBundleSigners(bundle)
suite.Require().NoError(err)
suite.Require().Equal(len(tc.expectedSigners), len(signers))
for i, bundleSigners := range tc.expectedSigners {
suite.Require().Equal(len(bundleSigners), len(signers[i]))
for _, signer := range bundleSigners {
suite.Require().Contains(signers[i], signer)
}
}
})
}
}
func (suite *IntegrationTestSuite) TestWrapBundleTransaction() {
testCases := []struct {
name string
createBundleTx func() (sdk.Tx, []byte)
}{
{
"normal sdk tx",
func() (sdk.Tx, []byte) {
tx, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 1, 0)
suite.Require().NoError(err)
bz, err := suite.encCfg.TxConfig.TxEncoder()(tx)
suite.Require().NoError(err)
return tx, bz
},
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
tx, bz := tc.createBundleTx()
wrappedTx, err := suite.config.WrapBundleTransaction(bz)
suite.Require().NoError(err)
txBytes, err := suite.encCfg.TxConfig.TxEncoder()(tx)
suite.Require().NoError(err)
wrappedTxBytes, err := suite.encCfg.TxConfig.TxEncoder()(wrappedTx)
suite.Require().NoError(err)
suite.Require().Equal(txBytes, wrappedTxBytes)
})
}
}
func (suite *IntegrationTestSuite) TestGetBidder() {
testCases := []struct {
name string
createTx func() sdk.Tx
expectedBidder string
expectedError bool
}{
{
"normal sdk tx",
func() sdk.Tx {
tx, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 1, 0)
suite.Require().NoError(err)
return tx
},
"",
true,
},
{
"valid auction tx",
func() sdk.Tx {
msgAuctionBid, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 0, 2)
suite.Require().NoError(err)
msgs := []sdk.Msg{msgAuctionBid}
tx, err := testutils.CreateTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 0, msgs)
suite.Require().NoError(err)
return tx
},
suite.accounts[0].Address.String(),
false,
},
{
"invalid auction tx",
func() sdk.Tx {
msgAuctionBid, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 0, 2)
suite.Require().NoError(err)
randomMsg := testutils.CreateRandomMsgs(suite.accounts[0].Address, 1)[0]
suite.Require().NoError(err)
msgs := []sdk.Msg{msgAuctionBid, randomMsg}
tx, err := testutils.CreateTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 0, msgs)
suite.Require().NoError(err)
return tx
},
"",
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
tx := tc.createTx()
bidder, err := suite.config.GetBidder(tx)
if tc.expectedError {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
suite.Require().Equal(tc.expectedBidder, bidder.String())
}
})
}
}
func (suite *IntegrationTestSuite) TestGetBid() {
testCases := []struct {
name string
createTx func() sdk.Tx
expectedBid sdk.Coin
expectedError bool
}{
{
"normal sdk tx",
func() sdk.Tx {
tx, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 1, 0)
suite.Require().NoError(err)
return tx
},
sdk.Coin{},
true,
},
{
"valid auction tx",
func() sdk.Tx {
msgAuctionBid, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 0, 2)
suite.Require().NoError(err)
msgs := []sdk.Msg{msgAuctionBid}
tx, err := testutils.CreateTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 0, msgs)
suite.Require().NoError(err)
return tx
},
sdk.NewInt64Coin("foo", 100),
false,
},
{
"invalid auction tx",
func() sdk.Tx {
msgAuctionBid, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 0, 2)
suite.Require().NoError(err)
randomMsg := testutils.CreateRandomMsgs(suite.accounts[0].Address, 1)[0]
suite.Require().NoError(err)
msgs := []sdk.Msg{msgAuctionBid, randomMsg}
tx, err := testutils.CreateTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 0, msgs)
suite.Require().NoError(err)
return tx
},
sdk.Coin{},
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
tx := tc.createTx()
bid, err := suite.config.GetBid(tx)
if tc.expectedError {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
suite.Require().Equal(tc.expectedBid, bid)
}
})
}
}
func (suite *IntegrationTestSuite) TestGetBundledTransactions() {
testCases := []struct {
name string
createTx func() (sdk.Tx, [][]byte)
expectedError bool
}{
{
"normal sdk tx",
func() (sdk.Tx, [][]byte) {
tx, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 1, 0)
suite.Require().NoError(err)
return tx, nil
},
true,
},
{
"valid auction tx",
func() (sdk.Tx, [][]byte) {
msgAuctionBid, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 0, 2)
suite.Require().NoError(err)
msgs := []sdk.Msg{msgAuctionBid}
tx, err := testutils.CreateTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 0, msgs)
suite.Require().NoError(err)
return tx, msgAuctionBid.Transactions
},
false,
},
{
"invalid auction tx",
func() (sdk.Tx, [][]byte) {
msgAuctionBid, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 0, 2)
suite.Require().NoError(err)
randomMsg := testutils.CreateRandomMsgs(suite.accounts[0].Address, 1)[0]
suite.Require().NoError(err)
msgs := []sdk.Msg{msgAuctionBid, randomMsg}
tx, err := testutils.CreateTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 0, msgs)
suite.Require().NoError(err)
return tx, nil
},
true,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
tx, expectedBundledTxs := tc.createTx()
bundledTxs, err := suite.config.GetBundledTransactions(tx)
if tc.expectedError {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
suite.Require().Equal(expectedBundledTxs, bundledTxs)
}
})
}
}
func (suite *IntegrationTestSuite) TestGetTimeout() {
testCases := []struct {
name string
createTx func() sdk.Tx
expectedError bool
expectedTimeout uint64
}{
{
"normal sdk tx",
func() sdk.Tx {
tx, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 1, 1)
suite.Require().NoError(err)
return tx
},
false,
1,
},
{
"valid auction tx",
func() sdk.Tx {
msgAuctionBid, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 0, 2)
suite.Require().NoError(err)
msgs := []sdk.Msg{msgAuctionBid}
tx, err := testutils.CreateTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 10, msgs)
suite.Require().NoError(err)
return tx
},
false,
10,
},
{
"invalid auction tx",
func() sdk.Tx {
msgAuctionBid, err := testutils.CreateMsgAuctionBid(suite.encCfg.TxConfig, suite.accounts[0], sdk.NewInt64Coin("foo", 100), 0, 2)
suite.Require().NoError(err)
randomMsg := testutils.CreateRandomMsgs(suite.accounts[0].Address, 1)[0]
suite.Require().NoError(err)
msgs := []sdk.Msg{msgAuctionBid, randomMsg}
tx, err := testutils.CreateTx(suite.encCfg.TxConfig, suite.accounts[0], 0, 10, msgs)
suite.Require().NoError(err)
return tx
},
false,
10,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
tx := tc.createTx()
timeout, err := suite.config.GetTimeout(tx)
if tc.expectedError {
suite.Require().Error(err)
} else {
suite.Require().NoError(err)
suite.Require().Equal(tc.expectedTimeout, timeout)
}
})
}
}

View File

@ -19,6 +19,7 @@ type IntegrationTestSuite struct {
suite.Suite
encCfg testutils.EncodingConfig
config mempool.Config
mempool *mempool.AuctionMempool
ctx sdk.Context
random *rand.Rand
@ -33,13 +34,13 @@ func TestMempoolTestSuite(t *testing.T) {
func (suite *IntegrationTestSuite) SetupTest() {
// Mempool setup
suite.encCfg = testutils.CreateTestEncodingConfig()
config := mempool.NewDefaultConfig(suite.encCfg.TxConfig.TxDecoder())
suite.mempool = mempool.NewAuctionMempool(suite.encCfg.TxConfig.TxDecoder(), suite.encCfg.TxConfig.TxEncoder(), 0, config)
suite.config = mempool.NewDefaultConfig(suite.encCfg.TxConfig.TxDecoder())
suite.mempool = mempool.NewAuctionMempool(suite.encCfg.TxConfig.TxDecoder(), suite.encCfg.TxConfig.TxEncoder(), 0, suite.config)
suite.ctx = sdk.NewContext(nil, cmtproto.Header{}, false, log.NewNopLogger())
// Init accounts
suite.random = rand.New(rand.NewSource(time.Now().Unix()))
suite.accounts = testutils.RandomAccounts(suite.random, 5)
suite.accounts = testutils.RandomAccounts(suite.random, 10)
suite.nonces = make(map[string]uint64)
for _, acc := range suite.accounts {

View File

@ -125,6 +125,36 @@ func CreateRandomTx(txCfg client.TxConfig, account Account, nonce, numberMsgs, t
return txBuilder.GetTx(), nil
}
func CreateTxWithSigners(txCfg client.TxConfig, nonce, timeout uint64, signers []Account) (authsigning.Tx, error) {
msgs := []sdk.Msg{}
for _, signer := range signers {
msg := CreateRandomMsgs(signer.Address, 1)
msgs = append(msgs, msg...)
}
txBuilder := txCfg.NewTxBuilder()
if err := txBuilder.SetMsgs(msgs...); err != nil {
return nil, err
}
sigV2 := signing.SignatureV2{
PubKey: signers[0].PrivKey.PubKey(),
Data: &signing.SingleSignatureData{
SignMode: txCfg.SignModeHandler().DefaultMode(),
Signature: nil,
},
Sequence: nonce,
}
if err := txBuilder.SetSignatures(sigV2); err != nil {
return nil, err
}
txBuilder.SetTimeoutHeight(timeout)
return txBuilder.GetTx(), nil
}
func CreateAuctionTxWithSigners(txCfg client.TxConfig, bidder Account, bid sdk.Coin, nonce, timeout uint64, signers []Account) (authsigning.Tx, error) {
bidMsg := &buildertypes.MsgAuctionBid{
Bidder: bidder.Address.String(),