feat: x/blocksdk module integration (#201)
* module proto * lane proto * proto-gen * proto-format * regenerate * genesis * stub * test * comment * new keeper functions * finalize * lint fix * proto format * encounteredLanes * make protos * generate * generate * msgs * msgs test * msg service * grpc query * add module * add module assertions * add client * config * app * clean * wip * mocks * integrate into mempool * lane utils * wip * fix and test * format * debug logs * add * integrate * format * fix * rm * add * fmt imports * better error * simplify * simplify * simplify * format * deep copy * Update block/lane.go Co-authored-by: Keefer Taylor | Tessellated <keefer@tessellated.io> --------- Co-authored-by: aljo242 <alex@ingenuity.build> Co-authored-by: Keefer Taylor | Tessellated <keefer@tessellated.io>
This commit is contained in:
parent
f5457e3e54
commit
41e85e9cfe
38
abci/abci.go
38
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)
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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()),
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
78
block/lane_test.go
Normal file
78
block/lane_test.go
Normal file
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
35
block/mocks/lane_fetcher.go
Normal file
35
block/mocks/lane_fetcher.go
Normal file
@ -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()
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user