diff --git a/abci/abci_test.go b/abci/abci_test.go index ef43d8b5..86e2d1e1 100644 --- a/abci/abci_test.go +++ b/abci/abci_test.go @@ -101,7 +101,7 @@ func (s *ProposalsTestSuite) TestPrepareProposal() { tx1, err := testutils.CreateRandomTx( s.encodingConfig.TxConfig, s.accounts[0], - 0, + 1, 1, 0, 1, @@ -112,8 +112,8 @@ func (s *ProposalsTestSuite) TestPrepareProposal() { // Create a second random transaction that will be inserted into the default lane tx2, err := testutils.CreateRandomTx( s.encodingConfig.TxConfig, - s.accounts[1], - 1, + s.accounts[0], + 0, 1, 0, 1, @@ -1234,27 +1234,46 @@ func (s *ProposalsTestSuite) TestPrepareProcessParity() { numAccounts := 25 accounts := testutils.RandomAccounts(s.random, numAccounts) + feeDenoms := []string{ + s.gasTokenDenom, + "eth", + "btc", + "usdt", + "usdc", + } + // Create a bunch of transactions to insert into the default lane txsToInsert := []sdk.Tx{} validationMap := make(map[sdk.Tx]bool) - for _, account := range accounts { - for nonce := uint64(0); nonce < numTxsPerAccount; nonce++ { - // create a random fee amount - feeAmount := math.NewInt(int64(rand.Intn(100000))) - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - account, - nonce, - 1, - 0, - 1, - sdk.NewCoin(s.gasTokenDenom, feeAmount), - ) - s.Require().NoError(err) + for nonce := uint64(0); nonce < numTxsPerAccount*uint64(numAccounts); nonce++ { + fees := []sdk.Coin{} + // choose a random set of fee denoms + perm := rand.Perm(len(feeDenoms)) + for i := 0; i < 1+rand.Intn(len(feeDenoms)-1); i++ { + fees = append(fees, sdk.NewCoin(feeDenoms[perm[i]], math.NewInt(int64(rand.Intn(100000))))) + } - txsToInsert = append(txsToInsert, tx) - validationMap[tx] = true + // choose a random set of accounts + perm = rand.Perm(len(accounts)) + signers := []testutils.Account{} + for i := 0; i < 1+rand.Intn(len(accounts)-1); i++ { + signers = append(signers, accounts[perm[i]]) } + + // create a random fee amount + tx, err := testutils.CreateRandomTxMultipleSigners( + s.encodingConfig.TxConfig, + signers, + nonce, + 1, + 0, + 1, + fees..., + ) + s.Require().NoError(err) + + txsToInsert = append(txsToInsert, tx) + validationMap[tx] = true } // Set up the default lane with the transactions diff --git a/abci/utils_test.go b/abci/utils_test.go index 70ab4327..9672f16a 100644 --- a/abci/utils_test.go +++ b/abci/utils_test.go @@ -65,7 +65,7 @@ func (s *ProposalsTestSuite) setUpCustomMatchHandlerLane(maxBlockSpace math.Lega options := []base.LaneOption{ base.WithMatchHandler(mh), - base.WithMempoolConfigs[string](cfg, base.DefaultTxPriority()), + base.WithMempoolConfigs(cfg, base.DefaultTxPriority()), } lane, err := base.NewBaseLane( @@ -129,7 +129,7 @@ func (s *ProposalsTestSuite) setUpPanicLane(name string, maxBlockSpace math.Lega options := []base.LaneOption{ base.WithMatchHandler(base.DefaultMatchHandler()), - base.WithMempoolConfigs[string](cfg, base.DefaultTxPriority()), + base.WithMempoolConfigs(cfg, base.DefaultTxPriority()), base.WithPrepareLaneHandler(base.PanicPrepareLaneHandler()), base.WithProcessLaneHandler(base.PanicProcessLaneHandler()), } diff --git a/block/base/mempool_test.go b/block/base/mempool_test.go index c02f610b..0f59c5ab 100644 --- a/block/base/mempool_test.go +++ b/block/base/mempool_test.go @@ -1,4 +1,4 @@ -package base +package base_test import ( "fmt" @@ -10,15 +10,22 @@ import ( "github.com/stretchr/testify/require" signerextraction "github.com/skip-mev/block-sdk/adapters/signer_extraction_adapter" + "github.com/skip-mev/block-sdk/block/base" "github.com/skip-mev/block-sdk/testutils" ) +type txGen struct { + acc testutils.Account + nonce uint64 + amount sdk.Coin +} + func TestMempoolComparison(t *testing.T) { acct := testutils.RandomAccounts(rand.New(rand.NewSource(1)), 2) txc := testutils.CreateTestEncodingConfig().TxConfig ctx := testutils.CreateBaseSDKContext(t) - mp := NewMempool( - DefaultTxPriority(), + mp := base.NewMempool( + base.DefaultTxPriority(), txc.TxEncoder(), signerextraction.NewDefaultAdapter(), 1000, @@ -66,7 +73,7 @@ func TestMempoolComparison(t *testing.T) { require.NoError(t, err) output, err := mp.Compare(ctx, tx1, tx2) require.NoError(t, err) - require.Equal(t, -1, output) + require.Equal(t, 0, output) }) t.Run("test diff account, tx1 lt amount, tx1 gt nonce, diff denoms", func(t *testing.T) { tx1, err := testutils.CreateTx(txc, acct[0], 1, 0, nil, sdk.NewCoin("nonstake", sdkmath.NewInt(1))) @@ -87,3 +94,80 @@ func TestMempoolComparison(t *testing.T) { require.Equal(t, 0, output) }) } + +func TestMempoolSelect(t *testing.T) { + acct := testutils.RandomAccounts(rand.New(rand.NewSource(1)), 2) + txc := testutils.CreateTestEncodingConfig().TxConfig + ctx := testutils.CreateBaseSDKContext(t) + se := signerextraction.NewDefaultAdapter() + mp := base.NewMempool( + base.DefaultTxPriority(), + txc.TxEncoder(), + se, + 1000, + ) + tests := []struct { + name string + inputs []txGen + expected []txGen + }{ + { + name: "test1", + inputs: []txGen{ + { + acc: acct[0], + amount: sdk.NewCoin("stake", sdkmath.NewInt(1)), + nonce: 0, + }, + { + acc: acct[0], + amount: sdk.NewCoin("notstake", sdkmath.NewInt(2)), + nonce: 1, + }, + }, + expected: []txGen{ + { + acc: acct[0], + amount: sdk.NewCoin("stake", sdkmath.NewInt(1)), + nonce: 0, + }, + { + acc: acct[0], + amount: sdk.NewCoin("notstake", sdkmath.NewInt(2)), + nonce: 1, + }, + }, + }, + } + for _, tc := range tests { + // insert all input txs + t.Run(tc.name, func(t *testing.T) { + for _, tx := range tc.inputs { + inputTx, err := testutils.CreateTx(txc, tx.acc, tx.nonce, 0, nil, tx.amount) + require.NoError(t, err) + err = mp.Insert(ctx, inputTx) + require.NoError(t, err) + } + }) + // extract all txs via select + var output []sdk.Tx + for iter := mp.Select(ctx, nil); iter != nil; iter = iter.Next() { + output = append(output, iter.Tx()) + } + // validate the order matches the expected order + require.Equal(t, len(tc.expected), len(output)) + for i, tx := range output { + + sigs, err := se.GetSigners(tx) + require.NoError(t, err) + require.Equal(t, 1, len(sigs)) + require.Equal(t, tc.expected[i].acc.Address, sigs[0].Signer) + feeTx, ok := tx.(sdk.FeeTx) + require.True(t, ok) + require.Equal(t, tc.expected[i].amount.Denom, feeTx.GetFee().GetDenomByIndex(0)) + require.Equal(t, tc.expected[i].amount.Amount, feeTx.GetFee().AmountOf(feeTx.GetFee().GetDenomByIndex(0))) + require.Equal(t, tc.expected[i].nonce, sigs[0].Sequence) + + } + } +} diff --git a/block/base/tx_priority.go b/block/base/tx_priority.go index 570dcf31..33d7c8b2 100644 --- a/block/base/tx_priority.go +++ b/block/base/tx_priority.go @@ -2,174 +2,19 @@ package base import ( "context" - "fmt" - "strconv" - "strings" - - "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" ) -type Coins map[string]math.Int - -// DefaultTxPriority returns a default implementation of the TxPriority. It prioritizes -// transactions by their fee. -func DefaultTxPriority() TxPriority[string] { - return TxPriority[string]{ - GetTxPriority: func(goCtx context.Context, tx sdk.Tx) string { - feeTx, ok := tx.(sdk.FeeTx) - if !ok { - return "" - } - - return coinsToString(feeTx.GetFee()) - }, - Compare: func(a, b string) int { - aCoins, _ := coinsFromString(a) - bCoins, _ := coinsFromString(b) - - switch { - case aCoins.Greater(bCoins): - return 1 - - case bCoins.Greater(aCoins): - return -1 - - default: - return 0 - } - }, - MinValue: "", - } -} - -func coinsToString(coins sdk.Coins) string { - // sort the coins by denomination - coins.Sort() - - // to avoid dealing with regex, etc. we use a , to separate denominations from amounts - // e.g. 10000,stake,10000,atom - coinString := "" - for i, coin := range coins { - coinString += coin.Amount.String() + "," + coin.Denom - if i != len(coins)-1 { - coinString += "," - } - } - - return coinString -} - -// coinsFromString converts a string of coins to a sdk.Coins object. -func coinsFromString(coinsString string) (Coins, error) { - // if its empty string (zero value), we return nil - if coinsString == "" { - return nil, nil - } - - // split the string by commas - coinStrings := strings.Split(coinsString, ",") - - // if the length is odd, then the given string is invalid - if len(coinStrings)%2 != 0 { - return nil, fmt.Errorf("invalid coins string: %s", coinsString) - } - - coins := make(Coins, len(coinsString)/2) - for i := 0; i < len(coinStrings); i += 2 { - // split the string by pipe - amount, ok := intFromString(coinStrings[i]) - if !ok { - return nil, fmt.Errorf("invalid amount: %s, denom: %s", coinStrings[i], coinStrings[i+1]) - } - - coins[coinStrings[i+1]] = amount - } - - return coins, nil -} - -func intFromString(str string) (math.Int, bool) { - // first attempt to get int64 from the string - int64Val, err := strconv.ParseInt(str, 10, 64) - if err == nil { - return math.NewInt(int64Val), true - } - - // if we can't get an int64, then get raw math.Int - return math.NewIntFromString(str) -} - -// Greater returns true if lhs is strictly greater than rhs, and false otherwise. Notice, lhs / rhs must be comparable, -// specifically, they must have the exact same denoms, otherwise, they aren't comparable. -func (lhs Coins) Greater(rhs Coins) bool { - // if a or b is nil, then return whether a is non-nil - if lhs == nil || rhs == nil { - return lhs != nil - } - - // for each of a's denoms, check if b has the same denom - if len(lhs) != len(rhs) { - return false - } - - // for each of a's denoms, check if a is greater - for denom, aAmount := range lhs { - // b does not have the corresponding denom, a is not greater - bAmount, ok := rhs[denom] - if !ok { - return false - } - - // a is not greater than b - if !aAmount.GT(bAmount) { - return false - } - } - - return true -} - -// DeprecatedTxPriority serves the same purpose as DefaultTxPriority, however, it is significantly slower- on the order of -// 6-10x slower. -func DeprecatedTxPriority() TxPriority[string] { - return TxPriority[string]{ - GetTxPriority: func(goCtx context.Context, tx sdk.Tx) string { - feeTx, ok := tx.(sdk.FeeTx) - if !ok { - return "" - } - - return feeTx.GetFee().String() +// DefaultTxPriority +func DefaultTxPriority() TxPriority[int] { + return TxPriority[int]{ + GetTxPriority: func(goCtx context.Context, tx sdk.Tx) int { + return 0 }, - Compare: func(a, b string) int { - aCoins, _ := sdk.ParseCoinsNormalized(a) - bCoins, _ := sdk.ParseCoinsNormalized(b) - - switch { - case aCoins == nil && bCoins == nil: - return 0 - - case aCoins == nil: - return -1 - - case bCoins == nil: - return 1 - - default: - switch { - case aCoins.IsAllGT(bCoins): - return 1 - - case aCoins.IsAllLT(bCoins): - return -1 - - default: - return 0 - } - } + Compare: func(a, b int) int { + return 0 }, - MinValue: "", + MinValue: 0, } } diff --git a/block/base/tx_priority_test.go b/block/base/tx_priority_test.go index 65068280..8de9a821 100644 --- a/block/base/tx_priority_test.go +++ b/block/base/tx_priority_test.go @@ -1,7 +1,7 @@ package base_test import ( - "fmt" + "context" "math/rand" "testing" @@ -13,211 +13,30 @@ import ( "github.com/skip-mev/block-sdk/testutils" ) -const maxUint64 = "18446744073709551616" // value is 2^64 +func TestNopTxPriority(t *testing.T) { + txp := base.DefaultTxPriority() -func TestTxPriority(t *testing.T) { - acct := testutils.RandomAccounts(rand.New(rand.NewSource(1)), 1) txc := testutils.CreateTestEncodingConfig().TxConfig + accounts := testutils.RandomAccounts(rand.New(rand.NewSource(1)), 2) - type testCase struct { - name string - priority base.TxPriority[string] - } - - testCases := []testCase{ - { - "DeprecatedTxPriority", - base.DeprecatedTxPriority(), - }, - { - "DefaultTxPriority", - base.DefaultTxPriority(), - }, - } - t.Run("test getting a tx priority: DefaultTxPriority", func(t *testing.T) { - priority := base.DefaultTxPriority() - - tx, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1))) + t.Run("tx priority is zero, regardless of fees", func(t *testing.T) { + tx, err := testutils.CreateTx(txc, accounts[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1))) require.NoError(t, err) - require.Equal(t, "1,stake", priority.GetTxPriority(nil, tx)) + priority := txp.GetTxPriority(context.Background(), tx) + require.Equal(t, 0, priority) }) - t.Run("test with amt that is not uint64", func(t *testing.T) { - priority := base.DefaultTxPriority() - - amt, ok := math.NewIntFromString(maxUint64) - require.True(t, ok) - tx, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", amt)) + t.Run("tx priorities are always equal", func(t *testing.T) { + tx1, err := testutils.CreateTx(txc, accounts[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1))) require.NoError(t, err) - require.Equal(t, maxUint64+",stake", priority.GetTxPriority(nil, tx)) - - tx2, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1))) + tx2, err := testutils.CreateTx(txc, accounts[1], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(2))) require.NoError(t, err) - require.Equal(t, 1, priority.Compare(priority.GetTxPriority(nil, tx), priority.GetTxPriority(nil, tx2))) - }) - - t.Run("test invalid priorities", func(t *testing.T) { - priority := base.DefaultTxPriority() - - invalidAmount := "a,b" - invalidCoins := "1,stake,2" + priority1 := txp.GetTxPriority(context.Background(), tx1) + priority2 := txp.GetTxPriority(context.Background(), tx2) - require.Equal(t, 0, priority.Compare(invalidAmount, "")) - require.Equal(t, 0, priority.Compare("", invalidCoins)) + require.Equal(t, priority1, priority2) }) - - for _, tc := range testCases { - t.Run(fmt.Sprintf("test with non-tx: %s", tc.name), func(t *testing.T) { - require.Equal(t, "", tc.priority.GetTxPriority(nil, nil)) - }) - - t.Run(fmt.Sprintf("test tx with no fee: %s", tc.name), func(t *testing.T) { - tx, err := testutils.CreateTx(txc, acct[0], 0, 0, nil) - require.NoError(t, err) - - require.Equal(t, "", tc.priority.GetTxPriority(nil, tx)) - }) - - t.Run(fmt.Sprintf("test comparing two tx priorities: %s", tc.name), func(t *testing.T) { - tx1, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1))) - require.NoError(t, err) - - tx2, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(2))) - require.NoError(t, err) - - priority1 := tc.priority.GetTxPriority(nil, tx1) - priority2 := tc.priority.GetTxPriority(nil, tx2) - - require.Equal(t, -1, tc.priority.Compare(priority1, priority2)) - require.Equal(t, 1, tc.priority.Compare(priority2, priority1)) - require.Equal(t, 0, tc.priority.Compare(priority2, priority2)) - }) - - t.Run(fmt.Sprintf("test comparing two tx priorities with nil: %s", tc.name), func(t *testing.T) { - tx1, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1))) - require.NoError(t, err) - - priority1 := tc.priority.GetTxPriority(nil, tx1) - - require.Equal(t, 1, tc.priority.Compare(priority1, "")) - require.Equal(t, -1, tc.priority.Compare("", priority1)) - require.Equal(t, 0, tc.priority.Compare("", "")) - }) - - t.Run(fmt.Sprintf("test with multiple fee coins: %s", tc.name), func(t *testing.T) { - tx, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1)), sdk.NewCoin("atom", math.NewInt(2))) - require.NoError(t, err) - - tx2, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(2)), sdk.NewCoin("atom", math.NewInt(3))) - require.NoError(t, err) - - priority1 := tc.priority.GetTxPriority(nil, tx) - priority2 := tc.priority.GetTxPriority(nil, tx2) - - require.Equal(t, -1, tc.priority.Compare(priority1, priority2)) - require.Equal(t, 1, tc.priority.Compare(priority2, priority1)) - require.Equal(t, 0, tc.priority.Compare(priority2, priority2)) - }) - - t.Run(fmt.Sprintf("test with multiple different fee coins: %s", tc.name), func(t *testing.T) { - tx1, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1)), sdk.NewCoin("atom", math.NewInt(2)), sdk.NewCoin("btc", math.NewInt(3))) - require.NoError(t, err) - - tx2, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(2)), sdk.NewCoin("eth", math.NewInt(3))) - require.NoError(t, err) - - priority1 := tc.priority.GetTxPriority(nil, tx1) - priority2 := tc.priority.GetTxPriority(nil, tx2) - - require.Equal(t, 0, tc.priority.Compare(priority1, priority2)) - - tx3, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(2)), sdk.NewCoin("osmo", math.NewInt(3)), sdk.NewCoin("btc", math.NewInt(3))) - require.NoError(t, err) - - priority3 := tc.priority.GetTxPriority(nil, tx3) - - require.Equal(t, 0, tc.priority.Compare(priority3, priority1)) - }) - - t.Run(fmt.Sprintf("one is nil, and the other isn't: %s", tc.name), func(t *testing.T) { - tx1, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1)), sdk.NewCoin("atom", math.NewInt(2)), sdk.NewCoin("btc", math.NewInt(3))) - require.NoError(t, err) - - tx2, err := testutils.CreateTx(txc, acct[0], 0, 0, nil) - require.NoError(t, err) - - priority1 := tc.priority.GetTxPriority(nil, tx1) - priority2 := tc.priority.GetTxPriority(nil, tx2) - - require.Equal(t, 1, tc.priority.Compare(priority1, priority2)) - require.Equal(t, -1, tc.priority.Compare(priority2, priority1)) - require.Equal(t, 0, tc.priority.Compare(priority2, priority2)) - }) - - t.Run(fmt.Sprintf("incorrectly ordered fee tokens: %s", tc.name), func(t *testing.T) { - tx1, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1)), sdk.NewCoin("atom", math.NewInt(2)), sdk.NewCoin("btc", math.NewInt(3))) - require.NoError(t, err) - - tx2, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("atom", math.NewInt(2)), sdk.NewCoin("stake", math.NewInt(1)), sdk.NewCoin("btc", math.NewInt(3))) - require.NoError(t, err) - - priority1 := tc.priority.GetTxPriority(nil, tx1) - priority2 := tc.priority.GetTxPriority(nil, tx2) - - require.Equal(t, tc.priority.Compare(priority1, priority2), 0) - }) - - t.Run(fmt.Sprintf("IBC tokens: %s", tc.name), func(t *testing.T) { - tx1, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", math.NewInt(1))) - require.NoError(t, err) - - tx2, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", math.NewInt(2))) - require.NoError(t, err) - - priority1 := tc.priority.GetTxPriority(nil, tx1) - priority2 := tc.priority.GetTxPriority(nil, tx2) - - require.Equal(t, -1, tc.priority.Compare(priority1, priority2)) - require.Equal(t, 1, tc.priority.Compare(priority2, priority1)) - require.Equal(t, 0, tc.priority.Compare(priority2, priority2)) - }) - } -} - -func BenchmarkDefaultTxPriority(b *testing.B) { - acct := testutils.RandomAccounts(rand.New(rand.NewSource(1)), 1) - txc := testutils.CreateTestEncodingConfig().TxConfig - - priority := base.DefaultTxPriority() - - tx1, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1)), sdk.NewCoin("atom", math.NewInt(2)), sdk.NewCoin("btc", math.NewInt(3))) - require.NoError(b, err) - - tx2, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(2)), sdk.NewCoin("eth", math.NewInt(3)), sdk.NewCoin("btc", math.NewInt(4))) - require.NoError(b, err) - - for i := 0; i < b.N; i++ { - priority.Compare(priority.GetTxPriority(nil, tx1), priority.GetTxPriority(nil, tx2)) - } -} - -func BenchmarkDeprecatedTxPriority(b *testing.B) { - // ignore setup - acct := testutils.RandomAccounts(rand.New(rand.NewSource(1)), 1) - txc := testutils.CreateTestEncodingConfig().TxConfig - - priority := base.DeprecatedTxPriority() - - tx1, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(1)), sdk.NewCoin("atom", math.NewInt(2)), sdk.NewCoin("btc", math.NewInt(3))) - require.NoError(b, err) - - tx2, err := testutils.CreateTx(txc, acct[0], 0, 0, nil, sdk.NewCoin("stake", math.NewInt(2)), sdk.NewCoin("eth", math.NewInt(3)), sdk.NewCoin("btc", math.NewInt(4))) - require.NoError(b, err) - // start timer - for i := 0; i < b.N; i++ { - priority.Compare(priority.GetTxPriority(nil, tx1), priority.GetTxPriority(nil, tx2)) - } } diff --git a/lanes/base/abci_test.go b/lanes/base/abci_test.go index 10e9bb82..39679eb2 100644 --- a/lanes/base/abci_test.go +++ b/lanes/base/abci_test.go @@ -292,8 +292,8 @@ func (s *BaseTestSuite) TestPrepareLane() { s.Run("should order transactions correctly in the proposal (with different insertion)", func() { tx1, err := testutils.CreateRandomTx( s.encodingConfig.TxConfig, - s.accounts[0], - 0, + s.accounts[1], + 1, 1, 0, 1, @@ -961,7 +961,7 @@ func (s *BaseTestSuite) TestProcessLane() { s.Require().Equal(encodedTxs, finalProposal.Txs) }) - s.Run("should not accept a proposal with transactions that are not in the correct order fee wise", func() { + s.Run("should accept a proposal with transactions that are in any order fee wise", func() { tx1, err := testutils.CreateRandomTx( s.encodingConfig.TxConfig, s.accounts[0], @@ -998,8 +998,8 @@ func (s *BaseTestSuite) TestProcessLane() { ) txsFromLane, remainingTxs, err := base.NewDefaultProposalHandler(lane).ProcessLaneHandler()(s.ctx, proposal) - s.Require().Error(err) - s.Require().Len(txsFromLane, 0) + s.Require().NoError(err) + s.Require().Len(txsFromLane, 2) s.Require().Len(remainingTxs, 0) emptyProposal := proposals.NewProposal( @@ -1009,7 +1009,7 @@ func (s *BaseTestSuite) TestProcessLane() { ) _, err = lane.ProcessLane(s.ctx, emptyProposal, proposal, block.NoOpProcessLanesHandler()) - s.Require().Error(err) + s.Require().NoError(err) }) s.Run("should not accept proposal where transactions from lane are not contiguous from the start", func() { diff --git a/lanes/base/mempool_test.go b/lanes/base/mempool_test.go index 6913c977..8fd4abe0 100644 --- a/lanes/base/mempool_test.go +++ b/lanes/base/mempool_test.go @@ -95,7 +95,7 @@ func (s *BaseTestSuite) TestCompareTxPriority() { s.Require().Error(err) }) - s.Run("should return 1 when the first tx has a higher priority", func() { + s.Run("should return 0 when the first tx has a higher fee", func() { tx1, err := testutils.CreateRandomTx( s.encodingConfig.TxConfig, s.accounts[0], @@ -120,12 +120,12 @@ func (s *BaseTestSuite) TestCompareTxPriority() { cmp, err := lane.Compare(sdk.Context{}, tx1, tx2) s.Require().NoError(err) - s.Require().Equal(1, cmp) + s.Require().Equal(0, cmp) }) } func (s *BaseTestSuite) TestInsert() { - mempool := base.NewMempool[string](base.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), signer_extraction.NewDefaultAdapter(), 3) + mempool := base.NewMempool(base.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), signer_extraction.NewDefaultAdapter(), 3) s.Run("should be able to insert a transaction", func() { tx, err := testutils.CreateRandomTx( @@ -180,7 +180,7 @@ func (s *BaseTestSuite) TestInsert() { } func (s *BaseTestSuite) TestRemove() { - mempool := base.NewMempool[string](base.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), signer_extraction.NewDefaultAdapter(), 3) + mempool := base.NewMempool(base.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), signer_extraction.NewDefaultAdapter(), 3) s.Run("should be able to remove a transaction", func() { tx, err := testutils.CreateRandomTx( @@ -220,11 +220,11 @@ func (s *BaseTestSuite) TestRemove() { func (s *BaseTestSuite) TestSelect() { s.Run("should be able to select transactions in the correct order", func() { - mempool := base.NewMempool[string](base.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), signer_extraction.NewDefaultAdapter(), 3) + mempool := base.NewMempool(base.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), signer_extraction.NewDefaultAdapter(), 3) tx1, err := testutils.CreateRandomTx( s.encodingConfig.TxConfig, - s.accounts[0], + s.accounts[1], 0, 0, 0, @@ -236,7 +236,7 @@ func (s *BaseTestSuite) TestSelect() { tx2, err := testutils.CreateRandomTx( s.encodingConfig.TxConfig, s.accounts[1], - 0, + 1, 0, 0, 0, @@ -252,16 +252,16 @@ func (s *BaseTestSuite) TestSelect() { // Check that the transactions are in the correct order iterator := mempool.Select(sdk.Context{}, nil) s.Require().NotNil(iterator) - s.Require().Equal(tx2, iterator.Tx()) + s.Require().Equal(tx1, iterator.Tx()) // Check the second transaction iterator = iterator.Next() s.Require().NotNil(iterator) - s.Require().Equal(tx1, iterator.Tx()) + s.Require().Equal(tx2, iterator.Tx()) }) s.Run("should be able to select a single transaction", func() { - mempool := base.NewMempool[string](base.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), signer_extraction.NewDefaultAdapter(), 3) + mempool := base.NewMempool(base.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), signer_extraction.NewDefaultAdapter(), 3) tx1, err := testutils.CreateRandomTx( s.encodingConfig.TxConfig, diff --git a/testutils/mempool/mempool.go b/testutils/mempool/mempool.go index c94524de..47588722 100644 --- a/testutils/mempool/mempool.go +++ b/testutils/mempool/mempool.go @@ -37,7 +37,7 @@ func CreateMempool() *block.LanedMempool { MaxBlockSpace: math.LegacyMustNewDecFromStr("0.3"), MaxTxs: 0, // unlimited } - freeLane := free.NewFreeLane[string](freeConfig, base.DefaultTxPriority(), free.DefaultMatchHandler()) + freeLane := free.NewFreeLane(freeConfig, base.DefaultTxPriority(), free.DefaultMatchHandler()) defaultConfig := base.LaneConfig{ SignerExtractor: signerExtractor, diff --git a/testutils/utils.go b/testutils/utils.go index 776f5e25..42ba0a14 100644 --- a/testutils/utils.go +++ b/testutils/utils.go @@ -1,6 +1,7 @@ package testutils import ( + "fmt" "math/rand" "testing" @@ -212,6 +213,49 @@ func CreateTxWithSigners(txCfg client.TxConfig, nonce, timeout uint64, signers [ return txBuilder.GetTx(), nil } +func CreateRandomTxMultipleSigners(txCfg client.TxConfig, accounts []Account, nonce, numberMsgs, timeout uint64, gasLimit uint64, fees ...sdk.Coin) (authsigning.Tx, error) { + if len(accounts) == 0 { + return nil, fmt.Errorf("no accounts provided") + } + + msgs := make([]sdk.Msg, numberMsgs) + for i := 0; i < int(numberMsgs); i++ { + msgs[i] = &banktypes.MsgSend{ + FromAddress: accounts[0].Address.String(), + ToAddress: accounts[0].Address.String(), + } + } + + txBuilder := txCfg.NewTxBuilder() + if err := txBuilder.SetMsgs(msgs...); err != nil { + return nil, err + } + + sigs := make([]signing.SignatureV2, len(accounts)) + for i, acc := range accounts { + sigs[i] = signing.SignatureV2{ + PubKey: acc.PrivKey.PubKey(), + Data: &signing.SingleSignatureData{ + SignMode: signing.SignMode_SIGN_MODE_DIRECT, + Signature: nil, + }, + Sequence: nonce, + } + } + + if err := txBuilder.SetSignatures(sigs...); err != nil { + return nil, err + } + + txBuilder.SetTimeoutHeight(timeout) + + txBuilder.SetFeeAmount(fees) + + txBuilder.SetGasLimit(gasLimit) + + return txBuilder.GetTx(), nil +} + func CreateAuctionTx(txCfg client.TxConfig, bidder Account, bid sdk.Coin, nonce, timeout uint64, signers []Account, gasLimit uint64) (sdk.Tx, []sdk.Tx, error) { bidMsg := &auctiontypes.MsgAuctionBid{ Bidder: bidder.Address.String(),