diff --git a/abci/abci.go b/abci/abci.go index 90fd019..b8d6a81 100644 --- a/abci/abci.go +++ b/abci/abci.go @@ -20,11 +20,10 @@ type ( // ProposalHandler is a wrapper around the ABCI++ PrepareProposal and ProcessProposal // handlers. ProposalHandler struct { - logger log.Logger - txDecoder sdk.TxDecoder - txEncoder sdk.TxEncoder - prepareLanesHandler block.PrepareLanesHandler - mempool block.Mempool + logger log.Logger + txDecoder sdk.TxDecoder + txEncoder sdk.TxEncoder + mempool block.Mempool } ) @@ -37,11 +36,10 @@ func NewProposalHandler( mempool block.Mempool, ) *ProposalHandler { return &ProposalHandler{ - logger: logger, - txDecoder: txDecoder, - txEncoder: txEncoder, - prepareLanesHandler: ChainPrepareLanes(mempool.Registry()), - mempool: mempool, + logger: logger, + txDecoder: txDecoder, + txEncoder: txEncoder, + mempool: mempool, } } @@ -74,8 +72,16 @@ func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler { "height", req.Height, ) + registry, err := h.mempool.Registry(ctx) + if err != nil { + h.logger.Error("failed to get lane registry", "err", err) + return &abci.ResponsePrepareProposal{Txs: make([][]byte, 0)}, err + } + + prepareLanesHandler := ChainPrepareLanes(registry) + // Fill the proposal with transactions from each lane. - finalProposal, err := h.prepareLanesHandler(ctx, proposals.NewProposalWithContext(h.logger, ctx, h.txEncoder)) + finalProposal, err := prepareLanesHandler(ctx, proposals.NewProposalWithContext(h.logger, ctx, h.txEncoder)) if err != nil { h.logger.Error("failed to prepare proposal", "err", err) return &abci.ResponsePrepareProposal{Txs: make([][]byte, 0)}, err @@ -133,14 +139,20 @@ func (h *ProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHandler { }() // Extract all of the lanes and their corresponding transactions from the proposal. - proposalInfo, partialProposals, err := h.ExtractLanes(req.Txs) + proposalInfo, partialProposals, err := h.ExtractLanes(ctx, req.Txs) if err != nil { h.logger.Error("failed to validate proposal", "err", err) return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err } // Build handler that will verify the partial proposals according to each lane's verification logic. - processLanesHandler := ChainProcessLanes(partialProposals, h.mempool.Registry()) + registry, err := h.mempool.Registry(ctx) + if err != nil { + h.logger.Error("failed to get lane registry", "err", err) + return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}, err + } + + processLanesHandler := ChainProcessLanes(partialProposals, registry) finalProposal, err := processLanesHandler(ctx, proposals.NewProposalWithContext(h.logger, ctx, h.txEncoder)) if err != nil { h.logger.Error("failed to validate the proposal", "err", err) diff --git a/abci/abci_test.go b/abci/abci_test.go index a66e8e8..29ed6d4 100644 --- a/abci/abci_test.go +++ b/abci/abci_test.go @@ -15,10 +15,40 @@ import ( "github.com/skip-mev/block-sdk/abci" "github.com/skip-mev/block-sdk/block" + "github.com/skip-mev/block-sdk/block/mocks" "github.com/skip-mev/block-sdk/block/proposals" testutils "github.com/skip-mev/block-sdk/testutils" + blocksdkmoduletypes "github.com/skip-mev/block-sdk/x/blocksdk/types" ) +type MockLaneFetcher struct { + getLaneHandler func() (blocksdkmoduletypes.Lane, error) + getLanesHandler func() []blocksdkmoduletypes.Lane +} + +func NewMockLaneFetcher(getLane func() (blocksdkmoduletypes.Lane, error), getLanes func() []blocksdkmoduletypes.Lane) MockLaneFetcher { + return MockLaneFetcher{ + getLaneHandler: getLane, + getLanesHandler: getLanes, + } +} + +func (m *MockLaneFetcher) SetGetLaneHandler(h func() (blocksdkmoduletypes.Lane, error)) { + m.getLaneHandler = h +} + +func (m MockLaneFetcher) GetLane(_ sdk.Context, _ string) (blocksdkmoduletypes.Lane, error) { + return m.getLaneHandler() +} + +func (m *MockLaneFetcher) SetGetLanesHandler(h func() []blocksdkmoduletypes.Lane) { + m.getLanesHandler = h +} + +func (m MockLaneFetcher) GetLanes(_ sdk.Context) []blocksdkmoduletypes.Lane { + return m.getLanesHandler() +} + type ProposalsTestSuite struct { suite.Suite ctx sdk.Context @@ -660,7 +690,34 @@ func (s *ProposalsTestSuite) TestPrepareProposalEdgeCases() { }) s.Require().NoError(defaultLane.Insert(sdk.Context{}, tx)) - mempool := block.NewLanedMempool(log.NewTestLogger(s.T()), false, panicLane, defaultLane) + lanes := []block.Lane{ + panicLane, + defaultLane, + } + + chainLanes := []blocksdkmoduletypes.Lane{ + { + Id: panicLane.Name(), + MaxBlockSpace: panicLane.GetMaxBlockSpace(), + Order: 0, + }, + { + Id: defaultLane.Name(), + MaxBlockSpace: defaultLane.GetMaxBlockSpace(), + Order: 1, + }, + } + + mempool := block.NewLanedMempool( + log.NewTestLogger(s.T()), + false, + mocks.NewMockLaneFetcher(func() (blocksdkmoduletypes.Lane, error) { + return blocksdkmoduletypes.Lane{}, nil + }, func() []blocksdkmoduletypes.Lane { + return chainLanes + }), + lanes..., + ) proposalHandler := abci.NewProposalHandler( log.NewTestLogger(s.T()), @@ -709,7 +766,34 @@ func (s *ProposalsTestSuite) TestPrepareProposalEdgeCases() { }) s.Require().NoError(defaultLane.Insert(sdk.Context{}, tx)) - mempool := block.NewLanedMempool(log.NewTestLogger(s.T()), false, defaultLane, panicLane) + lanes := []block.Lane{ + defaultLane, + panicLane, + } + + chainLanes := []blocksdkmoduletypes.Lane{ + { + Id: panicLane.Name(), + MaxBlockSpace: panicLane.GetMaxBlockSpace(), + Order: 1, + }, + { + Id: defaultLane.Name(), + MaxBlockSpace: defaultLane.GetMaxBlockSpace(), + Order: 0, + }, + } + + mempool := block.NewLanedMempool( + log.NewTestLogger(s.T()), + false, + mocks.NewMockLaneFetcher(func() (blocksdkmoduletypes.Lane, error) { + return blocksdkmoduletypes.Lane{}, nil + }, func() []blocksdkmoduletypes.Lane { + return chainLanes + }), + lanes..., + ) proposalHandler := abci.NewProposalHandler( log.NewTestLogger(s.T()), @@ -759,8 +843,40 @@ func (s *ProposalsTestSuite) TestPrepareProposalEdgeCases() { }) s.Require().NoError(defaultLane.Insert(sdk.Context{}, tx)) - mempool := block.NewLanedMempool(log.NewTestLogger(s.T()), false, panicLane, panicLane2, defaultLane) + lanes := []block.Lane{ + panicLane, + panicLane2, + defaultLane, + } + chainLanes := []blocksdkmoduletypes.Lane{ + { + Id: panicLane.Name(), + MaxBlockSpace: panicLane.GetMaxBlockSpace(), + Order: 0, + }, + { + Id: panicLane2.Name(), + MaxBlockSpace: panicLane2.GetMaxBlockSpace(), + Order: 1, + }, + { + Id: defaultLane.Name(), + MaxBlockSpace: defaultLane.GetMaxBlockSpace(), + Order: 2, + }, + } + + mempool := block.NewLanedMempool( + log.NewTestLogger(s.T()), + false, + mocks.NewMockLaneFetcher(func() (blocksdkmoduletypes.Lane, error) { + return blocksdkmoduletypes.Lane{}, nil + }, func() []blocksdkmoduletypes.Lane { + return chainLanes + }), + lanes..., + ) proposalHandler := abci.NewProposalHandler( log.NewTestLogger(s.T()), s.encodingConfig.TxConfig.TxDecoder(), @@ -809,7 +925,40 @@ func (s *ProposalsTestSuite) TestPrepareProposalEdgeCases() { }) s.Require().NoError(defaultLane.Insert(sdk.Context{}, tx)) - mempool := block.NewLanedMempool(log.NewTestLogger(s.T()), false, defaultLane, panicLane, panicLane2) + lanes := []block.Lane{ + defaultLane, + panicLane, + panicLane2, + } + + chainLanes := []blocksdkmoduletypes.Lane{ + { + Id: panicLane.Name(), + MaxBlockSpace: panicLane.GetMaxBlockSpace(), + Order: 1, + }, + { + Id: panicLane2.Name(), + MaxBlockSpace: panicLane2.GetMaxBlockSpace(), + Order: 2, + }, + { + Id: defaultLane.Name(), + MaxBlockSpace: defaultLane.GetMaxBlockSpace(), + Order: 0, + }, + } + + mempool := block.NewLanedMempool( + log.NewTestLogger(s.T()), + false, + mocks.NewMockLaneFetcher(func() (blocksdkmoduletypes.Lane, error) { + return blocksdkmoduletypes.Lane{}, nil + }, func() []blocksdkmoduletypes.Lane { + return chainLanes + }), + lanes..., + ) proposalHandler := abci.NewProposalHandler( log.NewTestLogger(s.T()), @@ -1454,7 +1603,7 @@ func (s *ProposalsTestSuite) TestIterateMempoolAndProcessProposalParity() { accounts := testutils.RandomAccounts(s.random, numAccounts) // Create a bunch of transactions to insert into the default lane - txsToInsert := []sdk.Tx{} + var txsToInsert []sdk.Tx validationMap := make(map[sdk.Tx]bool) for _, account := range accounts { for nonce := uint64(0); nonce < numTxsPerAccount; nonce++ { @@ -1511,14 +1660,14 @@ func (s *ProposalsTestSuite) TestIterateMempoolAndProcessProposalParity() { } // Retrieve the transactions from the default lane in the same way the prepare function would. - retrievedTxs := []sdk.Tx{} + var retrievedTxs []sdk.Tx for iterator := defaultLane.Select(context.Background(), nil); iterator != nil; iterator = iterator.Next() { retrievedTxs = append(retrievedTxs, iterator.Tx()) } s.Require().Equal(len(txsToInsert), len(retrievedTxs)) // Retrieve the transactions from the free lane in the same way the prepare function would. - freeRetrievedTxs := []sdk.Tx{} + var freeRetrievedTxs []sdk.Tx for iterator := freelane.Select(context.Background(), nil); iterator != nil; iterator = iterator.Next() { freeRetrievedTxs = append(freeRetrievedTxs, iterator.Tx()) } @@ -1557,7 +1706,7 @@ func (s *ProposalsTestSuite) TestValidateBasic() { info := s.createProposalInfoBytes(0, 0, 0, 0, nil) proposal := [][]byte{info} - _, partialProposals, err := proposalHandlers.ExtractLanes(proposal) + _, partialProposals, err := proposalHandlers.ExtractLanes(s.ctx, proposal) s.Require().NoError(err) s.Require().Equal(3, len(partialProposals)) @@ -1570,21 +1719,21 @@ func (s *ProposalsTestSuite) TestValidateBasic() { info := s.createProposalInfoBytes(0, 0, 0, 0, nil) proposal := [][]byte{info, {0x01, 0x02, 0x03}} - _, _, err := proposalHandlers.ExtractLanes(proposal) + _, _, err := proposalHandlers.ExtractLanes(s.ctx, proposal) s.Require().Error(err) }) s.Run("should invalidate proposal without info", func() { proposal := [][]byte{{0x01, 0x02, 0x03}} - _, _, err := proposalHandlers.ExtractLanes(proposal) + _, _, err := proposalHandlers.ExtractLanes(s.ctx, proposal) s.Require().Error(err) }) s.Run("should invalidate completely empty proposal", func() { proposal := [][]byte{} - _, _, err := proposalHandlers.ExtractLanes(proposal) + _, _, err := proposalHandlers.ExtractLanes(s.ctx, proposal) s.Require().Error(err) }) @@ -1592,7 +1741,7 @@ func (s *ProposalsTestSuite) TestValidateBasic() { info := s.createProposalInfoBytes(0, 0, 0, 0, nil) proposal := [][]byte{info, {0x01, 0x02, 0x03}, {0x01, 0x02, 0x03}} - _, _, err := proposalHandlers.ExtractLanes(proposal) + _, _, err := proposalHandlers.ExtractLanes(s.ctx, proposal) s.Require().Error(err) }) @@ -1622,7 +1771,7 @@ func (s *ProposalsTestSuite) TestValidateBasic() { proposal = append([][]byte{info}, proposal...) - _, partialProposals, err := proposalHandlers.ExtractLanes(proposal) + _, partialProposals, err := proposalHandlers.ExtractLanes(s.ctx, proposal) s.Require().NoError(err) s.Require().Equal(3, len(partialProposals)) @@ -1669,7 +1818,7 @@ func (s *ProposalsTestSuite) TestValidateBasic() { proposal = append([][]byte{info}, proposal...) - _, partialProposals, err := proposalHandlers.ExtractLanes(proposal) + _, partialProposals, err := proposalHandlers.ExtractLanes(s.ctx, proposal) s.Require().NoError(err) s.Require().Equal(3, len(partialProposals)) @@ -1730,7 +1879,7 @@ func (s *ProposalsTestSuite) TestValidateBasic() { proposal = append([][]byte{info}, proposal...) - _, partialProposals, err := proposalHandlers.ExtractLanes(proposal) + _, partialProposals, err := proposalHandlers.ExtractLanes(s.ctx, proposal) s.Require().NoError(err) s.Require().Equal(3, len(partialProposals)) diff --git a/abci/utils.go b/abci/utils.go index a834910..6f411e4 100644 --- a/abci/utils.go +++ b/abci/utils.go @@ -15,7 +15,7 @@ import ( // for the proposal to be valid. This includes: // 1. The proposal must contain the proposal information and must be valid. // 2. The proposal must contain the correct number of transactions for each lane. -func (h *ProposalHandler) ExtractLanes(proposal [][]byte) (types.ProposalInfo, [][][]byte, error) { +func (h *ProposalHandler) ExtractLanes(ctx sdk.Context, proposal [][]byte) (types.ProposalInfo, [][][]byte, error) { // If the proposal is empty, then the metadata was not included. if len(proposal) == 0 { return types.ProposalInfo{}, nil, fmt.Errorf("proposal does not contain proposal metadata") @@ -29,7 +29,10 @@ func (h *ProposalHandler) ExtractLanes(proposal [][]byte) (types.ProposalInfo, [ return types.ProposalInfo{}, nil, fmt.Errorf("failed to unmarshal proposal metadata: %w", err) } - lanes := h.mempool.Registry() + lanes, err := h.mempool.Registry(ctx) + if err != nil { + return types.ProposalInfo{}, nil, fmt.Errorf("failed to get mempool registry: %w", err) + } partialProposals := make([][][]byte, len(lanes)) if metaData.TxsByLane == nil { diff --git a/abci/utils_test.go b/abci/utils_test.go index 953e1ad..fdbaef0 100644 --- a/abci/utils_test.go +++ b/abci/utils_test.go @@ -5,6 +5,8 @@ import ( "encoding/hex" "fmt" + blocksdkmoduletypes "github.com/skip-mev/block-sdk/x/blocksdk/types" + "cosmossdk.io/log" "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" @@ -63,6 +65,7 @@ func (s *ProposalsTestSuite) setUpStandardLane(maxBlockSpace math.LegacyDec, exp TxDecoder: s.encodingConfig.TxConfig.TxDecoder(), AnteHandler: s.setUpAnteHandler(expectedExecution), MaxBlockSpace: maxBlockSpace, + IgnoreList: make([]block.Lane, 0), SignerExtractor: signeradaptors.NewDefaultAdapter(), } @@ -118,7 +121,29 @@ func (s *ProposalsTestSuite) setUpPanicLane(maxBlockSpace math.LegacyDec) *base. } func (s *ProposalsTestSuite) setUpProposalHandlers(lanes []block.Lane) *abci.ProposalHandler { - mempool := block.NewLanedMempool(log.NewTestLogger(s.T()), true, lanes...) + blocksdkLanes := make([]blocksdkmoduletypes.Lane, len(lanes)) + for i, lane := range lanes { + blocksdkLanes[i] = blocksdkmoduletypes.Lane{ + Id: lane.Name(), + MaxBlockSpace: lane.GetMaxBlockSpace(), + Order: uint64(i), + } + } + + laneFetcher := NewMockLaneFetcher( + func() (blocksdkmoduletypes.Lane, error) { + return blocksdkmoduletypes.Lane{}, nil + }, + func() []blocksdkmoduletypes.Lane { + return blocksdkLanes + }) + + mempool := block.NewLanedMempool(log.NewTestLogger( + s.T()), + false, + laneFetcher, + lanes..., + ) return abci.NewProposalHandler( log.NewTestLogger(s.T()), diff --git a/block/base/lane.go b/block/base/lane.go index ae0a06f..b332071 100644 --- a/block/base/lane.go +++ b/block/base/lane.go @@ -173,3 +173,9 @@ func (l *BaseLane) TxEncoder() sdk.TxEncoder { func (l *BaseLane) GetMaxBlockSpace() math.LegacyDec { return l.cfg.MaxBlockSpace } + +// SetMaxBlockSpace sets the maximum amount of block space that the lane is +// allowed to consume as a percentage of the total block space. +func (l *BaseLane) SetMaxBlockSpace(maxBlockSpace math.LegacyDec) { + l.cfg.MaxBlockSpace = maxBlockSpace +} diff --git a/block/lane.go b/block/lane.go index 71923cc..f3dd80b 100644 --- a/block/lane.go +++ b/block/lane.go @@ -57,6 +57,9 @@ type Lane interface { // GetMaxBlockSpace returns the max block space for the lane as a relative percentage. GetMaxBlockSpace() math.LegacyDec + // SetMaxBlockSpace sets the max block space for the lane as a relative percentage. + SetMaxBlockSpace(math.LegacyDec) + // Name returns the name of the lane. Name() string @@ -69,3 +72,15 @@ type Lane interface { // Match determines if a transaction belongs to this lane. Match(ctx sdk.Context, tx sdk.Tx) bool } + +// FindLane finds a Lanes from in an array of Lanes and returns it and its index if found. +// Returns nil, 0 and false if not found. +func FindLane(lanes []Lane, name string) (lane Lane, index int, found bool) { + for i, lane := range lanes { + if lane.Name() == name { + return lanes[i], i, true + } + } + + return nil, 0, false +} diff --git a/block/lane_test.go b/block/lane_test.go new file mode 100644 index 0000000..0813edb --- /dev/null +++ b/block/lane_test.go @@ -0,0 +1,78 @@ +package block_test + +import ( + "fmt" + + "github.com/skip-mev/block-sdk/block" + "github.com/skip-mev/block-sdk/block/mocks" +) + +func (suite *BlockBusterTestSuite) TestFindLane() { + lanes := make([]block.Lane, 30) + cleanup := func() { + for i := range lanes { + _ = lanes[i].Name() + } + } + defer cleanup() + + for i := range lanes { + laneMock := mocks.NewLane(suite.T()) + laneMock.On("Name").Return(fmt.Sprintf("lane%d", i)) + lanes[i] = laneMock + } + + type args struct { + lanes []block.Lane + name string + } + tests := []struct { + name string + args args + wantLane block.Lane + wantIndex int + wantFound bool + }{ + { + name: "invalid lane not found", + args: args{ + lanes: lanes, + name: "invalid", + }, + wantFound: false, + }, + { + name: "valid lane1", + args: args{ + lanes: lanes, + name: "lane1", + }, + wantLane: lanes[1], + wantIndex: 1, + wantFound: true, + }, + { + name: "valid lane15", + args: args{ + lanes: lanes, + name: "lane15", + }, + wantLane: lanes[15], + wantIndex: 15, + wantFound: true, + }, + } + for _, tc := range tests { + suite.Run(tc.name, func() { + gotLane, gotIndex, gotFound := block.FindLane(tc.args.lanes, tc.args.name) + if tc.wantFound { + suite.Require().True(gotFound) + suite.Require().Equal(tc.wantLane, gotLane) + suite.Require().Equal(tc.wantIndex, gotIndex) + return + } + + suite.Require().False(gotFound) + }) + } +} diff --git a/block/mempool.go b/block/mempool.go index 6845956..f4c5b3c 100644 --- a/block/mempool.go +++ b/block/mempool.go @@ -9,19 +9,27 @@ import ( "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" + + blocksdkmoduletypes "github.com/skip-mev/block-sdk/x/blocksdk/types" ) var _ Mempool = (*LanedMempool)(nil) +// LaneFetcher defines the interface to get a lane stored in the x/blocksdk module. +type LaneFetcher interface { + GetLane(ctx sdk.Context, id string) (lane blocksdkmoduletypes.Lane, err error) + GetLanes(ctx sdk.Context) []blocksdkmoduletypes.Lane +} + type ( // Mempool defines the Block SDK mempool interface. Mempool interface { sdkmempool.Mempool // Registry returns the mempool's lane registry. - Registry() []Lane + Registry(ctx sdk.Context) ([]Lane, error) - // Contains returns the any of the lanes currently contain the transaction. + // Contains returns true if any of the lanes currently contain the transaction. Contains(tx sdk.Tx) bool // GetTxDistribution returns the number of transactions in each lane. @@ -37,11 +45,17 @@ type ( // according to their priority. The first lane in the registry has the // highest priority and the last lane has the lowest priority. registry []Lane + + // moduleLaneFetcher is the mempool's interface to read on-chain lane + // information in the x/blocksdk module. + moduleLaneFetcher LaneFetcher } ) -// NewLanedMempool returns a new Block SDK LanedMempool. The laned mempool is -// comprised of a registry of lanes. Each lane is responsible for selecting +// NewLanedMempool returns a new Block SDK LanedMempool. The laned mempool comprises +// +// a registry of lanes. Each lane is responsible for selecting +// // transactions according to its own selection logic. The lanes are ordered // according to their priority. The first lane in the registry has the highest // priority. Proposals are verified according to the order of the lanes in the @@ -51,10 +65,11 @@ type ( // attempt to insert, remove transactions from all lanes it belongs to. It is recommended, // that mutex is set to true when creating the mempool. This will ensure that each // transaction cannot be inserted into the lanes before it. -func NewLanedMempool(logger log.Logger, mutex bool, lanes ...Lane) Mempool { +func NewLanedMempool(logger log.Logger, mutex bool, laneFetcher LaneFetcher, lanes ...Lane) Mempool { mempool := &LanedMempool{ - logger: logger, - registry: lanes, + logger: logger, + registry: lanes, + moduleLaneFetcher: laneFetcher, } if err := mempool.ValidateBasic(); err != nil { @@ -63,8 +78,10 @@ func NewLanedMempool(logger log.Logger, mutex bool, lanes ...Lane) Mempool { // Set the ignore list for each lane if mutex { - registry := mempool.registry - for index, lane := range mempool.registry { + // perform full copy to prevent GC + registry := make([]Lane, len(mempool.registry)) + copy(registry, mempool.registry) + for index, lane := range registry { if index > 0 { lane.SetIgnoreList(registry[:index]) } @@ -193,11 +210,6 @@ func (m *LanedMempool) Contains(tx sdk.Tx) (contains bool) { return false } -// Registry returns the mempool's lane registry. -func (m *LanedMempool) Registry() []Lane { - return m.registry -} - // ValidateBasic validates the mempools configuration. ValidateBasic ensures // the following: // - The sum of the lane max block space percentages is less than or equal to 1. @@ -225,5 +237,50 @@ func (m *LanedMempool) ValidateBasic() error { return fmt.Errorf("sum of total block space percentages will be less than 1") } + if m.moduleLaneFetcher == nil { + return fmt.Errorf("moduleLaneFetcher muset be set on mempool") + } + return nil } + +// Registry returns the mempool's lane registry. +func (m *LanedMempool) Registry(ctx sdk.Context) (newRegistry []Lane, err error) { + if m.moduleLaneFetcher == nil { + return m.registry, fmt.Errorf("module lane fetcher not set") + } + + // TODO add a last block updated check ? + // potential future optimization + chainLanes := m.moduleLaneFetcher.GetLanes(ctx) + + // order lanes and populate the necessary fields (maxBlockSize, etc) + m.registry, err = m.OrderLanes(chainLanes) + return m.registry, err +} + +func (m *LanedMempool) OrderLanes(chainLanes []blocksdkmoduletypes.Lane) (orderedLanes []Lane, err error) { + orderedLanes = make([]Lane, len(chainLanes)) + for _, chainLane := range chainLanes { + // panic protect + if chainLane.GetOrder() >= uint64(len(orderedLanes)) { + return orderedLanes, fmt.Errorf("lane order %d out of bounds, invalid configuration", chainLane.GetOrder()) + } + + _, index, found := FindLane(m.registry, chainLane.Id) + if !found { + return orderedLanes, fmt.Errorf("lane %s not found in registry, invalid configuration", chainLane.Id) + } + + lane := m.registry[index] + lane.SetMaxBlockSpace(chainLane.MaxBlockSpace) + orderedLanes[chainLane.GetOrder()] = lane + + // remove found lane from registry lanes for quicker find() + m.registry[index] = m.registry[len(m.registry)-1] // Copy last element to index i. + m.registry[len(m.registry)-1] = nil // Erase last element (write zero value). + m.registry = m.registry[:len(m.registry)-1] // Truncate slice. + } + + return orderedLanes, nil +} diff --git a/block/mempool_test.go b/block/mempool_test.go index 714bc27..c827f51 100644 --- a/block/mempool_test.go +++ b/block/mempool_test.go @@ -5,6 +5,10 @@ import ( "testing" "time" + blocksdkmoduletypes "github.com/skip-mev/block-sdk/x/blocksdk/types" + + "github.com/skip-mev/block-sdk/block/mocks" + "cosmossdk.io/log" "cosmossdk.io/math" storetypes "cosmossdk.io/store/types" @@ -35,8 +39,14 @@ type BlockBusterTestSuite struct { freeLane *free.FreeLane gasTokenDenom string - lanes []block.Lane - mempool block.Mempool + // sdk module lanes + mevSDKLane blocksdkmoduletypes.Lane + baseSDKLane blocksdkmoduletypes.Lane + freeSDKLane blocksdkmoduletypes.Lane + + chainLanes []blocksdkmoduletypes.Lane + lanes []block.Lane + mempool block.Mempool // account set up accounts []testutils.Account @@ -73,6 +83,12 @@ func (suite *BlockBusterTestSuite) SetupTest() { mev.NewDefaultAuctionFactory(suite.encodingConfig.TxConfig.TxDecoder(), signer_extraction.NewDefaultAdapter()), ) + suite.mevSDKLane = blocksdkmoduletypes.Lane{ + Id: suite.mevLane.Name(), + MaxBlockSpace: suite.mevLane.GetMaxBlockSpace(), + Order: 0, + } + // Free lane set up freeConfig := base.LaneConfig{ Logger: log.NewNopLogger(), @@ -88,6 +104,12 @@ func (suite *BlockBusterTestSuite) SetupTest() { free.DefaultMatchHandler(), ) + suite.freeSDKLane = blocksdkmoduletypes.Lane{ + Id: suite.freeLane.Name(), + MaxBlockSpace: suite.freeLane.GetMaxBlockSpace(), + Order: 1, + } + // Base lane set up baseConfig := base.LaneConfig{ Logger: log.NewNopLogger(), @@ -101,9 +123,25 @@ func (suite *BlockBusterTestSuite) SetupTest() { baseConfig, ) + suite.baseSDKLane = blocksdkmoduletypes.Lane{ + Id: suite.baseLane.Name(), + MaxBlockSpace: suite.baseLane.GetMaxBlockSpace(), + Order: 2, + } + // Mempool set up suite.lanes = []block.Lane{suite.mevLane, suite.freeLane, suite.baseLane} - suite.mempool = block.NewLanedMempool(log.NewTestLogger(suite.T()), true, suite.lanes...) + suite.chainLanes = []blocksdkmoduletypes.Lane{suite.mevSDKLane, suite.freeSDKLane, suite.baseSDKLane} + suite.mempool = block.NewLanedMempool( + log.NewTestLogger(suite.T()), + true, + mocks.NewMockLaneFetcher(func() (blocksdkmoduletypes.Lane, error) { + return suite.baseSDKLane, nil + }, func() []blocksdkmoduletypes.Lane { + return suite.chainLanes + }), + suite.lanes..., + ) // Accounts set up suite.accounts = testutils.RandomAccounts(suite.random, 10) @@ -376,3 +414,260 @@ func (suite *BlockBusterTestSuite) fillFreeLane(numTxs int) { suite.Require().NoError(suite.mempool.Insert(suite.ctx, tx)) } } + +func (suite *BlockBusterTestSuite) TestLanedMempool_Registry() { + tests := []struct { + name string + chainLanes []blocksdkmoduletypes.Lane + registryLanes []block.Lane + expectedNewRegistry []block.Lane + wantErr bool + }{ + { + name: "invalid lanes in chain", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.freeLane, + suite.mevLane, + suite.baseLane, + }, + wantErr: true, + }, + { + name: "invalid duplicate lanes in chain", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.baseSDKLane, // order = 2 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.freeLane, + suite.mevLane, + suite.baseLane, + }, + wantErr: true, + }, + { + name: "invalid lanes in registry", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.freeSDKLane, // order = 1 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.freeLane, + suite.baseLane, + }, + wantErr: true, + }, + { + name: "invalid duplicate lanes in registry", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.freeSDKLane, // order = 1 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.freeLane, + suite.baseLane, + suite.baseLane, + }, + wantErr: true, + }, + { + name: "valid reorder", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.freeSDKLane, // order = 1 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.freeLane, + suite.mevLane, + suite.baseLane, + }, + expectedNewRegistry: []block.Lane{ + suite.mevLane, + suite.freeLane, + suite.baseLane, + }, + wantErr: false, + }, + { + name: "valid no reorder", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.freeSDKLane, // order = 1 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.mevLane, + suite.freeLane, + suite.baseLane, + }, + expectedNewRegistry: []block.Lane{ + suite.mevLane, + suite.freeLane, + suite.baseLane, + }, + wantErr: false, + }, + } + for _, tc := range tests { + suite.Run(tc.name, func() { + // setup mock mempool + mempool := block.NewLanedMempool( + log.NewTestLogger(suite.T()), + true, + mocks.NewMockLaneFetcher(func() (blocksdkmoduletypes.Lane, error) { + return blocksdkmoduletypes.Lane{}, nil + }, func() []blocksdkmoduletypes.Lane { + return tc.chainLanes + }), + tc.registryLanes..., + ) + + gotOrderedLanes, err := mempool.Registry(suite.ctx) + if tc.wantErr { + suite.Require().Error(err) + return + } + + suite.Require().NoError(err) + suite.Require().Equal(tc.expectedNewRegistry, gotOrderedLanes) + }) + } +} + +func (suite *BlockBusterTestSuite) TestLanedMempool_OrderLanes() { + tests := []struct { + name string + chainLanes []blocksdkmoduletypes.Lane + registryLanes []block.Lane + expectedOrderedLane []block.Lane + wantErr bool + }{ + { + name: "invalid lanes in chain", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.freeLane, + suite.mevLane, + suite.baseLane, + }, + wantErr: true, + }, + { + name: "invalid duplicate lanes in chain", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.baseSDKLane, // order = 2 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.freeLane, + suite.mevLane, + suite.baseLane, + }, + wantErr: true, + }, + { + name: "invalid lanes in registry", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.freeSDKLane, // order = 1 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.freeLane, + suite.baseLane, + }, + wantErr: true, + }, + { + name: "invalid duplicate lanes in registry", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.freeSDKLane, // order = 1 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.freeLane, + suite.baseLane, + suite.baseLane, + }, + wantErr: true, + }, + { + name: "valid reorder", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.freeSDKLane, // order = 1 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.freeLane, + suite.mevLane, + suite.baseLane, + }, + expectedOrderedLane: []block.Lane{ + suite.mevLane, + suite.freeLane, + suite.baseLane, + }, + wantErr: false, + }, + { + name: "valid no reorder", + chainLanes: []blocksdkmoduletypes.Lane{ + suite.mevSDKLane, // order = 0 + suite.freeSDKLane, // order = 1 + suite.baseSDKLane, // order = 2 + }, + registryLanes: []block.Lane{ + suite.mevLane, + suite.freeLane, + suite.baseLane, + }, + expectedOrderedLane: []block.Lane{ + suite.mevLane, + suite.freeLane, + suite.baseLane, + }, + wantErr: false, + }, + } + for _, tc := range tests { + suite.Run(tc.name, func() { + // setup mock mempool + mempool := block.NewLanedMempool( + log.NewTestLogger(suite.T()), + true, + mocks.NewMockLaneFetcher(func() (blocksdkmoduletypes.Lane, error) { + return blocksdkmoduletypes.Lane{}, nil + }, func() []blocksdkmoduletypes.Lane { + return []blocksdkmoduletypes.Lane{} + }), + tc.registryLanes..., + ) + + lanedMempool, ok := mempool.(*block.LanedMempool) + suite.Require().True(ok) + + gotOrderedLanes, err := lanedMempool.OrderLanes(tc.chainLanes) + if tc.wantErr { + suite.Require().Error(err) + return + } + + suite.Require().NoError(err) + suite.Require().Equal(tc.expectedOrderedLane, gotOrderedLanes) + }) + } +} diff --git a/block/mocks/lane.go b/block/mocks/lane.go index f922091..cd17e4e 100644 --- a/block/mocks/lane.go +++ b/block/mocks/lane.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.30.1. DO NOT EDIT. +// Code generated by mockery v0.0.0-dev. DO NOT EDIT. package mocks @@ -24,17 +24,27 @@ type Lane struct { } // Compare provides a mock function with given fields: ctx, this, other -func (_m *Lane) Compare(ctx types.Context, this types.Tx, other types.Tx) int { +func (_m *Lane) Compare(ctx types.Context, this types.Tx, other types.Tx) (int, error) { ret := _m.Called(ctx, this, other) var r0 int + var r1 error + if rf, ok := ret.Get(0).(func(types.Context, types.Tx, types.Tx) (int, error)); ok { + return rf(ctx, this, other) + } if rf, ok := ret.Get(0).(func(types.Context, types.Tx, types.Tx) int); ok { r0 = rf(ctx, this, other) } else { r0 = ret.Get(0).(int) } - return r0 + if rf, ok := ret.Get(1).(func(types.Context, types.Tx, types.Tx) error); ok { + r1 = rf(ctx, this, other) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // Contains provides a mock function with given fields: tx @@ -209,6 +219,11 @@ func (_m *Lane) SetIgnoreList(ignoreList []block.Lane) { _m.Called(ignoreList) } +// SetMaxBlockSpace provides a mock function with given fields: _a0 +func (_m *Lane) SetMaxBlockSpace(_a0 math.LegacyDec) { + _m.Called(_a0) +} + // NewLane creates a new instance of Lane. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewLane(t interface { diff --git a/block/mocks/lane_fetcher.go b/block/mocks/lane_fetcher.go new file mode 100644 index 0000000..d7c9372 --- /dev/null +++ b/block/mocks/lane_fetcher.go @@ -0,0 +1,35 @@ +package mocks + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + + blocksdkmoduletypes "github.com/skip-mev/block-sdk/x/blocksdk/types" +) + +type MockLaneFetcher struct { + getLaneHandler func() (blocksdkmoduletypes.Lane, error) + getLanesHandler func() []blocksdkmoduletypes.Lane +} + +func NewMockLaneFetcher(getLane func() (blocksdkmoduletypes.Lane, error), getLanes func() []blocksdkmoduletypes.Lane) MockLaneFetcher { + return MockLaneFetcher{ + getLaneHandler: getLane, + getLanesHandler: getLanes, + } +} + +func (m *MockLaneFetcher) SetGetLaneHandler(h func() (blocksdkmoduletypes.Lane, error)) { + m.getLaneHandler = h +} + +func (m MockLaneFetcher) GetLane(_ sdk.Context, _ string) (blocksdkmoduletypes.Lane, error) { + return m.getLaneHandler() +} + +func (m *MockLaneFetcher) SetGetLanesHandler(h func() []blocksdkmoduletypes.Lane) { + m.getLanesHandler = h +} + +func (m MockLaneFetcher) GetLanes(_ sdk.Context) []blocksdkmoduletypes.Lane { + return m.getLanesHandler() +} diff --git a/block/mocks/lane_mempool.go b/block/mocks/lane_mempool.go index d3892d3..e9d674c 100644 --- a/block/mocks/lane_mempool.go +++ b/block/mocks/lane_mempool.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.30.1. DO NOT EDIT. +// Code generated by mockery v0.0.0-dev. DO NOT EDIT. package mocks @@ -17,17 +17,27 @@ type LaneMempool struct { } // Compare provides a mock function with given fields: ctx, this, other -func (_m *LaneMempool) Compare(ctx types.Context, this types.Tx, other types.Tx) int { +func (_m *LaneMempool) Compare(ctx types.Context, this types.Tx, other types.Tx) (int, error) { ret := _m.Called(ctx, this, other) var r0 int + var r1 error + if rf, ok := ret.Get(0).(func(types.Context, types.Tx, types.Tx) (int, error)); ok { + return rf(ctx, this, other) + } if rf, ok := ret.Get(0).(func(types.Context, types.Tx, types.Tx) int); ok { r0 = rf(ctx, this, other) } else { r0 = ret.Get(0).(int) } - return r0 + if rf, ok := ret.Get(1).(func(types.Context, types.Tx, types.Tx) error); ok { + r1 = rf(ctx, this, other) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // Contains provides a mock function with given fields: tx diff --git a/lanes/terminator/lane.go b/lanes/terminator/lane.go index c125dae..0e0a534 100644 --- a/lanes/terminator/lane.go +++ b/lanes/terminator/lane.go @@ -55,6 +55,9 @@ func (t Terminator) GetMaxBlockSpace() math.LegacyDec { return math.LegacyZeroDec() } +// SetMaxBlockSpace is a no-op +func (t Terminator) SetMaxBlockSpace(_ math.LegacyDec) {} + // Logger is a no-op func (t Terminator) Logger() log.Logger { return log.NewNopLogger() diff --git a/tests/app/app.go b/tests/app/app.go index 2d5cf88..d18faf9 100644 --- a/tests/app/app.go +++ b/tests/app/app.go @@ -12,11 +12,9 @@ import ( "cosmossdk.io/depinject" storetypes "cosmossdk.io/store/types" circuitkeeper "cosmossdk.io/x/circuit/keeper" - "cosmossdk.io/x/upgrade" upgradekeeper "cosmossdk.io/x/upgrade/keeper" feegrantkeeper "cosmossdk.io/x/feegrant/keeper" - feegrantmodule "cosmossdk.io/x/feegrant/module" cometabci "github.com/cometbft/cometbft/abci/types" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" @@ -29,36 +27,19 @@ import ( servertypes "github.com/cosmos/cosmos-sdk/server/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" - "github.com/cosmos/cosmos-sdk/x/auth" "github.com/cosmos/cosmos-sdk/x/auth/ante" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - "github.com/cosmos/cosmos-sdk/x/auth/vesting" authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" - authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" - "github.com/cosmos/cosmos-sdk/x/bank" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - "github.com/cosmos/cosmos-sdk/x/consensus" consensuskeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper" - "github.com/cosmos/cosmos-sdk/x/crisis" crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper" - distr "github.com/cosmos/cosmos-sdk/x/distribution" distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" - "github.com/cosmos/cosmos-sdk/x/genutil" - genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" - "github.com/cosmos/cosmos-sdk/x/gov" - govclient "github.com/cosmos/cosmos-sdk/x/gov/client" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper" - groupmodule "github.com/cosmos/cosmos-sdk/x/group/module" - "github.com/cosmos/cosmos-sdk/x/mint" mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper" - "github.com/cosmos/cosmos-sdk/x/params" - paramsclient "github.com/cosmos/cosmos-sdk/x/params/client" paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" - "github.com/cosmos/cosmos-sdk/x/slashing" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" - "github.com/cosmos/cosmos-sdk/x/staking" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" "github.com/skip-mev/block-sdk/abci" @@ -68,8 +49,8 @@ import ( defaultlane "github.com/skip-mev/block-sdk/lanes/base" "github.com/skip-mev/block-sdk/lanes/free" "github.com/skip-mev/block-sdk/lanes/mev" - auctionmodule "github.com/skip-mev/block-sdk/x/auction" auctionkeeper "github.com/skip-mev/block-sdk/x/auction/keeper" + blocksdkkeeper "github.com/skip-mev/block-sdk/x/blocksdk/keeper" ) const ( @@ -81,33 +62,6 @@ var ( // DefaultNodeHome default home directories for the application daemon DefaultNodeHome string - - // ModuleBasics defines the module BasicManager is in charge of setting up basic, - // non-dependant module elements, such as codec registration - // and genesis verification. - ModuleBasics = module.NewBasicManager( - auth.AppModuleBasic{}, - genutil.NewAppModuleBasic(genutiltypes.DefaultMessageValidator), - bank.AppModuleBasic{}, - staking.AppModuleBasic{}, - mint.AppModuleBasic{}, - distr.AppModuleBasic{}, - gov.NewAppModuleBasic( - []govclient.ProposalHandler{ - paramsclient.ProposalHandler, - }, - ), - params.AppModuleBasic{}, - crisis.AppModuleBasic{}, - slashing.AppModuleBasic{}, - upgrade.AppModuleBasic{}, - authzmodule.AppModuleBasic{}, - groupmodule.AppModuleBasic{}, - vesting.AppModuleBasic{}, - consensus.AppModuleBasic{}, - auctionmodule.AppModuleBasic{}, - feegrantmodule.AppModuleBasic{}, - ) ) var ( @@ -138,6 +92,7 @@ type TestApp struct { ConsensusParamsKeeper consensuskeeper.Keeper CircuitBreakerKeeper circuitkeeper.Keeper auctionkeeper auctionkeeper.Keeper + blocksdkKeeper blocksdkkeeper.Keeper FeeGrantKeeper feegrantkeeper.Keeper // custom checkTx handler @@ -219,6 +174,7 @@ func New( &app.AuthzKeeper, &app.GroupKeeper, &app.auctionkeeper, + &app.blocksdkKeeper, &app.ConsensusParamsKeeper, &app.FeeGrantKeeper, &app.CircuitBreakerKeeper, @@ -309,7 +265,12 @@ func New( freeLane, defaultLane, } - mempool := block.NewLanedMempool(app.Logger(), true, lanes...) + mempool := block.NewLanedMempool( + app.Logger(), + true, + &app.blocksdkKeeper, + lanes..., + ) app.App.SetMempool(mempool) // Create a global ante handler that will be called on each transaction when diff --git a/tests/app/config.go b/tests/app/config.go index 700ac38..8731b45 100644 --- a/tests/app/config.go +++ b/tests/app/config.go @@ -49,6 +49,7 @@ import ( "google.golang.org/protobuf/types/known/durationpb" _ "cosmossdk.io/x/circuit" // import for side-effects + _ "cosmossdk.io/x/feegrant/module" // import for side-effects _ "cosmossdk.io/x/upgrade" // import for side-effects _ "github.com/cosmos/cosmos-sdk/x/auth/tx/config" // import for side-effects _ "github.com/cosmos/cosmos-sdk/x/auth/vesting" // import for side-effects @@ -66,8 +67,11 @@ import ( _ "github.com/cosmos/cosmos-sdk/x/staking" // import for side-effects auctionmodulev1 "github.com/skip-mev/block-sdk/api/sdk/auction/module/v1" + blocksdkmodulev1 "github.com/skip-mev/block-sdk/api/sdk/blocksdk/module/v1" _ "github.com/skip-mev/block-sdk/x/auction" // import for side-effects auctiontypes "github.com/skip-mev/block-sdk/x/auction/types" + _ "github.com/skip-mev/block-sdk/x/blocksdk" // import for side-effects + blocksdktypes "github.com/skip-mev/block-sdk/x/blocksdk/types" ) var ( @@ -151,6 +155,7 @@ var ( consensustypes.ModuleName, circuittypes.ModuleName, auctiontypes.ModuleName, + blocksdktypes.ModuleName, feegrant.ModuleName, }, // When ExportGenesis is not specified, the export genesis module order @@ -247,6 +252,10 @@ var ( Name: auctiontypes.ModuleName, Config: appconfig.WrapAny(&auctionmodulev1.Module{}), }, + { + Name: blocksdktypes.ModuleName, + Config: appconfig.WrapAny(&blocksdkmodulev1.Module{}), + }, }, }), depinject.Supply( diff --git a/tests/integration/block_sdk_integration_test.go b/tests/integration/block_sdk_integration_test.go index 59937d8..9b61bb2 100644 --- a/tests/integration/block_sdk_integration_test.go +++ b/tests/integration/block_sdk_integration_test.go @@ -4,15 +4,21 @@ import ( "fmt" "testing" + "cosmossdk.io/math" + testutil "github.com/cosmos/cosmos-sdk/types/module/testutil" - "github.com/strangelove-ventures/interchaintest/v7" + interchaintest "github.com/strangelove-ventures/interchaintest/v7" "github.com/strangelove-ventures/interchaintest/v7/chain/cosmos" "github.com/strangelove-ventures/interchaintest/v7/ibc" ictestutil "github.com/strangelove-ventures/interchaintest/v7/testutil" "github.com/stretchr/testify/suite" + "github.com/skip-mev/block-sdk/lanes/base" + "github.com/skip-mev/block-sdk/lanes/free" + "github.com/skip-mev/block-sdk/lanes/mev" "github.com/skip-mev/block-sdk/tests/integration" auctiontypes "github.com/skip-mev/block-sdk/x/auction/types" + blocksdkmoduletypes "github.com/skip-mev/block-sdk/x/blocksdk/types" ) var ( @@ -28,13 +34,33 @@ var ( } encodingConfig = MakeEncodingConfig() noHostMount = false - gasAdjustment = float64(2.0) + gasAdjustment = 2.0 genesisKV = []cosmos.GenesisKV{ { Key: "app_state.auction.params.max_bundle_size", Value: 3, }, + { + Key: "app_state.blocksdk.lanes", + Value: []blocksdkmoduletypes.Lane{ + { + Id: mev.LaneName, + MaxBlockSpace: math.LegacyMustNewDecFromStr("0.2"), + Order: 0, + }, + { + Id: free.LaneName, + MaxBlockSpace: math.LegacyMustNewDecFromStr("0.2"), + Order: 1, + }, + { + Id: base.LaneName, + MaxBlockSpace: math.LegacyMustNewDecFromStr("0.6"), + Order: 2, + }, + }, + }, } consensusParams = ictestutil.Toml{ @@ -78,6 +104,7 @@ func MakeEncodingConfig() *testutil.TestEncodingConfig { // register auction types auctiontypes.RegisterInterfaces(cfg.InterfaceRegistry) + blocksdkmoduletypes.RegisterInterfaces(cfg.InterfaceRegistry) return &cfg }