From 8b37a0a38cfcfb0dbac07ad775669eac3d99e553 Mon Sep 17 00:00:00 2001 From: David Terpay Date: Tue, 15 Aug 2023 16:42:44 -0400 Subject: [PATCH] more clean up --- abci/abci_test.go | 4 +- block/constructor/abci.go | 8 +- block/constructor/handlers.go | 6 +- block/constructor/lane.go | 36 +- block/lanes/base/abci_test.go | 547 ------------------------------- block/lanes/base/base_test.go | 32 -- block/lanes/base/mempool_test.go | 240 -------------- lanes/base/lane.go | 4 +- lanes/free/lane.go | 4 +- lanes/mev/lane.go | 4 +- 10 files changed, 34 insertions(+), 851 deletions(-) delete mode 100644 block/lanes/base/abci_test.go delete mode 100644 block/lanes/base/base_test.go delete mode 100644 block/lanes/base/mempool_test.go diff --git a/abci/abci_test.go b/abci/abci_test.go index 23d8a73..36ff22b 100644 --- a/abci/abci_test.go +++ b/abci/abci_test.go @@ -760,7 +760,7 @@ func (s *ProposalsTestSuite) setUpFreeLane(maxBlockSpace math.LegacyDec, expecte return free.NewFreeLane(cfg, constructor.DefaultTxPriority(), free.DefaultMatchHandler()) } -func (s *ProposalsTestSuite) setUpPanicLane(maxBlockSpace math.LegacyDec) *constructor.LaneConstructor[string] { +func (s *ProposalsTestSuite) setUpPanicLane(maxBlockSpace math.LegacyDec) *constructor.LaneConstructor { cfg := constructor.LaneConfig{ Logger: log.NewTestLogger(s.T()), TxEncoder: s.encodingConfig.TxConfig.TxEncoder(), @@ -768,7 +768,7 @@ func (s *ProposalsTestSuite) setUpPanicLane(maxBlockSpace math.LegacyDec) *const MaxBlockSpace: maxBlockSpace, } - lane := constructor.NewLaneConstructor[string]( + lane := constructor.NewLaneConstructor( cfg, "panic", constructor.NewMempool[string](constructor.DefaultTxPriority(), cfg.TxEncoder, 0), diff --git a/block/constructor/abci.go b/block/constructor/abci.go index db07807..cc80fea 100644 --- a/block/constructor/abci.go +++ b/block/constructor/abci.go @@ -10,7 +10,7 @@ import ( // lane respecting the selection logic of the prepareLaneHandler. It will then update the partial // proposal with the selected transactions. If the proposal is unable to be updated, we return an // error. The proposal will only be modified if it passes all of the invarient checks. -func (l *LaneConstructor[C]) PrepareLane( +func (l *LaneConstructor) PrepareLane( ctx sdk.Context, proposal block.BlockProposal, maxTxBytes int64, @@ -40,7 +40,7 @@ func (l *LaneConstructor[C]) PrepareLane( // CheckOrder checks that the ordering logic of the lane is respected given the set of transactions // in the block proposal. If the ordering logic is not respected, we return an error. -func (l *LaneConstructor[C]) CheckOrder(ctx sdk.Context, txs []sdk.Tx) error { +func (l *LaneConstructor) CheckOrder(ctx sdk.Context, txs []sdk.Tx) error { return l.checkOrderHandler(ctx, txs) } @@ -48,7 +48,7 @@ func (l *LaneConstructor[C]) CheckOrder(ctx sdk.Context, txs []sdk.Tx) error { // the verification logic of the lane (processLaneHandler). If the transactions are valid, we // return the transactions that do not belong to this lane to the next lane. If the transactions // are invalid, we return an error. -func (l *LaneConstructor[C]) ProcessLane(ctx sdk.Context, txs []sdk.Tx, next block.ProcessLanesHandler) (sdk.Context, error) { +func (l *LaneConstructor) ProcessLane(ctx sdk.Context, txs []sdk.Tx, next block.ProcessLanesHandler) (sdk.Context, error) { remainingTxs, err := l.processLaneHandler(ctx, txs) if err != nil { return ctx, err @@ -59,7 +59,7 @@ func (l *LaneConstructor[C]) ProcessLane(ctx sdk.Context, txs []sdk.Tx, next blo // AnteVerifyTx verifies that the transaction is valid respecting the ante verification logic of // of the antehandler chain. -func (l *LaneConstructor[C]) AnteVerifyTx(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) { +func (l *LaneConstructor) AnteVerifyTx(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) { if l.cfg.AnteHandler != nil { return l.cfg.AnteHandler(ctx, tx, simulate) } diff --git a/block/constructor/handlers.go b/block/constructor/handlers.go index d07c61d..a927d79 100644 --- a/block/constructor/handlers.go +++ b/block/constructor/handlers.go @@ -12,7 +12,7 @@ import ( // selects all transactions in the mempool that are valid and not already in the partial // proposal. It will continue to reap transactions until the maximum block space for this // lane has been reached. Additionally, any transactions that are invalid will be returned. -func (l *LaneConstructor[C]) DefaultPrepareLaneHandler() block.PrepareLaneHandler { +func (l *LaneConstructor) DefaultPrepareLaneHandler() block.PrepareLaneHandler { return func(ctx sdk.Context, proposal block.BlockProposal, maxTxBytes int64) ([][]byte, []sdk.Tx, error) { var ( totalSize int64 @@ -96,7 +96,7 @@ func (l *LaneConstructor[C]) DefaultPrepareLaneHandler() block.PrepareLaneHandle // fails to verify, the entire proposal is rejected. If the handler comes across a transaction // that does not match the lane's matcher, it will return the remaining transactions in the // proposal. -func (l *LaneConstructor[C]) DefaultProcessLaneHandler() block.ProcessLaneHandler { +func (l *LaneConstructor) DefaultProcessLaneHandler() block.ProcessLaneHandler { return func(ctx sdk.Context, txs []sdk.Tx) ([]sdk.Tx, error) { var err error @@ -123,7 +123,7 @@ func (l *LaneConstructor[C]) DefaultProcessLaneHandler() block.ProcessLaneHandle // lane. // 2. Transactions that belong to other lanes cannot be interleaved with transactions that // belong to this lane. -func (l *LaneConstructor[C]) DefaultCheckOrderHandler() block.CheckOrderHandler { +func (l *LaneConstructor) DefaultCheckOrderHandler() block.CheckOrderHandler { return func(ctx sdk.Context, txs []sdk.Tx) error { seenOtherLaneTx := false diff --git a/block/constructor/lane.go b/block/constructor/lane.go index 559e45e..2cf49e6 100644 --- a/block/constructor/lane.go +++ b/block/constructor/lane.go @@ -9,12 +9,14 @@ import ( "github.com/skip-mev/pob/block" ) +var _ block.Lane = (*LaneConstructor)(nil) + // LaneConstructor is a generic implementation of a lane. It is meant to be used // as a base for other lanes to be built on top of. It provides a default // implementation of the MatchHandler, PrepareLaneHandler, ProcessLaneHandler, // and CheckOrderHandler. To extend this lane, you must either utilize the default // handlers or construct your own that you pass into the constructor/setters. -type LaneConstructor[C comparable] struct { +type LaneConstructor struct { // cfg stores functionality required to encode/decode transactions, maintains how // many transactions are allowed in this lane's mempool, and the amount of block // space this lane is allowed to consume. @@ -49,13 +51,13 @@ type LaneConstructor[C comparable] struct { // NewLaneConstructor returns a new lane constructor. When creating this lane, the type // of the lane must be specified. The type of the lane is directly associated with the // type of the mempool that is used to store transactions that are waiting to be processed. -func NewLaneConstructor[C comparable]( +func NewLaneConstructor( cfg LaneConfig, laneName string, laneMempool block.LaneMempool, matchHandlerFn block.MatchHandler, -) *LaneConstructor[C] { - lane := &LaneConstructor[C]{ +) *LaneConstructor { + lane := &LaneConstructor{ cfg: cfg, laneName: laneName, LaneMempool: laneMempool, @@ -71,7 +73,7 @@ func NewLaneConstructor[C comparable]( // ValidateBasic ensures that the lane was constructed properly. In the case that // the lane was not constructed with proper handlers, default handlers are set. -func (l *LaneConstructor[C]) ValidateBasic() error { +func (l *LaneConstructor) ValidateBasic() error { if err := l.cfg.ValidateBasic(); err != nil { return err } @@ -106,7 +108,7 @@ func (l *LaneConstructor[C]) ValidateBasic() error { // SetPrepareLaneHandler sets the prepare lane handler for the lane. This handler // is called when a new proposal is being requested and the lane needs to submit // transactions it wants included in the block. -func (l *LaneConstructor[C]) SetPrepareLaneHandler(prepareLaneHandler block.PrepareLaneHandler) { +func (l *LaneConstructor) SetPrepareLaneHandler(prepareLaneHandler block.PrepareLaneHandler) { if prepareLaneHandler == nil { panic("prepare lane handler cannot be nil") } @@ -118,7 +120,7 @@ func (l *LaneConstructor[C]) SetPrepareLaneHandler(prepareLaneHandler block.Prep // is called when a new proposal is being verified and the lane needs to verify // that the transactions included in the proposal are valid respecting the verification // logic of the lane. -func (l *LaneConstructor[C]) SetProcessLaneHandler(processLaneHandler block.ProcessLaneHandler) { +func (l *LaneConstructor) SetProcessLaneHandler(processLaneHandler block.ProcessLaneHandler) { if processLaneHandler == nil { panic("process lane handler cannot be nil") } @@ -130,7 +132,7 @@ func (l *LaneConstructor[C]) SetProcessLaneHandler(processLaneHandler block.Proc // is called when a new proposal is being verified and the lane needs to verify // that the transactions included in the proposal respect the ordering rules of // the lane and does not include transactions from other lanes. -func (l *LaneConstructor[C]) SetCheckOrderHandler(checkOrderHandler block.CheckOrderHandler) { +func (l *LaneConstructor) SetCheckOrderHandler(checkOrderHandler block.CheckOrderHandler) { if checkOrderHandler == nil { panic("check order handler cannot be nil") } @@ -142,14 +144,14 @@ func (l *LaneConstructor[C]) SetCheckOrderHandler(checkOrderHandler block.CheckO // function first determines if the transaction matches the lane and then checks // if the transaction is on the ignore list. If the transaction is on the ignore // list, it returns false. -func (l *LaneConstructor[C]) Match(ctx sdk.Context, tx sdk.Tx) bool { +func (l *LaneConstructor) Match(ctx sdk.Context, tx sdk.Tx) bool { return l.matchHandler(ctx, tx) && !l.CheckIgnoreList(ctx, tx) } // CheckIgnoreList returns true if the transaction is on the ignore list. The ignore // list is utilized to prevent transactions that should be considered in other lanes // from being considered from this lane. -func (l *LaneConstructor[C]) CheckIgnoreList(ctx sdk.Context, tx sdk.Tx) bool { +func (l *LaneConstructor) CheckIgnoreList(ctx sdk.Context, tx sdk.Tx) bool { for _, lane := range l.cfg.IgnoreList { if lane.Match(ctx, tx) { return true @@ -160,38 +162,38 @@ func (l *LaneConstructor[C]) CheckIgnoreList(ctx sdk.Context, tx sdk.Tx) bool { } // Name returns the name of the lane. -func (l *LaneConstructor[C]) Name() string { +func (l *LaneConstructor) Name() string { return l.laneName } // SetIgnoreList sets the ignore list for the lane. The ignore list is a list // of lanes that the lane should ignore when processing transactions. -func (l *LaneConstructor[C]) SetIgnoreList(lanes []block.Lane) { +func (l *LaneConstructor) SetIgnoreList(lanes []block.Lane) { l.cfg.IgnoreList = lanes } // SetAnteHandler sets the ante handler for the lane. -func (l *LaneConstructor[C]) SetAnteHandler(anteHandler sdk.AnteHandler) { +func (l *LaneConstructor) SetAnteHandler(anteHandler sdk.AnteHandler) { l.cfg.AnteHandler = anteHandler } // Logger returns the logger for the lane. -func (l *LaneConstructor[C]) Logger() log.Logger { +func (l *LaneConstructor) Logger() log.Logger { return l.cfg.Logger } // TxDecoder returns the tx decoder for the lane. -func (l *LaneConstructor[C]) TxDecoder() sdk.TxDecoder { +func (l *LaneConstructor) TxDecoder() sdk.TxDecoder { return l.cfg.TxDecoder } // TxEncoder returns the tx encoder for the lane. -func (l *LaneConstructor[C]) TxEncoder() sdk.TxEncoder { +func (l *LaneConstructor) TxEncoder() sdk.TxEncoder { return l.cfg.TxEncoder } // GetMaxBlockSpace returns the maximum amount of block space that the lane is // allowed to consume as a percentage of the total block space. -func (l *LaneConstructor[C]) GetMaxBlockSpace() math.LegacyDec { +func (l *LaneConstructor) GetMaxBlockSpace() math.LegacyDec { return l.cfg.MaxBlockSpace } diff --git a/block/lanes/base/abci_test.go b/block/lanes/base/abci_test.go deleted file mode 100644 index d5c054d..0000000 --- a/block/lanes/base/abci_test.go +++ /dev/null @@ -1,547 +0,0 @@ -package base_test - -import ( - "crypto/sha256" - "encoding/hex" - "fmt" - - "cosmossdk.io/log" - "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/skip-mev/pob/blockbuster" - "github.com/skip-mev/pob/blockbuster/lanes/base" - "github.com/skip-mev/pob/blockbuster/utils/mocks" - testutils "github.com/skip-mev/pob/testutils" -) - -func (s *BaseTestSuite) TestPrepareLane() { - s.Run("should not build a proposal when amount configured to lane is too small", func() { - // Create a basic transaction that should not in the proposal - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)), - ) - s.Require().NoError(err) - - // Create a lane with a max block space of 1 but a proposal that is smaller than the tx - expectedExecution := map[sdk.Tx]bool{ - tx: true, - } - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), expectedExecution) - - // Insert the transaction into the lane - s.Require().NoError(lane.Insert(sdk.Context{}, tx)) - - txBz, err := s.encodingConfig.TxConfig.TxEncoder()(tx) - s.Require().NoError(err) - - // Create a proposal - maxTxBytes := int64(len(txBz) - 1) - proposal, err := lane.PrepareLane(sdk.Context{}, blockbuster.NewProposal(maxTxBytes), maxTxBytes, blockbuster.NoOpPrepareLanesHandler()) - s.Require().NoError(err) - - // Ensure the proposal is empty - s.Require().Equal(0, proposal.GetNumTxs()) - s.Require().Equal(int64(0), proposal.GetTotalTxBytes()) - }) - - s.Run("should not build a proposal when box space configured to lane is too small", func() { - // Create a basic transaction that should not in the proposal - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)), - ) - s.Require().NoError(err) - - // Create a lane with a max block space of 1 but a proposal that is smaller than the tx - expectedExecution := map[sdk.Tx]bool{ - tx: true, - } - lane := s.initLane(math.LegacyMustNewDecFromStr("0.000001"), expectedExecution) - - // Insert the transaction into the lane - s.Require().NoError(lane.Insert(sdk.Context{}, tx)) - - txBz, err := s.encodingConfig.TxConfig.TxEncoder()(tx) - s.Require().NoError(err) - - // Create a proposal - maxTxBytes := int64(len(txBz)) - proposal, err := lane.PrepareLane(sdk.Context{}, blockbuster.NewProposal(maxTxBytes), maxTxBytes, blockbuster.NoOpPrepareLanesHandler()) - s.Require().Error(err) - - // Ensure the proposal is empty - s.Require().Equal(0, proposal.GetNumTxs()) - s.Require().Equal(int64(0), proposal.GetTotalTxBytes()) - }) - - s.Run("should be able to build a proposal with a tx that just fits in", func() { - // Create a basic transaction that should not in the proposal - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)), - ) - s.Require().NoError(err) - - // Create a lane with a max block space of 1 but a proposal that is smaller than the tx - expectedExecution := map[sdk.Tx]bool{ - tx: true, - } - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), expectedExecution) - - // Insert the transaction into the lane - s.Require().NoError(lane.Insert(sdk.Context{}, tx)) - - txBz, err := s.encodingConfig.TxConfig.TxEncoder()(tx) - s.Require().NoError(err) - - // Create a proposal - maxTxBytes := int64(len(txBz)) - proposal, err := lane.PrepareLane(sdk.Context{}, blockbuster.NewProposal(maxTxBytes), maxTxBytes, blockbuster.NoOpPrepareLanesHandler()) - s.Require().NoError(err) - - // Ensure the proposal is not empty and contains the transaction - s.Require().Equal(1, proposal.GetNumTxs()) - s.Require().Equal(maxTxBytes, proposal.GetTotalTxBytes()) - s.Require().Equal(txBz, proposal.GetTxs()[0]) - }) - - s.Run("should not build a proposal with a that fails verify tx", func() { - // Create a basic transaction that should not in the proposal - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)), - ) - s.Require().NoError(err) - - // Create a lane with a max block space of 1 but a proposal that is smaller than the tx - expectedExecution := map[sdk.Tx]bool{ - tx: false, - } - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), expectedExecution) - - // Insert the transaction into the lane - s.Require().NoError(lane.Insert(sdk.Context{}, tx)) - - // Create a proposal - txBz, err := s.encodingConfig.TxConfig.TxEncoder()(tx) - s.Require().NoError(err) - - maxTxBytes := int64(len(txBz)) - proposal, err := lane.PrepareLane(sdk.Context{}, blockbuster.NewProposal(maxTxBytes), maxTxBytes, blockbuster.NoOpPrepareLanesHandler()) - s.Require().NoError(err) - - // Ensure the proposal is empty - s.Require().Equal(0, proposal.GetNumTxs()) - s.Require().Equal(int64(0), proposal.GetTotalTxBytes()) - - // Ensure the transaction is removed from the lane - s.Require().False(lane.Contains(tx)) - s.Require().Equal(0, lane.CountTx()) - }) - - s.Run("should order transactions correctly in the proposal", func() { - // Create a basic transaction that should not in the proposal - tx1, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(2)), - ) - s.Require().NoError(err) - - tx2, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[1], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)), - ) - s.Require().NoError(err) - - // Create a lane with a max block space of 1 but a proposal that is smaller than the tx - expectedExecution := map[sdk.Tx]bool{ - tx1: true, - tx2: true, - } - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), expectedExecution) - - // Insert the transaction into the lane - s.Require().NoError(lane.Insert(sdk.Context{}, tx1)) - s.Require().NoError(lane.Insert(sdk.Context{}, tx2)) - - txBz1, err := s.encodingConfig.TxConfig.TxEncoder()(tx1) - s.Require().NoError(err) - - txBz2, err := s.encodingConfig.TxConfig.TxEncoder()(tx2) - s.Require().NoError(err) - - maxTxBytes := int64(len(txBz1)) + int64(len(txBz2)) - proposal, err := lane.PrepareLane(sdk.Context{}, blockbuster.NewProposal(maxTxBytes), maxTxBytes, blockbuster.NoOpPrepareLanesHandler()) - s.Require().NoError(err) - - // Ensure the proposal is ordered correctly - s.Require().Equal(2, proposal.GetNumTxs()) - s.Require().Equal(maxTxBytes, proposal.GetTotalTxBytes()) - s.Require().Equal([][]byte{txBz1, txBz2}, proposal.GetTxs()) - }) - - s.Run("should order transactions correctly in the proposal (with different insertion)", func() { - // Create a basic transaction that should not in the proposal - tx1, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)), - ) - s.Require().NoError(err) - - tx2, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[1], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(2)), - ) - s.Require().NoError(err) - - // Create a lane with a max block space of 1 but a proposal that is smaller than the tx - expectedExecution := map[sdk.Tx]bool{ - tx1: true, - tx2: true, - } - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), expectedExecution) - - // Insert the transaction into the lane - s.Require().NoError(lane.Insert(sdk.Context{}, tx1)) - s.Require().NoError(lane.Insert(sdk.Context{}, tx2)) - - txBz1, err := s.encodingConfig.TxConfig.TxEncoder()(tx1) - s.Require().NoError(err) - - txBz2, err := s.encodingConfig.TxConfig.TxEncoder()(tx2) - s.Require().NoError(err) - - maxTxBytes := int64(len(txBz1)) + int64(len(txBz2)) - proposal, err := lane.PrepareLane(sdk.Context{}, blockbuster.NewProposal(maxTxBytes), maxTxBytes, blockbuster.NoOpPrepareLanesHandler()) - s.Require().NoError(err) - - // Ensure the proposal is ordered correctly - s.Require().Equal(2, proposal.GetNumTxs()) - s.Require().Equal(maxTxBytes, proposal.GetTotalTxBytes()) - s.Require().Equal([][]byte{txBz2, txBz1}, proposal.GetTxs()) - }) - - s.Run("should include tx that fits in proposal when other does not", func() { - // Create a basic transaction that should not in the proposal - tx1, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)), - ) - s.Require().NoError(err) - - tx2, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[1], - 0, - 10, // This tx is too large to fit in the proposal - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)), - ) - s.Require().NoError(err) - - // Create a lane with a max block space of 1 but a proposal that is smaller than the tx - expectedExecution := map[sdk.Tx]bool{ - tx1: true, - tx2: true, - } - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), expectedExecution) - - // Insert the transaction into the lane - s.Require().NoError(lane.Insert(sdk.Context{}.WithPriority(10), tx1)) - s.Require().NoError(lane.Insert(sdk.Context{}.WithPriority(5), tx2)) - - txBz1, err := s.encodingConfig.TxConfig.TxEncoder()(tx1) - s.Require().NoError(err) - - txBz2, err := s.encodingConfig.TxConfig.TxEncoder()(tx2) - s.Require().NoError(err) - - maxTxBytes := int64(len(txBz1)) + int64(len(txBz2)) - 1 - proposal, err := lane.PrepareLane(sdk.Context{}, blockbuster.NewProposal(maxTxBytes), maxTxBytes, blockbuster.NoOpPrepareLanesHandler()) - s.Require().NoError(err) - - // Ensure the proposal is ordered correctly - s.Require().Equal(1, proposal.GetNumTxs()) - s.Require().Equal(int64(len(txBz1)), proposal.GetTotalTxBytes()) - s.Require().Equal([][]byte{txBz1}, proposal.GetTxs()) - }) -} - -func (s *BaseTestSuite) TestProcessLane() { - s.Run("should accept a proposal with valid transactions", func() { - tx1, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - ) - s.Require().NoError(err) - - proposal := []sdk.Tx{ - tx1, - } - - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), map[sdk.Tx]bool{ - tx1: true, - }) - - _, err = lane.ProcessLane(sdk.Context{}, proposal, blockbuster.NoOpProcessLanesHandler()) - s.Require().NoError(err) - }) - - s.Run("should not accept a proposal with invalid transactions", func() { - tx1, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - ) - s.Require().NoError(err) - - proposal := []sdk.Tx{ - tx1, - } - - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), map[sdk.Tx]bool{ - tx1: false, - }) - - _, err = lane.ProcessLane(sdk.Context{}, proposal, blockbuster.NoOpProcessLanesHandler()) - s.Require().Error(err) - }) - - s.Run("should not accept a proposal with some invalid transactions", func() { - tx1, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - ) - s.Require().NoError(err) - - tx2, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[1], - 0, - 1, - 0, - ) - s.Require().NoError(err) - - tx3, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[2], - 0, - 1, - 0, - ) - s.Require().NoError(err) - - proposal := []sdk.Tx{ - tx1, - tx2, - tx3, - } - - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), map[sdk.Tx]bool{ - tx1: true, - tx2: false, - tx3: true, - }) - - _, err = lane.ProcessLane(sdk.Context{}, proposal, blockbuster.NoOpProcessLanesHandler()) - s.Require().Error(err) - }) -} - -func (s *BaseTestSuite) TestCheckOrder() { - s.Run("should accept proposal with transactions in correct order", func() { - tx1, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(2)), - ) - s.Require().NoError(err) - - tx2, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[1], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)), - ) - s.Require().NoError(err) - - proposal := []sdk.Tx{ - tx1, - tx2, - } - - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), map[sdk.Tx]bool{ - tx1: true, - tx2: true, - }) - s.Require().NoError(lane.CheckOrder(sdk.Context{}, proposal)) - }) - - s.Run("should not accept a proposal with transactions that are not in the correct order", func() { - tx1, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)), - ) - s.Require().NoError(err) - - tx2, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[1], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(2)), - ) - s.Require().NoError(err) - - proposal := []sdk.Tx{ - tx1, - tx2, - } - - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), map[sdk.Tx]bool{ - tx1: true, - tx2: true, - }) - s.Require().Error(lane.CheckOrder(sdk.Context{}, proposal)) - }) - - s.Run("should not accept a proposal where transactions are out of order relative to other lanes", func() { - tx1, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 2, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)), - ) - s.Require().NoError(err) - - tx2, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[1], - 0, - 1, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(2)), - ) - s.Require().NoError(err) - - mocklane := mocks.NewLane(s.T()) - mocklane.On("Match", sdk.Context{}, tx1).Return(true) - mocklane.On("Match", sdk.Context{}, tx2).Return(false) - - lane := s.initLane(math.LegacyMustNewDecFromStr("1"), nil) - lane.SetIgnoreList([]blockbuster.Lane{mocklane}) - - proposal := []sdk.Tx{ - tx1, - tx2, - } - - s.Require().Error(lane.CheckOrder(sdk.Context{}, proposal)) - }) -} - -func (s *BaseTestSuite) initLane( - maxBlockSpace math.LegacyDec, - expectedExecution map[sdk.Tx]bool, -) *base.DefaultLane { - config := blockbuster.NewBaseLaneConfig( - log.NewTestLogger(s.T()), - s.encodingConfig.TxConfig.TxEncoder(), - s.encodingConfig.TxConfig.TxDecoder(), - s.setUpAnteHandler(expectedExecution), - maxBlockSpace, - ) - - return base.NewDefaultLane(config) -} - -func (s *BaseTestSuite) setUpAnteHandler(expectedExecution map[sdk.Tx]bool) sdk.AnteHandler { - txCache := make(map[string]bool) - for tx, pass := range expectedExecution { - bz, err := s.encodingConfig.TxConfig.TxEncoder()(tx) - s.Require().NoError(err) - - hash := sha256.Sum256(bz) - hashStr := hex.EncodeToString(hash[:]) - txCache[hashStr] = pass - } - - anteHandler := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) { - bz, err := s.encodingConfig.TxConfig.TxEncoder()(tx) - s.Require().NoError(err) - - hash := sha256.Sum256(bz) - hashStr := hex.EncodeToString(hash[:]) - - pass, found := txCache[hashStr] - if !found { - return ctx, fmt.Errorf("tx not found") - } - - if pass { - return ctx, nil - } - - return ctx, fmt.Errorf("tx failed") - } - - return anteHandler -} diff --git a/block/lanes/base/base_test.go b/block/lanes/base/base_test.go deleted file mode 100644 index 7852dac..0000000 --- a/block/lanes/base/base_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package base_test - -import ( - "math/rand" - "testing" - - testutils "github.com/skip-mev/pob/testutils" - "github.com/stretchr/testify/suite" -) - -type BaseTestSuite struct { - suite.Suite - - encodingConfig testutils.EncodingConfig - random *rand.Rand - accounts []testutils.Account - gasTokenDenom string -} - -func TestBaseTestSuite(t *testing.T) { - suite.Run(t, new(BaseTestSuite)) -} - -func (s *BaseTestSuite) SetupTest() { - // Set up basic TX encoding config. - s.encodingConfig = testutils.CreateTestEncodingConfig() - - // Create a few random accounts - s.random = rand.New(rand.NewSource(1)) - s.accounts = testutils.RandomAccounts(s.random, 5) - s.gasTokenDenom = "stake" -} diff --git a/block/lanes/base/mempool_test.go b/block/lanes/base/mempool_test.go deleted file mode 100644 index 4f12e73..0000000 --- a/block/lanes/base/mempool_test.go +++ /dev/null @@ -1,240 +0,0 @@ -package base_test - -import ( - "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/skip-mev/pob/blockbuster" - testutils "github.com/skip-mev/pob/testutils" -) - -func (s *BaseTestSuite) TestGetTxPriority() { - txPriority := blockbuster.DefaultTxPriority() - - s.Run("should be able to get the priority off a normal transaction with fees", func() { - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 0, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)), - ) - s.Require().NoError(err) - - priority := txPriority.GetTxPriority(sdk.Context{}, tx) - s.Require().Equal(sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)).String(), priority) - }) - - s.Run("should not get a priority when the transaction does not have a fee", func() { - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 0, - 0, - ) - s.Require().NoError(err) - - priority := txPriority.GetTxPriority(sdk.Context{}, tx) - s.Require().Equal("", priority) - }) - - s.Run("should get a priority when the gas token is different", func() { - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 0, - 0, - sdk.NewCoin("random", math.NewInt(100)), - ) - s.Require().NoError(err) - - priority := txPriority.GetTxPriority(sdk.Context{}, tx) - s.Require().Equal(sdk.NewCoin("random", math.NewInt(100)).String(), priority) - }) -} - -func (s *BaseTestSuite) TestCompareTxPriority() { - txPriority := blockbuster.DefaultTxPriority() - - s.Run("should return 0 when both priorities are nil", func() { - a := sdk.NewCoin(s.gasTokenDenom, math.NewInt(0)).String() - b := sdk.NewCoin(s.gasTokenDenom, math.NewInt(0)).String() - s.Require().Equal(0, txPriority.Compare(a, b)) - }) - - s.Run("should return 1 when the first priority is greater", func() { - a := sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)).String() - b := sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)).String() - s.Require().Equal(1, txPriority.Compare(a, b)) - }) - - s.Run("should return -1 when the second priority is greater", func() { - a := sdk.NewCoin(s.gasTokenDenom, math.NewInt(1)).String() - b := sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)).String() - s.Require().Equal(-1, txPriority.Compare(a, b)) - }) - - s.Run("should return 0 when both priorities are equal", func() { - a := sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)).String() - b := sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)).String() - s.Require().Equal(0, txPriority.Compare(a, b)) - }) -} - -func (s *BaseTestSuite) TestInsert() { - mempool := blockbuster.NewConstructorMempool[string](blockbuster.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), 3) - - s.Run("should be able to insert a transaction", func() { - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 0, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)), - ) - s.Require().NoError(err) - - err = mempool.Insert(sdk.Context{}, tx) - s.Require().NoError(err) - s.Require().True(mempool.Contains(tx)) - }) - - s.Run("cannot insert more transactions than the max", func() { - for i := 0; i < 3; i++ { - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - uint64(i), - 0, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(int64(100*i))), - ) - s.Require().NoError(err) - - err = mempool.Insert(sdk.Context{}, tx) - s.Require().NoError(err) - s.Require().True(mempool.Contains(tx)) - } - - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 10, - 0, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)), - ) - s.Require().NoError(err) - - err = mempool.Insert(sdk.Context{}, tx) - s.Require().Error(err) - s.Require().False(mempool.Contains(tx)) - }) -} - -func (s *BaseTestSuite) TestRemove() { - mempool := blockbuster.NewConstructorMempool[string](blockbuster.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), 3) - - s.Run("should be able to remove a transaction", func() { - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 0, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)), - ) - s.Require().NoError(err) - - err = mempool.Insert(sdk.Context{}, tx) - s.Require().NoError(err) - s.Require().True(mempool.Contains(tx)) - - mempool.Remove(tx) - s.Require().False(mempool.Contains(tx)) - }) - - s.Run("should not error when removing a transaction that does not exist", func() { - tx, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 0, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)), - ) - s.Require().NoError(err) - - mempool.Remove(tx) - }) -} - -func (s *BaseTestSuite) TestSelect() { - s.Run("should be able to select transactions in the correct order", func() { - mempool := blockbuster.NewConstructorMempool[string](blockbuster.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), 3) - - tx1, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 0, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)), - ) - s.Require().NoError(err) - - tx2, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[1], - 0, - 0, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(200)), - ) - s.Require().NoError(err) - - // Insert the transactions into the mempool - s.Require().NoError(mempool.Insert(sdk.Context{}, tx1)) - s.Require().NoError(mempool.Insert(sdk.Context{}, tx2)) - s.Require().Equal(2, mempool.CountTx()) - - // 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()) - - // Check the second transaction - iterator = iterator.Next() - s.Require().NotNil(iterator) - s.Require().Equal(tx1, iterator.Tx()) - }) - - s.Run("should be able to select a single transaction", func() { - mempool := blockbuster.NewConstructorMempool[string](blockbuster.DefaultTxPriority(), s.encodingConfig.TxConfig.TxEncoder(), 3) - - tx1, err := testutils.CreateRandomTx( - s.encodingConfig.TxConfig, - s.accounts[0], - 0, - 0, - 0, - sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)), - ) - s.Require().NoError(err) - - // Insert the transactions into the mempool - s.Require().NoError(mempool.Insert(sdk.Context{}, tx1)) - s.Require().Equal(1, mempool.CountTx()) - - // Check that the transactions are in the correct order - iterator := mempool.Select(sdk.Context{}, nil) - s.Require().NotNil(iterator) - s.Require().Equal(tx1, iterator.Tx()) - - iterator = iterator.Next() - s.Require().Nil(iterator) - }) -} diff --git a/lanes/base/lane.go b/lanes/base/lane.go index 4e59785..99d0e10 100644 --- a/lanes/base/lane.go +++ b/lanes/base/lane.go @@ -19,12 +19,12 @@ var _ block.Lane = (*DefaultLane)(nil) // CometBFT/Tendermint consensus engine builds and verifies blocks pre SDK version // 0.47.0. type DefaultLane struct { - *constructor.LaneConstructor[string] + *constructor.LaneConstructor } // NewDefaultLane returns a new default lane. func NewDefaultLane(cfg constructor.LaneConfig) *DefaultLane { - lane := constructor.NewLaneConstructor[string]( + lane := constructor.NewLaneConstructor( cfg, LaneName, constructor.NewMempool[string]( diff --git a/lanes/free/lane.go b/lanes/free/lane.go index e29ed27..ba48d89 100644 --- a/lanes/free/lane.go +++ b/lanes/free/lane.go @@ -17,7 +17,7 @@ var _ block.Lane = (*FreeLane)(nil) // FreeLane defines the lane that is responsible for processing free transactions. // By default, transactions that are staking related are considered free. type FreeLane struct { - *constructor.LaneConstructor[string] + *constructor.LaneConstructor } // NewFreeLane returns a new free lane. @@ -26,7 +26,7 @@ func NewFreeLane( txPriority constructor.TxPriority[string], matchFn block.MatchHandler, ) *FreeLane { - lane := constructor.NewLaneConstructor[string]( + lane := constructor.NewLaneConstructor( cfg, LaneName, constructor.NewMempool[string]( diff --git a/lanes/mev/lane.go b/lanes/mev/lane.go index e2b405b..9e1e5f8 100644 --- a/lanes/mev/lane.go +++ b/lanes/mev/lane.go @@ -34,7 +34,7 @@ type ( MEVLane struct { // LaneConfig defines the base lane configuration. - *constructor.LaneConstructor[string] + *constructor.LaneConstructor // Factory defines the API/functionality which is responsible for determining // if a transaction is a bid transaction and how to extract relevant @@ -49,7 +49,7 @@ func NewMEVLane( factory Factory, ) *MEVLane { lane := &MEVLane{ - LaneConstructor: constructor.NewLaneConstructor[string]( + LaneConstructor: constructor.NewLaneConstructor( cfg, LaneName, constructor.NewMempool[string](