fix(mempool parity): Enforce comet / app-side mempool parity in CheckTx + integ. tests [BLO-584] [BLO-635] (#306)
* account setup for network tests * Add Test case for app-mempool / cmt mempool parity * add fix * move check-tx handlers to wrap each other * linting * migrate to chaintestutils * linting * additional test-case * lint * remove paralell tests * remove MEVLaneI * fix(check_tx): Check error of GetAuctionBid in ValidateBidTx [BLO-461] (#312) * add err check in ValidateBidTx * add test-case for ValidateBidTx * remove -race flag for integ
This commit is contained in:
parent
4b6e481c3f
commit
b5fe2a772c
2
Makefile
2
Makefile
@ -134,7 +134,7 @@ test-unit: use-main
|
||||
@go test -v -race $(shell go list ./... | grep -v tests/)
|
||||
|
||||
test-integration: tidy
|
||||
@go test -v -race ./tests/integration
|
||||
@go test -v -race ./tests/integration/...
|
||||
|
||||
test-cover: tidy
|
||||
@echo Running unit tests and creating coverage report...
|
||||
|
||||
11
abci/checktx/check_tx.go
Normal file
11
abci/checktx/check_tx.go
Normal file
@ -0,0 +1,11 @@
|
||||
package checktx
|
||||
|
||||
import (
|
||||
cometabci "github.com/cometbft/cometbft/abci/types"
|
||||
)
|
||||
|
||||
type (
|
||||
// CheckTx is baseapp's CheckTx method that checks the validity of a
|
||||
// transaction.
|
||||
CheckTx func(req *cometabci.RequestCheckTx) (*cometabci.ResponseCheckTx, error)
|
||||
)
|
||||
328
abci/checktx/check_tx_test.go
Normal file
328
abci/checktx/check_tx_test.go
Normal file
@ -0,0 +1,328 @@
|
||||
package checktx_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/math"
|
||||
"cosmossdk.io/store"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
cometabci "github.com/cometbft/cometbft/abci/types"
|
||||
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
db "github.com/cosmos/cosmos-db"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/skip-mev/block-sdk/abci/checktx"
|
||||
"github.com/skip-mev/block-sdk/block"
|
||||
"github.com/skip-mev/block-sdk/lanes/mev"
|
||||
mevlanetestutils "github.com/skip-mev/block-sdk/lanes/mev/testutils"
|
||||
"github.com/skip-mev/block-sdk/testutils"
|
||||
auctiontypes "github.com/skip-mev/block-sdk/x/auction/types"
|
||||
blocksdktypes "github.com/skip-mev/block-sdk/x/blocksdk/types"
|
||||
)
|
||||
|
||||
type CheckTxTestSuite struct {
|
||||
mevlanetestutils.MEVLaneTestSuiteBase
|
||||
}
|
||||
|
||||
func TestCheckTxTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(CheckTxTestSuite))
|
||||
}
|
||||
|
||||
func (s *CheckTxTestSuite) TestCheckTxMempoolParity() {
|
||||
bidTx, _, err := testutils.CreateAuctionTx(
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// create a tx that should not be inserted in the mev-lane
|
||||
bidTx2, _, err := testutils.CreateAuctionTx(
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
1,
|
||||
0,
|
||||
nil,
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txs := map[sdk.Tx]bool{
|
||||
bidTx: true,
|
||||
}
|
||||
|
||||
mevLane := s.InitLane(math.LegacyOneDec(), txs)
|
||||
mempool, err := block.NewLanedMempool(s.Ctx.Logger(), []block.Lane{mevLane}, moduleLaneFetcher{
|
||||
mevLane,
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
ba := &baseApp{
|
||||
s.Ctx,
|
||||
}
|
||||
mevLaneHandler := checktx.NewMEVCheckTxHandler(
|
||||
ba,
|
||||
s.EncCfg.TxConfig.TxDecoder(),
|
||||
mevLane,
|
||||
s.SetUpAnteHandler(txs),
|
||||
ba.CheckTx,
|
||||
).CheckTx()
|
||||
|
||||
handler := checktx.NewMempoolParityCheckTx(
|
||||
s.Ctx.Logger(),
|
||||
mempool,
|
||||
s.EncCfg.TxConfig.TxDecoder(),
|
||||
mevLaneHandler,
|
||||
).CheckTx()
|
||||
|
||||
// test that a bid can be successfully inserted to mev-lane on CheckTx
|
||||
s.Run("test bid insertion on CheckTx", func() {
|
||||
txBz, err := s.EncCfg.TxConfig.TxEncoder()(bidTx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// check tx
|
||||
res, err := handler(&cometabci.RequestCheckTx{Tx: txBz, Type: cometabci.CheckTxType_New})
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(uint32(0), res.Code)
|
||||
|
||||
// check that the mev-lane contains the bid
|
||||
s.Require().True(mevLane.Contains(bidTx))
|
||||
})
|
||||
|
||||
// test that a bid-tx (not in mev-lane) can be removed from the mempool on ReCheck
|
||||
s.Run("test bid removal on ReCheckTx", func() {
|
||||
// assert that the mev-lane does not contain the bidTx2
|
||||
s.Require().False(mevLane.Contains(bidTx2))
|
||||
|
||||
// check tx
|
||||
txBz, err := s.EncCfg.TxConfig.TxEncoder()(bidTx2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
res, err := handler(&cometabci.RequestCheckTx{Tx: txBz, Type: cometabci.CheckTxType_Recheck})
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(uint32(1), res.Code)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CheckTxTestSuite) TestMempoolParityCheckTx() {
|
||||
s.Run("tx fails tx-decoding", func() {
|
||||
handler := checktx.NewMempoolParityCheckTx(
|
||||
s.Ctx.Logger(),
|
||||
nil,
|
||||
s.EncCfg.TxConfig.TxDecoder(),
|
||||
nil,
|
||||
)
|
||||
|
||||
res, err := handler.CheckTx()(&cometabci.RequestCheckTx{Tx: []byte("invalid-tx")})
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(uint32(1), res.Code)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CheckTxTestSuite) TestMEVCheckTxHandler() {
|
||||
txs := map[sdk.Tx]bool{}
|
||||
|
||||
mevLane := s.InitLane(math.LegacyOneDec(), txs)
|
||||
mempool, err := block.NewLanedMempool(s.Ctx.Logger(), []block.Lane{mevLane}, moduleLaneFetcher{
|
||||
mevLane,
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
ba := &baseApp{
|
||||
s.Ctx,
|
||||
}
|
||||
|
||||
acc := s.Accounts[0]
|
||||
// create a tx that should not be inserted in the mev-lane
|
||||
normalTx, err := testutils.CreateRandomTxBz(s.EncCfg.TxConfig, acc, 0, 1, 0, 0)
|
||||
s.Require().NoError(err)
|
||||
|
||||
var gotTx []byte
|
||||
mevLaneHandler := checktx.NewMEVCheckTxHandler(
|
||||
ba,
|
||||
s.EncCfg.TxConfig.TxDecoder(),
|
||||
mevLane,
|
||||
s.SetUpAnteHandler(txs),
|
||||
func(req *cometabci.RequestCheckTx) (*cometabci.ResponseCheckTx, error) {
|
||||
// expect the above free tx to be sent here
|
||||
gotTx = req.Tx
|
||||
return &cometabci.ResponseCheckTx{
|
||||
Code: uint32(0),
|
||||
}, nil
|
||||
},
|
||||
).CheckTx()
|
||||
|
||||
handler := checktx.NewMempoolParityCheckTx(
|
||||
s.Ctx.Logger(),
|
||||
mempool,
|
||||
s.EncCfg.TxConfig.TxDecoder(),
|
||||
mevLaneHandler,
|
||||
).CheckTx()
|
||||
|
||||
// test that a normal tx can be successfully inserted to the mempool
|
||||
s.Run("test non-mev tx insertion on CheckTx", func() {
|
||||
res, err := handler(&cometabci.RequestCheckTx{Tx: normalTx, Type: cometabci.CheckTxType_New})
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(uint32(0), res.Code)
|
||||
s.Require().Equal(normalTx, gotTx)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *CheckTxTestSuite) TestValidateBidTx() {
|
||||
validBidTx, bundled, err := testutils.CreateAuctionTx(
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
[]testutils.Account{s.Accounts[0]},
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
txBz, err := s.EncCfg.TxConfig.TxEncoder()(validBidTx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// create an invalid bid-tx (nested)
|
||||
bidMsg := auctiontypes.NewMsgAuctionBid(s.Accounts[0].Address, sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)), [][]byte{
|
||||
txBz,
|
||||
})
|
||||
nestedBidTx, err := testutils.CreateTx(
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
0,
|
||||
0,
|
||||
[]sdk.Msg{bidMsg},
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// create an invalid bid-tx (signer invalid)
|
||||
invalidBidMsg := auctiontypes.MsgAuctionBid{
|
||||
Bidder: "",
|
||||
Bid: sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
Transactions: nil,
|
||||
}
|
||||
invalidBidTx, err := testutils.CreateTx(
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
0,
|
||||
0,
|
||||
[]sdk.Msg{&invalidBidMsg},
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// create a tx that should not be inserted in the mev-lane
|
||||
s.Require().NoError(err)
|
||||
|
||||
txs := map[sdk.Tx]bool{
|
||||
validBidTx: true,
|
||||
bundled[0]: true,
|
||||
nestedBidTx: true,
|
||||
invalidBidTx: true,
|
||||
}
|
||||
|
||||
mevLane := s.InitLane(math.LegacyOneDec(), txs)
|
||||
|
||||
ba := &baseApp{
|
||||
s.Ctx,
|
||||
}
|
||||
mevLaneHandler := checktx.NewMEVCheckTxHandler(
|
||||
ba,
|
||||
s.EncCfg.TxConfig.TxDecoder(),
|
||||
mevLane,
|
||||
s.SetUpAnteHandler(txs),
|
||||
ba.CheckTx,
|
||||
)
|
||||
s.Run("expected bid-tx", func() {
|
||||
bundledTx, err := s.EncCfg.TxConfig.TxEncoder()(bundled[0])
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = mevLaneHandler.ValidateBidTx(s.Ctx, validBidTx, &auctiontypes.BidInfo{
|
||||
Transactions: [][]byte{bundledTx},
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
})
|
||||
|
||||
s.Run("nested bid-tx", func() {
|
||||
nestedBidTxBz, err := s.EncCfg.TxConfig.TxEncoder()(nestedBidTx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = mevLaneHandler.ValidateBidTx(s.Ctx, nestedBidTx, &auctiontypes.BidInfo{
|
||||
Transactions: [][]byte{nestedBidTxBz},
|
||||
})
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), "bundled tx cannot be a bid tx")
|
||||
})
|
||||
|
||||
s.Run("invalid bid-tx", func() {
|
||||
invalidBidTxBz, err := s.EncCfg.TxConfig.TxEncoder()(invalidBidTx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = mevLaneHandler.ValidateBidTx(s.Ctx, invalidBidTx, &auctiontypes.BidInfo{
|
||||
Transactions: [][]byte{invalidBidTxBz},
|
||||
})
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), "failed to get bid info")
|
||||
})
|
||||
}
|
||||
|
||||
type baseApp struct {
|
||||
ctx sdk.Context
|
||||
}
|
||||
|
||||
// CommitMultiStore is utilized to retrieve the latest committed state.
|
||||
func (ba *baseApp) CommitMultiStore() storetypes.CommitMultiStore {
|
||||
db := db.NewMemDB()
|
||||
return store.NewCommitMultiStore(db, ba.ctx.Logger(), nil)
|
||||
}
|
||||
|
||||
// CheckTx is baseapp's CheckTx method that checks the validity of a
|
||||
// transaction.
|
||||
func (baseApp) CheckTx(_ *cometabci.RequestCheckTx) (*cometabci.ResponseCheckTx, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
// Logger is utilized to log errors.
|
||||
func (ba *baseApp) Logger() log.Logger {
|
||||
return ba.ctx.Logger()
|
||||
}
|
||||
|
||||
// LastBlockHeight is utilized to retrieve the latest block height.
|
||||
func (ba *baseApp) LastBlockHeight() int64 {
|
||||
return ba.ctx.BlockHeight()
|
||||
}
|
||||
|
||||
// GetConsensusParams is utilized to retrieve the consensus params.
|
||||
func (baseApp) GetConsensusParams(ctx sdk.Context) cmtproto.ConsensusParams {
|
||||
return ctx.ConsensusParams()
|
||||
}
|
||||
|
||||
// ChainID is utilized to retrieve the chain ID.
|
||||
func (ba *baseApp) ChainID() string {
|
||||
return ba.ctx.ChainID()
|
||||
}
|
||||
|
||||
type moduleLaneFetcher struct {
|
||||
lane *mev.MEVLane
|
||||
}
|
||||
|
||||
func (mlf moduleLaneFetcher) GetLane(sdk.Context, string) (lane blocksdktypes.Lane, err error) {
|
||||
return blocksdktypes.Lane{}, nil
|
||||
}
|
||||
|
||||
func (mlf moduleLaneFetcher) GetLanes(sdk.Context) []blocksdktypes.Lane {
|
||||
return nil
|
||||
}
|
||||
77
abci/checktx/mempool_parity_check_tx.go
Normal file
77
abci/checktx/mempool_parity_check_tx.go
Normal file
@ -0,0 +1,77 @@
|
||||
package checktx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
|
||||
cmtabci "github.com/cometbft/cometbft/abci/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
"github.com/skip-mev/block-sdk/block"
|
||||
)
|
||||
|
||||
// MempoolParityCheckTx is a CheckTx function that evicts txs that are not in the app-side mempool
|
||||
// on ReCheckTx. This handler is used to enforce parity in the app-side / comet mempools.
|
||||
type MempoolParityCheckTx struct {
|
||||
// logger
|
||||
logger log.Logger
|
||||
|
||||
// app side mempool interface
|
||||
mempl block.Mempool
|
||||
|
||||
// tx-decoder
|
||||
txDecoder sdk.TxDecoder
|
||||
|
||||
// checkTxHandler to wrap
|
||||
checkTxHandler CheckTx
|
||||
}
|
||||
|
||||
// NewMempoolParityCheckTx returns a new MempoolParityCheckTx handler.
|
||||
func NewMempoolParityCheckTx(logger log.Logger, mempl block.Mempool, txDecoder sdk.TxDecoder, checkTxHandler CheckTx) MempoolParityCheckTx {
|
||||
return MempoolParityCheckTx{
|
||||
logger: logger,
|
||||
mempl: mempl,
|
||||
txDecoder: txDecoder,
|
||||
checkTxHandler: checkTxHandler,
|
||||
}
|
||||
}
|
||||
|
||||
// CheckTx returns a CheckTx handler that wraps a given CheckTx handler and evicts txs that are not
|
||||
// in the app-side mempool on ReCheckTx.
|
||||
func (m MempoolParityCheckTx) CheckTx() CheckTx {
|
||||
return func(req *cmtabci.RequestCheckTx) (*cmtabci.ResponseCheckTx, error) {
|
||||
// decode tx
|
||||
tx, err := m.txDecoder(req.Tx)
|
||||
if err != nil {
|
||||
return sdkerrors.ResponseCheckTxWithEvents(
|
||||
fmt.Errorf("failed to decode tx: %w", err),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
false,
|
||||
), nil
|
||||
}
|
||||
|
||||
// if the mode is ReCheck and the app's mempool does not contain the given tx, we fail
|
||||
// immediately, to purge the tx from the comet mempool.
|
||||
if req.Type == cmtabci.CheckTxType_Recheck && !m.mempl.Contains(tx) {
|
||||
m.logger.Debug(
|
||||
"tx from comet mempool not found in app-side mempool",
|
||||
"tx", tx,
|
||||
)
|
||||
|
||||
return sdkerrors.ResponseCheckTxWithEvents(
|
||||
fmt.Errorf("tx from comet mempool not found in app-side mempool"),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
false,
|
||||
), nil
|
||||
}
|
||||
|
||||
// run the checkTxHandler
|
||||
return m.checkTxHandler(req)
|
||||
}
|
||||
}
|
||||
@ -1,81 +1,89 @@
|
||||
package mev
|
||||
package checktx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
log "cosmossdk.io/log"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
cometabci "github.com/cometbft/cometbft/abci/types"
|
||||
cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
|
||||
"github.com/skip-mev/block-sdk/block"
|
||||
mevlane "github.com/skip-mev/block-sdk/lanes/mev"
|
||||
"github.com/skip-mev/block-sdk/x/auction/types"
|
||||
)
|
||||
|
||||
type (
|
||||
// CheckTxHandler is a wrapper around baseapp's CheckTx method that allows us to
|
||||
// verify bid transactions against the latest committed state. All other transactions
|
||||
// are executed normally using base app's CheckTx. This defines all of the
|
||||
// dependencies that are required to verify a bid transaction.
|
||||
CheckTxHandler struct {
|
||||
// baseApp is utilized to retrieve the latest committed state and to call
|
||||
// baseapp's CheckTx method.
|
||||
baseApp BaseApp
|
||||
// MevCheckTxHandler is a wrapper around baseapp's CheckTx method that allows us to
|
||||
// verify bid transactions against the latest committed state. All other transactions
|
||||
// are executed normally using base app's CheckTx. This defines all of the
|
||||
// dependencies that are required to verify a bid transaction.
|
||||
type MEVCheckTxHandler struct {
|
||||
// baseApp is utilized to retrieve the latest committed state and to call
|
||||
// baseapp's CheckTx method.
|
||||
baseApp BaseApp
|
||||
|
||||
// txDecoder is utilized to decode transactions to determine if they are
|
||||
// bid transactions.
|
||||
txDecoder sdk.TxDecoder
|
||||
// txDecoder is utilized to decode transactions to determine if they are
|
||||
// bid transactions.
|
||||
txDecoder sdk.TxDecoder
|
||||
|
||||
// MEVLane is utilized to retrieve the bid info of a transaction and to
|
||||
// insert a bid transaction into the application-side mempool.
|
||||
mevLane MEVLaneI
|
||||
// MEVLane is utilized to retrieve the bid info of a transaction and to
|
||||
// insert a bid transaction into the application-side mempool.
|
||||
mevLane MEVLaneI
|
||||
|
||||
// anteHandler is utilized to verify the bid transaction against the latest
|
||||
// committed state.
|
||||
anteHandler sdk.AnteHandler
|
||||
}
|
||||
// anteHandler is utilized to verify the bid transaction against the latest
|
||||
// committed state.
|
||||
anteHandler sdk.AnteHandler
|
||||
|
||||
// CheckTx is baseapp's CheckTx method that checks the validity of a
|
||||
// transaction.
|
||||
CheckTx func(req *cometabci.RequestCheckTx) (*cometabci.ResponseCheckTx, error)
|
||||
// checkTxHandler is the wrapped CheckTx handler that is used to execute all non-bid txs
|
||||
checkTxHandler CheckTx
|
||||
}
|
||||
|
||||
// BaseApp is an interface that allows us to call baseapp's CheckTx method
|
||||
// as well as retrieve the latest committed state.
|
||||
BaseApp interface {
|
||||
// CommitMultiStore is utilized to retrieve the latest committed state.
|
||||
CommitMultiStore() storetypes.CommitMultiStore
|
||||
// MEVLaneI defines the interface for the mev auction lane. This interface
|
||||
// is utilized by both the x/auction module and the checkTx handler.
|
||||
type MEVLaneI interface {
|
||||
block.Lane
|
||||
mevlane.Factory
|
||||
GetTopAuctionTx(ctx context.Context) sdk.Tx
|
||||
}
|
||||
|
||||
// CheckTx is baseapp's CheckTx method that checks the validity of a
|
||||
// transaction.
|
||||
CheckTx(req *cometabci.RequestCheckTx) (*cometabci.ResponseCheckTx, error)
|
||||
// BaseApp is an interface that allows us to call baseapp's CheckTx method
|
||||
// as well as retrieve the latest committed state.
|
||||
type BaseApp interface {
|
||||
// CommitMultiStore is utilized to retrieve the latest committed state.
|
||||
CommitMultiStore() storetypes.CommitMultiStore
|
||||
|
||||
// Logger is utilized to log errors.
|
||||
Logger() log.Logger
|
||||
// Logger is utilized to log errors.
|
||||
Logger() log.Logger
|
||||
|
||||
// LastBlockHeight is utilized to retrieve the latest block height.
|
||||
LastBlockHeight() int64
|
||||
// LastBlockHeight is utilized to retrieve the latest block height.
|
||||
LastBlockHeight() int64
|
||||
|
||||
// GetConsensusParams is utilized to retrieve the consensus params.
|
||||
GetConsensusParams(ctx sdk.Context) cmtproto.ConsensusParams
|
||||
// GetConsensusParams is utilized to retrieve the consensus params.
|
||||
GetConsensusParams(ctx sdk.Context) cmtproto.ConsensusParams
|
||||
|
||||
// ChainID is utilized to retrieve the chain ID.
|
||||
ChainID() string
|
||||
}
|
||||
)
|
||||
// ChainID is utilized to retrieve the chain ID.
|
||||
ChainID() string
|
||||
}
|
||||
|
||||
// NewCheckTxHandler constructs a new CheckTxHandler instance.
|
||||
func NewCheckTxHandler(
|
||||
// NewCheckTxHandler constructs a new CheckTxHandler instance. This method fails if the given LanedMempool does not have a lane
|
||||
// adhering to the MevLaneI interface
|
||||
func NewMEVCheckTxHandler(
|
||||
baseApp BaseApp,
|
||||
txDecoder sdk.TxDecoder,
|
||||
mevLane MEVLaneI,
|
||||
anteHandler sdk.AnteHandler,
|
||||
) *CheckTxHandler {
|
||||
return &CheckTxHandler{
|
||||
baseApp: baseApp,
|
||||
txDecoder: txDecoder,
|
||||
mevLane: mevLane,
|
||||
anteHandler: anteHandler,
|
||||
checkTxHandler CheckTx,
|
||||
) *MEVCheckTxHandler {
|
||||
return &MEVCheckTxHandler{
|
||||
baseApp: baseApp,
|
||||
txDecoder: txDecoder,
|
||||
mevLane: mevLane,
|
||||
anteHandler: anteHandler,
|
||||
checkTxHandler: checkTxHandler,
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,7 +93,7 @@ func NewCheckTxHandler(
|
||||
// before we can insert it into the mempool against the latest commit state because
|
||||
// otherwise the auction can be griefed. No state changes are applied to the state
|
||||
// during this process.
|
||||
func (handler *CheckTxHandler) CheckTx() CheckTx {
|
||||
func (handler *MEVCheckTxHandler) CheckTx() CheckTx {
|
||||
return func(req *cometabci.RequestCheckTx) (resp *cometabci.ResponseCheckTx, err error) {
|
||||
defer func() {
|
||||
if rec := recover(); rec != nil {
|
||||
@ -140,7 +148,7 @@ func (handler *CheckTxHandler) CheckTx() CheckTx {
|
||||
|
||||
// If this is not a bid transaction, we just execute it normally.
|
||||
if bidInfo == nil {
|
||||
resp, err := handler.baseApp.CheckTx(req)
|
||||
resp, err := handler.checkTxHandler(req)
|
||||
if err != nil {
|
||||
handler.baseApp.Logger().Info(
|
||||
"failed to execute check tx",
|
||||
@ -222,7 +230,7 @@ func (handler *CheckTxHandler) CheckTx() CheckTx {
|
||||
}
|
||||
|
||||
// ValidateBidTx is utilized to verify the bid transaction against the latest committed state.
|
||||
func (handler *CheckTxHandler) ValidateBidTx(ctx sdk.Context, bidTx sdk.Tx, bidInfo *types.BidInfo) (sdk.GasInfo, error) {
|
||||
func (handler *MEVCheckTxHandler) ValidateBidTx(ctx sdk.Context, bidTx sdk.Tx, bidInfo *types.BidInfo) (sdk.GasInfo, error) {
|
||||
// Verify the bid transaction.
|
||||
ctx, err := handler.anteHandler(ctx, bidTx, false)
|
||||
if err != nil {
|
||||
@ -243,7 +251,11 @@ func (handler *CheckTxHandler) ValidateBidTx(ctx sdk.Context, bidTx sdk.Tx, bidI
|
||||
}
|
||||
|
||||
// bid txs cannot be included in bundled txs
|
||||
bidInfo, _ := handler.mevLane.GetAuctionBidInfo(bundledTx)
|
||||
bidInfo, err := handler.mevLane.GetAuctionBidInfo(bundledTx)
|
||||
if err != nil {
|
||||
return gasInfo, fmt.Errorf("invalid bid tx; failed to get bid info: %w", err)
|
||||
}
|
||||
|
||||
if bidInfo != nil {
|
||||
return gasInfo, fmt.Errorf("invalid bid tx; bundled tx cannot be a bid tx")
|
||||
}
|
||||
@ -258,7 +270,7 @@ func (handler *CheckTxHandler) ValidateBidTx(ctx sdk.Context, bidTx sdk.Tx, bidI
|
||||
|
||||
// GetContextForBidTx is returns the latest committed state and sets the context given
|
||||
// the checkTx request.
|
||||
func (handler *CheckTxHandler) GetContextForBidTx(req *cometabci.RequestCheckTx) sdk.Context {
|
||||
func (handler *MEVCheckTxHandler) GetContextForBidTx(req *cometabci.RequestCheckTx) sdk.Context {
|
||||
// Retrieve the commit multi-store which is used to retrieve the latest committed state.
|
||||
ms := handler.baseApp.CommitMultiStore().CacheMultiStore()
|
||||
|
||||
2
go.mod
2
go.mod
@ -27,7 +27,7 @@ require (
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||
github.com/huandu/skiplist v1.2.0
|
||||
github.com/skip-mev/chaintestutil v0.0.0-20231213172849-7c623445dde1
|
||||
github.com/skip-mev/chaintestutil v0.0.0-20231218180533-7f3da3ddb3f4
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.17.0
|
||||
|
||||
4
go.sum
4
go.sum
@ -1223,8 +1223,8 @@ github.com/sivchari/nosnakecase v1.7.0 h1:7QkpWIRMe8x25gckkFd2A5Pi6Ymo0qgr4JrhGt
|
||||
github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY=
|
||||
github.com/sivchari/tenv v1.7.1 h1:PSpuD4bu6fSmtWMxSGWcvqUUgIn7k3yOJhOIzVWn8Ak=
|
||||
github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg=
|
||||
github.com/skip-mev/chaintestutil v0.0.0-20231213172849-7c623445dde1 h1:x1hie4oqAp0Ay0ijolPKaKVFAHXKuMulBir2RGe1oc0=
|
||||
github.com/skip-mev/chaintestutil v0.0.0-20231213172849-7c623445dde1/go.mod h1:mcyq67cXQTzyhCg2LSBeFS+u7GzWng5xnTFfUAqIHn4=
|
||||
github.com/skip-mev/chaintestutil v0.0.0-20231218180533-7f3da3ddb3f4 h1:uX3mI+MRH4wPclt4MS2BAGKXxxOoKfxy384zbXb6MQc=
|
||||
github.com/skip-mev/chaintestutil v0.0.0-20231218180533-7f3da3ddb3f4/go.mod h1:o3naFS52DumeJLR6h+0YoMV09YvxOALaou9WZuSJOIg=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
|
||||
@ -13,13 +13,13 @@ import (
|
||||
)
|
||||
|
||||
func (s *MEVTestSuite) TestPrepareLane() {
|
||||
s.ctx = s.ctx.WithExecMode(sdk.ExecModePrepareProposal)
|
||||
s.Ctx = s.Ctx.WithExecMode(sdk.ExecModePrepareProposal)
|
||||
|
||||
s.Run("can prepare a lane with no txs in mempool", func() {
|
||||
lane := s.initLane(math.LegacyOneDec(), nil)
|
||||
lane := s.InitLane(math.LegacyOneDec(), nil)
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200, 100)
|
||||
|
||||
proposal, err := lane.PrepareLane(s.ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
proposal, err := lane.PrepareLane(s.Ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(0, len(proposal.Txs))
|
||||
s.Require().Equal(0, len(proposal.Info.TxsByLane))
|
||||
@ -29,9 +29,9 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
|
||||
s.Run("can prepare a lane with a single bid tx in mempool", func() {
|
||||
bidTx, _, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -40,12 +40,12 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
s.Require().NoError(err)
|
||||
size := s.getTxSize(bidTx)
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true})
|
||||
s.Require().NoError(lane.Insert(s.ctx, bidTx))
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true})
|
||||
s.Require().NoError(lane.Insert(s.Ctx, bidTx))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200, 100)
|
||||
|
||||
proposal, err = lane.PrepareLane(s.ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
proposal, err = lane.PrepareLane(s.Ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(1, len(proposal.Txs))
|
||||
s.Require().Equal(1, len(proposal.Info.TxsByLane))
|
||||
@ -53,16 +53,16 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
s.Require().Equal(uint64(100), proposal.Info.GasLimit)
|
||||
|
||||
expectedProposal := []sdk.Tx{bidTx}
|
||||
txBzs, err := utils.GetEncodedTxs(s.encCfg.TxConfig.TxEncoder(), expectedProposal)
|
||||
txBzs, err := utils.GetEncodedTxs(s.EncCfg.TxConfig.TxEncoder(), expectedProposal)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(txBzs[0], proposal.Txs[0])
|
||||
})
|
||||
|
||||
s.Run("can prepare a lane with multiple bid txs where highest bid fails", func() {
|
||||
bidTx1, _, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -71,9 +71,9 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
s.Require().NoError(err)
|
||||
|
||||
bidTx2, _, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[1],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(200)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[1],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(200)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -81,13 +81,13 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx1: true, bidTx2: false})
|
||||
s.Require().NoError(lane.Insert(s.ctx, bidTx1))
|
||||
s.Require().NoError(lane.Insert(s.ctx, bidTx2))
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx1: true, bidTx2: false})
|
||||
s.Require().NoError(lane.Insert(s.Ctx, bidTx1))
|
||||
s.Require().NoError(lane.Insert(s.Ctx, bidTx2))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 20000, 100000)
|
||||
|
||||
proposal, err = lane.PrepareLane(s.ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
proposal, err = lane.PrepareLane(s.Ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(1, len(proposal.Txs))
|
||||
s.Require().Equal(1, len(proposal.Info.TxsByLane))
|
||||
@ -95,16 +95,16 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
s.Require().Equal(uint64(100), proposal.Info.GasLimit)
|
||||
|
||||
expectedProposal := []sdk.Tx{bidTx1}
|
||||
txBzs, err := utils.GetEncodedTxs(s.encCfg.TxConfig.TxEncoder(), expectedProposal)
|
||||
txBzs, err := utils.GetEncodedTxs(s.EncCfg.TxConfig.TxEncoder(), expectedProposal)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(txBzs[0], proposal.Txs[0])
|
||||
})
|
||||
|
||||
s.Run("can prepare a lane with multiple bid txs where highest bid passes", func() {
|
||||
bidTx1, _, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -113,9 +113,9 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
s.Require().NoError(err)
|
||||
|
||||
bidTx2, _, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[1],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(200)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[1],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(200)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -123,13 +123,13 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx1: false, bidTx2: true})
|
||||
s.Require().NoError(lane.Insert(s.ctx, bidTx1))
|
||||
s.Require().NoError(lane.Insert(s.ctx, bidTx2))
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx1: false, bidTx2: true})
|
||||
s.Require().NoError(lane.Insert(s.Ctx, bidTx1))
|
||||
s.Require().NoError(lane.Insert(s.Ctx, bidTx2))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 20000, 100000)
|
||||
|
||||
proposal, err = lane.PrepareLane(s.ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
proposal, err = lane.PrepareLane(s.Ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(1, len(proposal.Txs))
|
||||
s.Require().Equal(1, len(proposal.Info.TxsByLane))
|
||||
@ -137,29 +137,29 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
s.Require().Equal(uint64(100), proposal.Info.GasLimit)
|
||||
|
||||
expectedProposal := []sdk.Tx{bidTx2}
|
||||
txBzs, err := utils.GetEncodedTxs(s.encCfg.TxConfig.TxEncoder(), expectedProposal)
|
||||
txBzs, err := utils.GetEncodedTxs(s.EncCfg.TxConfig.TxEncoder(), expectedProposal)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(txBzs[0], proposal.Txs[0])
|
||||
})
|
||||
|
||||
s.Run("can build a proposal with bid tx that has a bundle", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
s.Require().NoError(lane.Insert(s.ctx, bidTx))
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
s.Require().NoError(lane.Insert(s.Ctx, bidTx))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 20000, 100000)
|
||||
|
||||
proposal, err = lane.PrepareLane(s.ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
proposal, err = lane.PrepareLane(s.Ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(3, len(proposal.Txs))
|
||||
s.Require().Equal(1, len(proposal.Info.TxsByLane))
|
||||
@ -168,29 +168,29 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
s.Require().Equal(uint64(100), proposal.Info.GasLimit)
|
||||
|
||||
expectedProposal := []sdk.Tx{bidTx, bundle[0], bundle[1]}
|
||||
txBzs, err := utils.GetEncodedTxs(s.encCfg.TxConfig.TxEncoder(), expectedProposal)
|
||||
txBzs, err := utils.GetEncodedTxs(s.EncCfg.TxConfig.TxEncoder(), expectedProposal)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(txBzs, proposal.Txs)
|
||||
})
|
||||
|
||||
s.Run("can reject a bid that is too large", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(200)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(200)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
s.Require().NoError(lane.Insert(s.ctx, bidTx))
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
s.Require().NoError(lane.Insert(s.Ctx, bidTx))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), s.getTxSize(bidTx), 100000)
|
||||
|
||||
proposal, err = lane.PrepareLane(s.ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
proposal, err = lane.PrepareLane(s.Ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(0, len(proposal.Txs))
|
||||
s.Require().Equal(0, len(proposal.Info.TxsByLane))
|
||||
@ -200,9 +200,9 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
|
||||
s.Run("can reject a bid that is too gas intensive", func() {
|
||||
bidTx, _, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(200)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(200)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -210,12 +210,12 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true})
|
||||
s.Require().NoError(lane.Insert(s.ctx, bidTx))
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true})
|
||||
s.Require().NoError(lane.Insert(s.Ctx, bidTx))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), s.getTxSize(bidTx), 99)
|
||||
|
||||
proposal, err = lane.PrepareLane(s.ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
proposal, err = lane.PrepareLane(s.Ctx, proposal, block.NoOpPrepareLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(0, len(proposal.Txs))
|
||||
s.Require().Equal(0, len(proposal.Info.TxsByLane))
|
||||
@ -225,44 +225,44 @@ func (s *MEVTestSuite) TestPrepareLane() {
|
||||
}
|
||||
|
||||
func (s *MEVTestSuite) TestProcessLane() {
|
||||
s.ctx = s.ctx.WithExecMode(sdk.ExecModeProcessProposal)
|
||||
s.Ctx = s.Ctx.WithExecMode(sdk.ExecModeProcessProposal)
|
||||
|
||||
s.Run("can process an empty proposal", func() {
|
||||
lane := s.initLane(math.LegacyOneDec(), nil)
|
||||
lane := s.InitLane(math.LegacyOneDec(), nil)
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200, 100)
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, nil)
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, nil)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(0, len(txsFromLane))
|
||||
s.Require().Equal(0, len(remainingTxs))
|
||||
|
||||
proposal, err = lane.ProcessLane(s.ctx, proposal, nil, block.NoOpProcessLanesHandler())
|
||||
proposal, err = lane.ProcessLane(s.Ctx, proposal, nil, block.NoOpProcessLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(0, len(proposal.Txs))
|
||||
})
|
||||
|
||||
s.Run("can process a proposal with tx that does not belong to this lane", func() {
|
||||
tx, err := testutils.CreateRandomTx(s.encCfg.TxConfig, s.accounts[0], 0, 1, 0, 100)
|
||||
tx, err := testutils.CreateRandomTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 1, 0, 100)
|
||||
s.Require().NoError(err)
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), nil)
|
||||
lane := s.InitLane(math.LegacyOneDec(), nil)
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200, 100)
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, []sdk.Tx{tx})
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, []sdk.Tx{tx})
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(0, len(txsFromLane))
|
||||
s.Require().Equal(1, len(remainingTxs))
|
||||
|
||||
finalProposal, err := lane.ProcessLane(s.ctx, proposal, []sdk.Tx{tx}, block.NoOpProcessLanesHandler())
|
||||
finalProposal, err := lane.ProcessLane(s.Ctx, proposal, []sdk.Tx{tx}, block.NoOpProcessLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(0, len(finalProposal.Txs))
|
||||
})
|
||||
|
||||
s.Run("can process a proposal with bad bid tx", func() {
|
||||
bidTx, _, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -272,126 +272,126 @@ func (s *MEVTestSuite) TestProcessLane() {
|
||||
|
||||
partialProposal := []sdk.Tx{bidTx}
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: false})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: false})
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, partialProposal)
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, partialProposal)
|
||||
s.Require().Error(err)
|
||||
s.Require().Equal(0, len(txsFromLane))
|
||||
s.Require().Equal(0, len(remainingTxs))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200000, 1000000)
|
||||
_, err = lane.ProcessLane(s.ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
_, err = lane.ProcessLane(s.Ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
s.Require().Error(err)
|
||||
})
|
||||
|
||||
s.Run("can process a proposal with a bad bundled tx", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
partialProposal := []sdk.Tx{bidTx, bundle[0], bundle[1]}
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: false})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: false})
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, partialProposal)
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, partialProposal)
|
||||
s.Require().Error(err)
|
||||
s.Require().Equal(0, len(txsFromLane))
|
||||
s.Require().Equal(0, len(remainingTxs))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200000, 1000000)
|
||||
_, err = lane.ProcessLane(s.ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
_, err = lane.ProcessLane(s.Ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
s.Require().Error(err)
|
||||
})
|
||||
|
||||
s.Run("can process a proposal with mismatching txs in bundle", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
partialProposal := []sdk.Tx{bidTx, bundle[1], bundle[0]}
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, partialProposal)
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, partialProposal)
|
||||
s.Require().Error(err)
|
||||
s.Require().Equal(0, len(txsFromLane))
|
||||
s.Require().Equal(0, len(remainingTxs))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200000, 1000000)
|
||||
_, err = lane.ProcessLane(s.ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
_, err = lane.ProcessLane(s.Ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
s.Require().Error(err)
|
||||
})
|
||||
|
||||
s.Run("can process a proposal with missing bundle tx", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
partialProposal := []sdk.Tx{bidTx, bundle[0]}
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true})
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, partialProposal)
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, partialProposal)
|
||||
s.Require().Error(err)
|
||||
s.Require().Equal(0, len(txsFromLane))
|
||||
s.Require().Equal(0, len(remainingTxs))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200000, 1000000)
|
||||
_, err = lane.ProcessLane(s.ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
_, err = lane.ProcessLane(s.Ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
s.Require().Error(err)
|
||||
})
|
||||
|
||||
s.Run("can process a valid proposal", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
partialProposal := []sdk.Tx{bidTx, bundle[0], bundle[1]}
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, partialProposal)
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, partialProposal)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(3, len(txsFromLane))
|
||||
s.Require().Equal(0, len(remainingTxs))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200000, 1000000)
|
||||
_, err = lane.ProcessLane(s.ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
_, err = lane.ProcessLane(s.Ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
})
|
||||
|
||||
s.Run("can process a valid proposal with a single bid with no bundle", func() {
|
||||
bidTx, _, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin("stake", math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
@ -402,137 +402,137 @@ func (s *MEVTestSuite) TestProcessLane() {
|
||||
|
||||
partialProposal := []sdk.Tx{bidTx}
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true})
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, partialProposal)
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, partialProposal)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(1, len(txsFromLane))
|
||||
s.Require().Equal(0, len(remainingTxs))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200000, 1000000)
|
||||
_, err = lane.ProcessLane(s.ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
_, err = lane.ProcessLane(s.Ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
})
|
||||
|
||||
s.Run("can reject a block proposal that exceeds its gas limit", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin("stake", math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
partialProposal := []sdk.Tx{bidTx, bundle[0], bundle[1]}
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, partialProposal)
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, partialProposal)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(3, len(txsFromLane))
|
||||
s.Require().Equal(0, len(remainingTxs))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 20000, 99)
|
||||
_, err = lane.ProcessLane(s.ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
_, err = lane.ProcessLane(s.Ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
s.Require().Error(err)
|
||||
})
|
||||
|
||||
s.Run("can reject a block proposal that exceeds its block size", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin("stake", math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
partialProposal := []sdk.Tx{bidTx, bundle[0], bundle[1]}
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, partialProposal)
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, partialProposal)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(3, len(txsFromLane))
|
||||
s.Require().Equal(0, len(remainingTxs))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200, 100)
|
||||
_, err = lane.ProcessLane(s.ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
_, err = lane.ProcessLane(s.Ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
s.Require().Error(err)
|
||||
})
|
||||
|
||||
s.Run("can accept a block proposal with bid and other txs", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin("stake", math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
otherTx, err := testutils.CreateRandomTx(s.encCfg.TxConfig, s.accounts[0], 0, 1, 0, 100)
|
||||
otherTx, err := testutils.CreateRandomTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 1, 0, 100)
|
||||
s.Require().NoError(err)
|
||||
|
||||
partialProposal := []sdk.Tx{bidTx, bundle[0], bundle[1], otherTx}
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, partialProposal)
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, partialProposal)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(3, len(txsFromLane))
|
||||
s.Require().Equal(1, len(remainingTxs))
|
||||
s.Require().Equal(otherTx, remainingTxs[0])
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200000, 1000000)
|
||||
proposal, err = lane.ProcessLane(s.ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
proposal, err = lane.ProcessLane(s.Ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(proposal.Txs, 3)
|
||||
|
||||
encodedTxs, err := utils.GetEncodedTxs(s.encCfg.TxConfig.TxEncoder(), []sdk.Tx{bidTx, bundle[0], bundle[1]})
|
||||
encodedTxs, err := utils.GetEncodedTxs(s.EncCfg.TxConfig.TxEncoder(), []sdk.Tx{bidTx, bundle[0], bundle[1]})
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(encodedTxs, proposal.Txs)
|
||||
})
|
||||
|
||||
s.Run("rejects a block where the bid tx is not the first tx", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin("stake", math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
otherTx, err := testutils.CreateRandomTx(s.encCfg.TxConfig, s.accounts[0], 0, 1, 0, 100)
|
||||
otherTx, err := testutils.CreateRandomTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 1, 0, 100)
|
||||
s.Require().NoError(err)
|
||||
|
||||
partialProposal := []sdk.Tx{otherTx, bidTx, bundle[0], bundle[1]}
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true})
|
||||
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.ctx, partialProposal)
|
||||
txsFromLane, remainingTxs, err := mev.NewProposalHandler(lane.BaseLane, lane.Factory).ProcessLaneHandler()(s.Ctx, partialProposal)
|
||||
s.Require().Error(err)
|
||||
s.Require().Equal(0, len(txsFromLane))
|
||||
s.Require().Equal(0, len(remainingTxs))
|
||||
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200000, 1000000)
|
||||
_, err = lane.ProcessLane(s.ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
_, err = lane.ProcessLane(s.Ctx, proposal, partialProposal, block.NoOpProcessLanesHandler())
|
||||
s.Require().Error(err)
|
||||
})
|
||||
}
|
||||
|
||||
func (s *MEVTestSuite) TestVerifyBidBasic() {
|
||||
lane := s.initLane(math.LegacyOneDec(), nil)
|
||||
lane := s.InitLane(math.LegacyOneDec(), nil)
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), 200, 100)
|
||||
limits := proposal.GetLaneLimits(lane.GetMaxBlockSpace())
|
||||
|
||||
@ -540,9 +540,9 @@ func (s *MEVTestSuite) TestVerifyBidBasic() {
|
||||
|
||||
s.Run("can verify a bid with no bundled txs", func() {
|
||||
bidTx, expectedBundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -550,15 +550,15 @@ func (s *MEVTestSuite) TestVerifyBidBasic() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
bundle, err := handler.VerifyBidBasic(s.ctx, bidTx, proposal, limits)
|
||||
bundle, err := handler.VerifyBidBasic(s.Ctx, bidTx, proposal, limits)
|
||||
s.Require().NoError(err)
|
||||
s.compare(bundle, expectedBundle)
|
||||
})
|
||||
|
||||
s.Run("can reject a tx that is not a bid", func() {
|
||||
tx, err := testutils.CreateRandomTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
@ -566,15 +566,15 @@ func (s *MEVTestSuite) TestVerifyBidBasic() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = handler.VerifyBidBasic(s.ctx, tx, proposal, limits)
|
||||
_, err = handler.VerifyBidBasic(s.Ctx, tx, proposal, limits)
|
||||
s.Require().Error(err)
|
||||
})
|
||||
|
||||
s.Run("can reject a bundle that is too gas intensive", func() {
|
||||
bidTx, _, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -582,18 +582,18 @@ func (s *MEVTestSuite) TestVerifyBidBasic() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = handler.VerifyBidBasic(s.ctx, bidTx, proposal, limits)
|
||||
_, err = handler.VerifyBidBasic(s.Ctx, bidTx, proposal, limits)
|
||||
s.Require().Error(err)
|
||||
})
|
||||
|
||||
s.Run("can reject a bundle that is too large", func() {
|
||||
bidTx, _, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
@ -602,15 +602,15 @@ func (s *MEVTestSuite) TestVerifyBidBasic() {
|
||||
proposal := proposals.NewProposal(log.NewNopLogger(), size-1, 100)
|
||||
limits := proposal.GetLaneLimits(lane.GetMaxBlockSpace())
|
||||
|
||||
_, err = handler.VerifyBidBasic(s.ctx, bidTx, proposal, limits)
|
||||
_, err = handler.VerifyBidBasic(s.Ctx, bidTx, proposal, limits)
|
||||
s.Require().Error(err)
|
||||
})
|
||||
|
||||
s.Run("can reject a bundle with malformed txs", func() {
|
||||
bidMsg, err := testutils.CreateMsgAuctionBid(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
3,
|
||||
)
|
||||
@ -619,15 +619,15 @@ func (s *MEVTestSuite) TestVerifyBidBasic() {
|
||||
bidMsg.Transactions[2] = []byte("invalid")
|
||||
|
||||
bidTx, err := testutils.CreateTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
0,
|
||||
0,
|
||||
[]sdk.Msg{bidMsg},
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
_, err = handler.VerifyBidBasic(s.ctx, bidTx, proposal, limits)
|
||||
_, err = handler.VerifyBidBasic(s.Ctx, bidTx, proposal, limits)
|
||||
s.Require().Error(err)
|
||||
})
|
||||
}
|
||||
@ -635,9 +635,9 @@ func (s *MEVTestSuite) TestVerifyBidBasic() {
|
||||
func (s *MEVTestSuite) TestVerifyBidTx() {
|
||||
s.Run("can verify a valid bid", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -645,17 +645,17 @@ func (s *MEVTestSuite) TestVerifyBidTx() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true})
|
||||
|
||||
handler := mev.NewProposalHandler(lane.BaseLane, lane.Factory)
|
||||
s.Require().NoError(handler.VerifyBidTx(s.ctx, bidTx, bundle))
|
||||
s.Require().NoError(handler.VerifyBidTx(s.Ctx, bidTx, bundle))
|
||||
})
|
||||
|
||||
s.Run("can reject a bid transaction", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -663,46 +663,46 @@ func (s *MEVTestSuite) TestVerifyBidTx() {
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: false})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: false})
|
||||
|
||||
handler := mev.NewProposalHandler(lane.BaseLane, lane.Factory)
|
||||
s.Require().Error(handler.VerifyBidTx(s.ctx, bidTx, bundle))
|
||||
s.Require().Error(handler.VerifyBidTx(s.Ctx, bidTx, bundle))
|
||||
})
|
||||
|
||||
s.Run("can reject a bid transaction with a bad bundle", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: false})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: false})
|
||||
|
||||
handler := mev.NewProposalHandler(lane.BaseLane, lane.Factory)
|
||||
s.Require().Error(handler.VerifyBidTx(s.ctx, bidTx, bundle))
|
||||
s.Require().Error(handler.VerifyBidTx(s.Ctx, bidTx, bundle))
|
||||
})
|
||||
|
||||
s.Run("can reject a bid transaction with a bundle that has another bid tx", func() {
|
||||
bidTx, bundle, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
s.accounts[0:2],
|
||||
s.Accounts[0:2],
|
||||
100,
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
otherBidTx, _, err := testutils.CreateAuctionTx(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
sdk.NewCoin(s.gasTokenDenom, math.NewInt(100)),
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin(s.GasTokenDenom, math.NewInt(100)),
|
||||
0,
|
||||
0,
|
||||
nil,
|
||||
@ -711,9 +711,9 @@ func (s *MEVTestSuite) TestVerifyBidTx() {
|
||||
s.Require().NoError(err)
|
||||
bundle = append(bundle, otherBidTx)
|
||||
|
||||
lane := s.initLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true, otherBidTx: true})
|
||||
lane := s.InitLane(math.LegacyOneDec(), map[sdk.Tx]bool{bidTx: true, bundle[0]: true, bundle[1]: true, otherBidTx: true})
|
||||
|
||||
handler := mev.NewProposalHandler(lane.BaseLane, lane.Factory)
|
||||
s.Require().Error(handler.VerifyBidTx(s.ctx, bidTx, bundle))
|
||||
s.Require().Error(handler.VerifyBidTx(s.Ctx, bidTx, bundle))
|
||||
})
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ func (s *MEVTestSuite) TestIsAuctionTx() {
|
||||
{
|
||||
"normal sdk tx",
|
||||
func() sdk.Tx {
|
||||
tx, err := testutils.CreateRandomTx(s.encCfg.TxConfig, s.accounts[0], 0, 2, 0, 0)
|
||||
tx, err := testutils.CreateRandomTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 2, 0, 0)
|
||||
s.Require().NoError(err)
|
||||
return tx
|
||||
},
|
||||
@ -29,13 +29,13 @@ func (s *MEVTestSuite) TestIsAuctionTx() {
|
||||
{
|
||||
"malformed auction bid tx",
|
||||
func() sdk.Tx {
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := testutils.CreateRandomMsgs(s.accounts[0].Address, 2)
|
||||
msgs := testutils.CreateRandomMsgs(s.Accounts[0].Address, 2)
|
||||
msgs = append(msgs, msgAuctionBid)
|
||||
|
||||
tx, err := testutils.CreateTx(s.encCfg.TxConfig, s.accounts[0], 0, 0, msgs)
|
||||
tx, err := testutils.CreateTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 0, msgs)
|
||||
s.Require().NoError(err)
|
||||
return tx
|
||||
},
|
||||
@ -45,12 +45,12 @@ func (s *MEVTestSuite) TestIsAuctionTx() {
|
||||
{
|
||||
"valid auction bid tx",
|
||||
func() sdk.Tx {
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := []sdk.Msg{msgAuctionBid}
|
||||
|
||||
tx, err := testutils.CreateTx(s.encCfg.TxConfig, s.accounts[0], 0, 0, msgs)
|
||||
tx, err := testutils.CreateTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 0, msgs)
|
||||
s.Require().NoError(err)
|
||||
return tx
|
||||
},
|
||||
@ -60,15 +60,15 @@ func (s *MEVTestSuite) TestIsAuctionTx() {
|
||||
{
|
||||
"tx with multiple MsgAuctionBid messages",
|
||||
func() sdk.Tx {
|
||||
bid1, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
bid1, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
bid2, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 1, 2)
|
||||
bid2, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 1, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := []sdk.Msg{bid1, bid2}
|
||||
|
||||
tx, err := testutils.CreateTx(s.encCfg.TxConfig, s.accounts[0], 0, 0, msgs)
|
||||
tx, err := testutils.CreateTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 0, msgs)
|
||||
s.Require().NoError(err)
|
||||
return tx
|
||||
},
|
||||
@ -81,7 +81,7 @@ func (s *MEVTestSuite) TestIsAuctionTx() {
|
||||
s.Run(tc.name, func() {
|
||||
tx := tc.createTx()
|
||||
|
||||
bidInfo, err := s.config.GetAuctionBidInfo(tx)
|
||||
bidInfo, err := s.Config.GetAuctionBidInfo(tx)
|
||||
|
||||
s.Require().Equal(tc.isAuctionTx, bidInfo != nil)
|
||||
if tc.expectedError {
|
||||
@ -104,12 +104,12 @@ func (s *MEVTestSuite) TestGetTransactionSigners() {
|
||||
"normal auction tx",
|
||||
func() sdk.Tx {
|
||||
tx, err := testutils.CreateAuctionTxWithSigners(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin("stake", math.NewInt(100)),
|
||||
1,
|
||||
0,
|
||||
s.accounts[0:1],
|
||||
s.Accounts[0:1],
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
@ -117,7 +117,7 @@ func (s *MEVTestSuite) TestGetTransactionSigners() {
|
||||
},
|
||||
[]map[string]struct{}{
|
||||
{
|
||||
s.accounts[0].Address.String(): {},
|
||||
s.Accounts[0].Address.String(): {},
|
||||
},
|
||||
},
|
||||
false,
|
||||
@ -125,7 +125,7 @@ func (s *MEVTestSuite) TestGetTransactionSigners() {
|
||||
{
|
||||
"normal sdk tx",
|
||||
func() sdk.Tx {
|
||||
tx, err := testutils.CreateRandomTx(s.encCfg.TxConfig, s.accounts[0], 0, 10, 0, 0)
|
||||
tx, err := testutils.CreateRandomTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 10, 0, 0)
|
||||
s.Require().NoError(err)
|
||||
|
||||
return tx
|
||||
@ -137,12 +137,12 @@ func (s *MEVTestSuite) TestGetTransactionSigners() {
|
||||
"multiple signers on auction tx",
|
||||
func() sdk.Tx {
|
||||
tx, err := testutils.CreateAuctionTxWithSigners(
|
||||
s.encCfg.TxConfig,
|
||||
s.accounts[0],
|
||||
s.EncCfg.TxConfig,
|
||||
s.Accounts[0],
|
||||
sdk.NewCoin("stake", math.NewInt(100)),
|
||||
1,
|
||||
0,
|
||||
s.accounts[0:3],
|
||||
s.Accounts[0:3],
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
|
||||
@ -150,13 +150,13 @@ func (s *MEVTestSuite) TestGetTransactionSigners() {
|
||||
},
|
||||
[]map[string]struct{}{
|
||||
{
|
||||
s.accounts[0].Address.String(): {},
|
||||
s.Accounts[0].Address.String(): {},
|
||||
},
|
||||
{
|
||||
s.accounts[1].Address.String(): {},
|
||||
s.Accounts[1].Address.String(): {},
|
||||
},
|
||||
{
|
||||
s.accounts[2].Address.String(): {},
|
||||
s.Accounts[2].Address.String(): {},
|
||||
},
|
||||
},
|
||||
false,
|
||||
@ -167,7 +167,7 @@ func (s *MEVTestSuite) TestGetTransactionSigners() {
|
||||
s.Run(tc.name, func() {
|
||||
tx := tc.createTx()
|
||||
|
||||
bidInfo, _ := s.config.GetAuctionBidInfo(tx)
|
||||
bidInfo, _ := s.Config.GetAuctionBidInfo(tx)
|
||||
if tc.expectedError {
|
||||
s.Require().Nil(bidInfo)
|
||||
} else {
|
||||
@ -186,10 +186,10 @@ func (s *MEVTestSuite) TestWrapBundleTransaction() {
|
||||
{
|
||||
"normal sdk tx",
|
||||
func() (sdk.Tx, []byte) {
|
||||
tx, err := testutils.CreateRandomTx(s.encCfg.TxConfig, s.accounts[0], 0, 1, 0, 0)
|
||||
tx, err := testutils.CreateRandomTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 1, 0, 0)
|
||||
s.Require().NoError(err)
|
||||
|
||||
bz, err := s.encCfg.TxConfig.TxEncoder()(tx)
|
||||
bz, err := s.EncCfg.TxConfig.TxEncoder()(tx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
return tx, bz
|
||||
@ -212,16 +212,16 @@ func (s *MEVTestSuite) TestWrapBundleTransaction() {
|
||||
s.Run(tc.name, func() {
|
||||
tx, bz := tc.createBundleTx()
|
||||
|
||||
wrappedTx, err := s.config.WrapBundleTransaction(bz)
|
||||
wrappedTx, err := s.Config.WrapBundleTransaction(bz)
|
||||
if tc.expectedError {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
s.Require().NoError(err)
|
||||
|
||||
txBytes, err := s.encCfg.TxConfig.TxEncoder()(tx)
|
||||
txBytes, err := s.EncCfg.TxConfig.TxEncoder()(tx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
wrappedTxBytes, err := s.encCfg.TxConfig.TxEncoder()(wrappedTx)
|
||||
wrappedTxBytes, err := s.EncCfg.TxConfig.TxEncoder()(wrappedTx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(txBytes, wrappedTxBytes)
|
||||
@ -241,7 +241,7 @@ func (s *MEVTestSuite) TestGetBidder() {
|
||||
{
|
||||
"normal sdk tx",
|
||||
func() sdk.Tx {
|
||||
tx, err := testutils.CreateRandomTx(s.encCfg.TxConfig, s.accounts[0], 0, 1, 0, 0)
|
||||
tx, err := testutils.CreateRandomTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 1, 0, 0)
|
||||
s.Require().NoError(err)
|
||||
|
||||
return tx
|
||||
@ -253,31 +253,31 @@ func (s *MEVTestSuite) TestGetBidder() {
|
||||
{
|
||||
"valid auction tx",
|
||||
func() sdk.Tx {
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := []sdk.Msg{msgAuctionBid}
|
||||
|
||||
tx, err := testutils.CreateTx(s.encCfg.TxConfig, s.accounts[0], 0, 0, msgs)
|
||||
tx, err := testutils.CreateTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 0, msgs)
|
||||
s.Require().NoError(err)
|
||||
return tx
|
||||
},
|
||||
s.accounts[0].Address.String(),
|
||||
s.Accounts[0].Address.String(),
|
||||
false,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"invalid auction tx",
|
||||
func() sdk.Tx {
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
randomMsg := testutils.CreateRandomMsgs(s.accounts[0].Address, 1)[0]
|
||||
randomMsg := testutils.CreateRandomMsgs(s.Accounts[0].Address, 1)[0]
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := []sdk.Msg{msgAuctionBid, randomMsg}
|
||||
|
||||
tx, err := testutils.CreateTx(s.encCfg.TxConfig, s.accounts[0], 0, 0, msgs)
|
||||
tx, err := testutils.CreateTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 0, msgs)
|
||||
s.Require().NoError(err)
|
||||
return tx
|
||||
},
|
||||
@ -291,7 +291,7 @@ func (s *MEVTestSuite) TestGetBidder() {
|
||||
s.Run(tc.name, func() {
|
||||
tx := tc.createTx()
|
||||
|
||||
bidInfo, err := s.config.GetAuctionBidInfo(tx)
|
||||
bidInfo, err := s.Config.GetAuctionBidInfo(tx)
|
||||
if tc.expectedError {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
@ -316,7 +316,7 @@ func (s *MEVTestSuite) TestGetBid() {
|
||||
{
|
||||
"normal sdk tx",
|
||||
func() sdk.Tx {
|
||||
tx, err := testutils.CreateRandomTx(s.encCfg.TxConfig, s.accounts[0], 0, 1, 0, 0)
|
||||
tx, err := testutils.CreateRandomTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 1, 0, 0)
|
||||
s.Require().NoError(err)
|
||||
|
||||
return tx
|
||||
@ -328,12 +328,12 @@ func (s *MEVTestSuite) TestGetBid() {
|
||||
{
|
||||
"valid auction tx",
|
||||
func() sdk.Tx {
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := []sdk.Msg{msgAuctionBid}
|
||||
|
||||
tx, err := testutils.CreateTx(s.encCfg.TxConfig, s.accounts[0], 0, 0, msgs)
|
||||
tx, err := testutils.CreateTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 0, msgs)
|
||||
s.Require().NoError(err)
|
||||
return tx
|
||||
},
|
||||
@ -344,15 +344,15 @@ func (s *MEVTestSuite) TestGetBid() {
|
||||
{
|
||||
"invalid auction tx",
|
||||
func() sdk.Tx {
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
randomMsg := testutils.CreateRandomMsgs(s.accounts[0].Address, 1)[0]
|
||||
randomMsg := testutils.CreateRandomMsgs(s.Accounts[0].Address, 1)[0]
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := []sdk.Msg{msgAuctionBid, randomMsg}
|
||||
|
||||
tx, err := testutils.CreateTx(s.encCfg.TxConfig, s.accounts[0], 0, 0, msgs)
|
||||
tx, err := testutils.CreateTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 0, msgs)
|
||||
s.Require().NoError(err)
|
||||
return tx
|
||||
},
|
||||
@ -366,7 +366,7 @@ func (s *MEVTestSuite) TestGetBid() {
|
||||
s.Run(tc.name, func() {
|
||||
tx := tc.createTx()
|
||||
|
||||
bidInfo, err := s.config.GetAuctionBidInfo(tx)
|
||||
bidInfo, err := s.Config.GetAuctionBidInfo(tx)
|
||||
if tc.expectedError {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
@ -390,7 +390,7 @@ func (s *MEVTestSuite) TestGetBundledTransactions() {
|
||||
{
|
||||
"normal sdk tx",
|
||||
func() (sdk.Tx, [][]byte) {
|
||||
tx, err := testutils.CreateRandomTx(s.encCfg.TxConfig, s.accounts[0], 0, 1, 0, 0)
|
||||
tx, err := testutils.CreateRandomTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 1, 0, 0)
|
||||
s.Require().NoError(err)
|
||||
|
||||
return tx, nil
|
||||
@ -401,12 +401,12 @@ func (s *MEVTestSuite) TestGetBundledTransactions() {
|
||||
{
|
||||
"valid auction tx",
|
||||
func() (sdk.Tx, [][]byte) {
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := []sdk.Msg{msgAuctionBid}
|
||||
|
||||
tx, err := testutils.CreateTx(s.encCfg.TxConfig, s.accounts[0], 0, 0, msgs)
|
||||
tx, err := testutils.CreateTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 0, msgs)
|
||||
s.Require().NoError(err)
|
||||
return tx, msgAuctionBid.Transactions
|
||||
},
|
||||
@ -416,15 +416,15 @@ func (s *MEVTestSuite) TestGetBundledTransactions() {
|
||||
{
|
||||
"invalid auction tx",
|
||||
func() (sdk.Tx, [][]byte) {
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
randomMsg := testutils.CreateRandomMsgs(s.accounts[0].Address, 1)[0]
|
||||
randomMsg := testutils.CreateRandomMsgs(s.Accounts[0].Address, 1)[0]
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := []sdk.Msg{msgAuctionBid, randomMsg}
|
||||
|
||||
tx, err := testutils.CreateTx(s.encCfg.TxConfig, s.accounts[0], 0, 0, msgs)
|
||||
tx, err := testutils.CreateTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 0, msgs)
|
||||
s.Require().NoError(err)
|
||||
return tx, nil
|
||||
},
|
||||
@ -437,7 +437,7 @@ func (s *MEVTestSuite) TestGetBundledTransactions() {
|
||||
s.Run(tc.name, func() {
|
||||
tx, expectedBundledTxs := tc.createTx()
|
||||
|
||||
bidInfo, err := s.config.GetAuctionBidInfo(tx)
|
||||
bidInfo, err := s.Config.GetAuctionBidInfo(tx)
|
||||
if tc.expectedError {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
@ -462,7 +462,7 @@ func (s *MEVTestSuite) TestGetTimeout() {
|
||||
{
|
||||
"normal sdk tx",
|
||||
func() sdk.Tx {
|
||||
tx, err := testutils.CreateRandomTx(s.encCfg.TxConfig, s.accounts[0], 0, 1, 1, 0)
|
||||
tx, err := testutils.CreateRandomTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 1, 1, 0)
|
||||
s.Require().NoError(err)
|
||||
|
||||
return tx
|
||||
@ -474,12 +474,12 @@ func (s *MEVTestSuite) TestGetTimeout() {
|
||||
{
|
||||
"valid auction tx",
|
||||
func() sdk.Tx {
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := []sdk.Msg{msgAuctionBid}
|
||||
|
||||
tx, err := testutils.CreateTx(s.encCfg.TxConfig, s.accounts[0], 0, 10, msgs)
|
||||
tx, err := testutils.CreateTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 10, msgs)
|
||||
s.Require().NoError(err)
|
||||
return tx
|
||||
},
|
||||
@ -490,15 +490,15 @@ func (s *MEVTestSuite) TestGetTimeout() {
|
||||
{
|
||||
"invalid auction tx",
|
||||
func() sdk.Tx {
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.encCfg.TxConfig, s.accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
msgAuctionBid, err := testutils.CreateMsgAuctionBid(s.EncCfg.TxConfig, s.Accounts[0], sdk.NewInt64Coin("stake", 100), 0, 2)
|
||||
s.Require().NoError(err)
|
||||
|
||||
randomMsg := testutils.CreateRandomMsgs(s.accounts[0].Address, 1)[0]
|
||||
randomMsg := testutils.CreateRandomMsgs(s.Accounts[0].Address, 1)[0]
|
||||
s.Require().NoError(err)
|
||||
|
||||
msgs := []sdk.Msg{msgAuctionBid, randomMsg}
|
||||
|
||||
tx, err := testutils.CreateTx(s.encCfg.TxConfig, s.accounts[0], 0, 10, msgs)
|
||||
tx, err := testutils.CreateTx(s.EncCfg.TxConfig, s.Accounts[0], 0, 10, msgs)
|
||||
s.Require().NoError(err)
|
||||
return tx
|
||||
},
|
||||
@ -512,7 +512,7 @@ func (s *MEVTestSuite) TestGetTimeout() {
|
||||
s.Run(tc.name, func() {
|
||||
tx := tc.createTx()
|
||||
|
||||
bidInfo, err := s.config.GetAuctionBidInfo(tx)
|
||||
bidInfo, err := s.Config.GetAuctionBidInfo(tx)
|
||||
if tc.expectedError {
|
||||
s.Require().Error(err)
|
||||
} else {
|
||||
|
||||
@ -1,11 +1,6 @@
|
||||
package mev
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/skip-mev/block-sdk/block"
|
||||
"github.com/skip-mev/block-sdk/block/base"
|
||||
)
|
||||
|
||||
@ -14,8 +9,6 @@ const (
|
||||
LaneName = "mev"
|
||||
)
|
||||
|
||||
var _ MEVLaneI = (*MEVLane)(nil)
|
||||
|
||||
// MEVLane defines a MEV (Maximal Extracted Value) auction lane. The MEV auction lane
|
||||
// hosts transactions that want to bid for inclusion at the top of the next block.
|
||||
// The MEV auction lane stores bid transactions that are sorted by their bid price.
|
||||
@ -23,14 +16,6 @@ var _ MEVLaneI = (*MEVLane)(nil)
|
||||
// The bundled transactions of the selected bid transaction are also included in the
|
||||
// next block.
|
||||
type (
|
||||
// MEVLaneI defines the interface for the mev auction lane. This interface
|
||||
// is utilized by both the x/auction module and the checkTx handler.
|
||||
MEVLaneI interface { //nolint
|
||||
block.Lane
|
||||
Factory
|
||||
GetTopAuctionTx(ctx context.Context) sdk.Tx
|
||||
}
|
||||
|
||||
MEVLane struct { //nolint
|
||||
*base.BaseLane
|
||||
|
||||
|
||||
@ -1,117 +1,35 @@
|
||||
package mev_test
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
signer_extraction "github.com/skip-mev/block-sdk/adapters/signer_extraction_adapter"
|
||||
"github.com/skip-mev/block-sdk/block/base"
|
||||
"github.com/skip-mev/block-sdk/block/utils"
|
||||
"github.com/skip-mev/block-sdk/lanes/mev"
|
||||
testutils "github.com/skip-mev/block-sdk/testutils"
|
||||
"github.com/skip-mev/block-sdk/lanes/mev/testutils"
|
||||
)
|
||||
|
||||
type MEVTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
encCfg testutils.EncodingConfig
|
||||
config mev.Factory
|
||||
ctx sdk.Context
|
||||
accounts []testutils.Account
|
||||
gasTokenDenom string
|
||||
testutils.MEVLaneTestSuiteBase
|
||||
}
|
||||
|
||||
func TestMEVTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(MEVTestSuite))
|
||||
}
|
||||
|
||||
func (s *MEVTestSuite) SetupTest() {
|
||||
// Init encoding config
|
||||
s.encCfg = testutils.CreateTestEncodingConfig()
|
||||
s.config = mev.NewDefaultAuctionFactory(s.encCfg.TxConfig.TxDecoder(), signer_extraction.NewDefaultAdapter())
|
||||
testCtx := testutil.DefaultContextWithDB(s.T(), storetypes.NewKVStoreKey("test"), storetypes.NewTransientStoreKey("transient_test"))
|
||||
s.ctx = testCtx.Ctx.WithExecMode(sdk.ExecModePrepareProposal)
|
||||
s.ctx = s.ctx.WithBlockHeight(1)
|
||||
|
||||
// Init accounts
|
||||
random := rand.New(rand.NewSource(time.Now().Unix()))
|
||||
s.accounts = testutils.RandomAccounts(random, 10)
|
||||
s.gasTokenDenom = "stake"
|
||||
}
|
||||
|
||||
func (s *MEVTestSuite) initLane(
|
||||
maxBlockSpace math.LegacyDec,
|
||||
expectedExecution map[sdk.Tx]bool,
|
||||
) *mev.MEVLane {
|
||||
config := base.NewLaneConfig(
|
||||
log.NewNopLogger(),
|
||||
s.encCfg.TxConfig.TxEncoder(),
|
||||
s.encCfg.TxConfig.TxDecoder(),
|
||||
s.setUpAnteHandler(expectedExecution),
|
||||
signer_extraction.NewDefaultAdapter(),
|
||||
maxBlockSpace,
|
||||
)
|
||||
|
||||
factory := mev.NewDefaultAuctionFactory(s.encCfg.TxConfig.TxDecoder(), signer_extraction.NewDefaultAdapter())
|
||||
return mev.NewMEVLane(config, factory, factory.MatchHandler())
|
||||
}
|
||||
|
||||
func (s *MEVTestSuite) setUpAnteHandler(expectedExecution map[sdk.Tx]bool) sdk.AnteHandler {
|
||||
txCache := make(map[string]bool)
|
||||
for tx, pass := range expectedExecution {
|
||||
bz, err := s.encCfg.TxConfig.TxEncoder()(tx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
hash := sha256.Sum256(bz)
|
||||
hashStr := hex.EncodeToString(hash[:])
|
||||
txCache[hashStr] = pass
|
||||
}
|
||||
|
||||
anteHandler := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) {
|
||||
bz, err := s.encCfg.TxConfig.TxEncoder()(tx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
hash := sha256.Sum256(bz)
|
||||
hashStr := hex.EncodeToString(hash[:])
|
||||
|
||||
pass, found := txCache[hashStr]
|
||||
if !found {
|
||||
return ctx, fmt.Errorf("tx not found")
|
||||
}
|
||||
|
||||
if pass {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
return ctx, fmt.Errorf("tx failed")
|
||||
}
|
||||
|
||||
return anteHandler
|
||||
}
|
||||
|
||||
func (s *MEVTestSuite) getTxSize(tx sdk.Tx) int64 {
|
||||
txBz, err := s.encCfg.TxConfig.TxEncoder()(tx)
|
||||
txBz, err := s.EncCfg.TxConfig.TxEncoder()(tx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
return int64(len(txBz))
|
||||
}
|
||||
|
||||
func (s *MEVTestSuite) compare(first, second []sdk.Tx) {
|
||||
firstBytes, err := utils.GetEncodedTxs(s.encCfg.TxConfig.TxEncoder(), first)
|
||||
firstBytes, err := utils.GetEncodedTxs(s.EncCfg.TxConfig.TxEncoder(), first)
|
||||
s.Require().NoError(err)
|
||||
|
||||
secondBytes, err := utils.GetEncodedTxs(s.encCfg.TxConfig.TxEncoder(), second)
|
||||
secondBytes, err := utils.GetEncodedTxs(s.EncCfg.TxConfig.TxEncoder(), second)
|
||||
s.Require().NoError(err)
|
||||
|
||||
s.Require().Equal(firstBytes, secondBytes)
|
||||
|
||||
95
lanes/mev/testutils/testutil.go
Normal file
95
lanes/mev/testutils/testutil.go
Normal file
@ -0,0 +1,95 @@
|
||||
package testutils
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/math"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
signer_extraction "github.com/skip-mev/block-sdk/adapters/signer_extraction_adapter"
|
||||
"github.com/skip-mev/block-sdk/block/base"
|
||||
"github.com/skip-mev/block-sdk/lanes/mev"
|
||||
testutils "github.com/skip-mev/block-sdk/testutils"
|
||||
)
|
||||
|
||||
type MEVLaneTestSuiteBase struct {
|
||||
suite.Suite
|
||||
|
||||
EncCfg testutils.EncodingConfig
|
||||
Config mev.Factory
|
||||
Ctx sdk.Context
|
||||
Accounts []testutils.Account
|
||||
GasTokenDenom string
|
||||
}
|
||||
|
||||
func (s *MEVLaneTestSuiteBase) SetupTest() {
|
||||
// Init encoding config
|
||||
s.EncCfg = testutils.CreateTestEncodingConfig()
|
||||
s.Config = mev.NewDefaultAuctionFactory(s.EncCfg.TxConfig.TxDecoder(), signer_extraction.NewDefaultAdapter())
|
||||
testCtx := testutil.DefaultContextWithDB(s.T(), storetypes.NewKVStoreKey("test"), storetypes.NewTransientStoreKey("transient_test"))
|
||||
s.Ctx = testCtx.Ctx.WithExecMode(sdk.ExecModePrepareProposal)
|
||||
s.Ctx = s.Ctx.WithBlockHeight(1)
|
||||
|
||||
// Init accounts
|
||||
random := rand.New(rand.NewSource(time.Now().Unix()))
|
||||
s.Accounts = testutils.RandomAccounts(random, 10)
|
||||
s.GasTokenDenom = "stake"
|
||||
}
|
||||
|
||||
func (s *MEVLaneTestSuiteBase) InitLane(
|
||||
maxBlockSpace math.LegacyDec,
|
||||
expectedExecution map[sdk.Tx]bool,
|
||||
) *mev.MEVLane {
|
||||
config := base.NewLaneConfig(
|
||||
log.NewNopLogger(),
|
||||
s.EncCfg.TxConfig.TxEncoder(),
|
||||
s.EncCfg.TxConfig.TxDecoder(),
|
||||
s.SetUpAnteHandler(expectedExecution),
|
||||
signer_extraction.NewDefaultAdapter(),
|
||||
maxBlockSpace,
|
||||
)
|
||||
|
||||
factory := mev.NewDefaultAuctionFactory(s.EncCfg.TxConfig.TxDecoder(), signer_extraction.NewDefaultAdapter())
|
||||
return mev.NewMEVLane(config, factory, factory.MatchHandler())
|
||||
}
|
||||
|
||||
func (s *MEVLaneTestSuiteBase) SetUpAnteHandler(expectedExecution map[sdk.Tx]bool) sdk.AnteHandler {
|
||||
txCache := make(map[string]bool)
|
||||
for tx, pass := range expectedExecution {
|
||||
bz, err := s.EncCfg.TxConfig.TxEncoder()(tx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
hash := sha256.Sum256(bz)
|
||||
hashStr := hex.EncodeToString(hash[:])
|
||||
txCache[hashStr] = pass
|
||||
}
|
||||
|
||||
anteHandler := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (newCtx sdk.Context, err error) {
|
||||
bz, err := s.EncCfg.TxConfig.TxEncoder()(tx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
hash := sha256.Sum256(bz)
|
||||
hashStr := hex.EncodeToString(hash[:])
|
||||
|
||||
pass, found := txCache[hashStr]
|
||||
if !found {
|
||||
return ctx, fmt.Errorf("tx not found")
|
||||
}
|
||||
|
||||
if pass {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
return ctx, fmt.Errorf("tx failed")
|
||||
}
|
||||
|
||||
return anteHandler
|
||||
}
|
||||
@ -42,10 +42,10 @@ import (
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
|
||||
"github.com/skip-mev/block-sdk/abci"
|
||||
"github.com/skip-mev/block-sdk/abci/checktx"
|
||||
"github.com/skip-mev/block-sdk/block"
|
||||
"github.com/skip-mev/block-sdk/block/base"
|
||||
service "github.com/skip-mev/block-sdk/block/service"
|
||||
"github.com/skip-mev/block-sdk/lanes/mev"
|
||||
auctionkeeper "github.com/skip-mev/block-sdk/x/auction/keeper"
|
||||
blocksdkkeeper "github.com/skip-mev/block-sdk/x/blocksdk/keeper"
|
||||
)
|
||||
@ -93,7 +93,7 @@ type TestApp struct {
|
||||
FeeGrantKeeper feegrantkeeper.Keeper
|
||||
|
||||
// custom checkTx handler
|
||||
checkTxHandler mev.CheckTx
|
||||
checkTxHandler checktx.CheckTx
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -276,12 +276,18 @@ func New(
|
||||
|
||||
// Step 7: Set the custom CheckTx handler on BaseApp. This is only required if you
|
||||
// use the MEV lane.
|
||||
checkTxHandler := mev.NewCheckTxHandler(
|
||||
mevCheckTx := checktx.NewMEVCheckTxHandler(
|
||||
app.App,
|
||||
app.txConfig.TxDecoder(),
|
||||
mevLane,
|
||||
anteHandler,
|
||||
app.App.CheckTx,
|
||||
)
|
||||
checkTxHandler := checktx.NewMempoolParityCheckTx(
|
||||
app.Logger(), mempool,
|
||||
app.txConfig.TxDecoder(), mevCheckTx.CheckTx(),
|
||||
)
|
||||
|
||||
app.SetCheckTx(checkTxHandler.CheckTx())
|
||||
|
||||
// ---------------------------------------------------------------------------- //
|
||||
@ -325,7 +331,7 @@ func (app *TestApp) CheckTx(req *cometabci.RequestCheckTx) (*cometabci.ResponseC
|
||||
}
|
||||
|
||||
// SetCheckTx sets the checkTxHandler for the app.
|
||||
func (app *TestApp) SetCheckTx(handler mev.CheckTx) {
|
||||
func (app *TestApp) SetCheckTx(handler checktx.CheckTx) {
|
||||
app.checkTxHandler = handler
|
||||
}
|
||||
|
||||
|
||||
302
tests/integration/network/mempool_test.go
Normal file
302
tests/integration/network/mempool_test.go
Normal file
@ -0,0 +1,302 @@
|
||||
package integration_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
cmthttp "github.com/cometbft/cometbft/rpc/client/http"
|
||||
cmttypes "github.com/cometbft/cometbft/types"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"github.com/skip-mev/chaintestutil/account"
|
||||
"github.com/skip-mev/chaintestutil/network"
|
||||
|
||||
blockservicetypes "github.com/skip-mev/block-sdk/block/service/types"
|
||||
auctiontypes "github.com/skip-mev/block-sdk/x/auction/types"
|
||||
)
|
||||
|
||||
const (
|
||||
free = "free"
|
||||
base = "base"
|
||||
mev = "mev"
|
||||
)
|
||||
|
||||
var cdc *codec.ProtoCodec
|
||||
|
||||
func init() {
|
||||
ir := codectypes.NewInterfaceRegistry()
|
||||
|
||||
authtypes.RegisterInterfaces(ir)
|
||||
cryptocodec.RegisterInterfaces(ir)
|
||||
cdc = codec.NewProtoCodec(ir)
|
||||
}
|
||||
|
||||
// TestLanedMempool tests that the block-sdk mempool is properly synced w/ comet's mempool
|
||||
func (s *NetworkTestSuite) TestLanedMempoolSyncWithComet() {
|
||||
cc, closefn, err := s.NetworkSuite.GetGRPC()
|
||||
s.Require().NoError(err)
|
||||
defer closefn()
|
||||
|
||||
tmClient, err := s.NetworkSuite.GetCometClient()
|
||||
s.Require().NoError(err)
|
||||
|
||||
blockClient := blockservicetypes.NewServiceClient(cc)
|
||||
|
||||
ctx, closeCtx := context.WithTimeout(context.Background(), 1*time.Minute)
|
||||
defer closeCtx()
|
||||
val := s.NetworkSuite.Network.Validators[0].ValAddress
|
||||
s.Require().NoError(err)
|
||||
acc := *s.Accounts[0]
|
||||
|
||||
s.Run("test free-lane sync", func() {
|
||||
s.Run("all valid txs", func() {
|
||||
// create a bunch of delegation txs and check the app-mempool v. comet-mempool
|
||||
msg := createFreeTx(acc.Address(), val, sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(10)))
|
||||
s.Require().NoError(s.checkParity(ctx, tmClient, blockClient, cc, acc, free, msg))
|
||||
})
|
||||
|
||||
s.Run("bid Verify invalidates later tx Verify", func() {
|
||||
// create a new account
|
||||
zeroAccount := account.NewAccount()
|
||||
|
||||
status, err := tmClient.Status(ctx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// initialize the account w/ enough for a single tx
|
||||
send := banktypes.NewMsgSend(acc.Address(), zeroAccount.Address(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(3000100))))
|
||||
|
||||
seq, _, err := getAccount(ctx, authtypes.NewQueryClient(cc), acc)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// send the tx (pay for fees)
|
||||
tx, err := s.NetworkSuite.CreateTxBytes(ctx, network.TxGenInfo{
|
||||
Account: acc,
|
||||
GasLimit: 1000000,
|
||||
TimeoutHeight: uint64(status.SyncInfo.LatestBlockHeight) + 1,
|
||||
Fee: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000000)),
|
||||
Sequence: seq,
|
||||
OverrideSequence: true,
|
||||
}, send)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// commit tx
|
||||
res, err := tmClient.BroadcastTxCommit(ctx, tx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(uint32(0), res.TxResult.Code)
|
||||
|
||||
// create a delegation tx -> this should spend fees in zeroAccount
|
||||
msg := banktypes.NewMsgSend(zeroAccount.Address(), acc.Address(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(1))))
|
||||
|
||||
// update the balance of zeroAccount to pay for the next tx
|
||||
updateMsg := banktypes.NewMsgSend(acc.Address(), zeroAccount.Address(), sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(1000000))))
|
||||
|
||||
status, err = tmClient.Status(ctx)
|
||||
s.Require().NoError(err)
|
||||
nextHeight := uint64(status.SyncInfo.LatestBlockHeight) + 1
|
||||
|
||||
// pay for fees of next tx for zeroAccount (account for bid sequence)
|
||||
tx2, err := s.NetworkSuite.CreateTxBytes(ctx, network.TxGenInfo{
|
||||
Account: acc,
|
||||
GasLimit: 1000000,
|
||||
TimeoutHeight: nextHeight,
|
||||
Fee: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000000)),
|
||||
Sequence: seq + 2,
|
||||
OverrideSequence: true,
|
||||
}, updateMsg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
seq2, _, err := getAccount(ctx, authtypes.NewQueryClient(cc), *zeroAccount)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// spends all funds in account on fee deduction -> fees are refilled after bid
|
||||
txToWrap, err := s.NetworkSuite.CreateTxBytes(ctx, network.TxGenInfo{
|
||||
Account: *zeroAccount,
|
||||
GasLimit: 1000000,
|
||||
TimeoutHeight: 100000000,
|
||||
Fee: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 3000000)),
|
||||
Sequence: seq2,
|
||||
OverrideSequence: true,
|
||||
}, msg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// first delegate tx (just used to increment sequence)
|
||||
firstDelegateTx, err := s.NetworkSuite.CreateTxBytes(ctx, network.TxGenInfo{
|
||||
Account: *zeroAccount,
|
||||
GasLimit: 1000000,
|
||||
TimeoutHeight: 100000000,
|
||||
Fee: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000000)),
|
||||
Sequence: seq2,
|
||||
OverrideSequence: true,
|
||||
}, msg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// ordered after bid, and shld fail in PrepareProposal as there will be no funds to pay (will be removed from lane)
|
||||
secondDelegateTx, err := s.NetworkSuite.CreateTxBytes(ctx, network.TxGenInfo{
|
||||
Account: *zeroAccount,
|
||||
GasLimit: 1000000,
|
||||
TimeoutHeight: 100000000,
|
||||
Fee: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000000)),
|
||||
Sequence: seq2 + 1,
|
||||
OverrideSequence: true,
|
||||
}, msg)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// create a bid wrapping firstDelegateTx, tx2 -> i.e spend funds in zeroAccount and refill
|
||||
bid := auctiontypes.NewMsgAuctionBid(acc.Address(), sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(1000000)), [][]byte{txToWrap, tx2})
|
||||
bidTx, err := s.NetworkSuite.CreateTxBytes(ctx, network.TxGenInfo{
|
||||
Account: acc,
|
||||
GasLimit: 1000000,
|
||||
TimeoutHeight: nextHeight,
|
||||
Fee: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000000)),
|
||||
Sequence: seq + 1,
|
||||
OverrideSequence: true,
|
||||
}, bid)
|
||||
s.Require().NoError(err)
|
||||
|
||||
// broadcast txs
|
||||
resp, err := tmClient.BroadcastTxSync(ctx, bidTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(uint32(0), resp.Code)
|
||||
|
||||
resp, err = tmClient.BroadcastTxSync(ctx, firstDelegateTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(uint32(0), resp.Code)
|
||||
|
||||
resp, err = tmClient.BroadcastTxSync(ctx, secondDelegateTx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(uint32(0), resp.Code)
|
||||
|
||||
// wait for commit of bid
|
||||
s.Require().NoError(waitForTxCommit(ctx, tmClient, cmttypes.Tx(bidTx).Hash()))
|
||||
|
||||
// check mempool size
|
||||
txs, err := tmClient.NumUnconfirmedTxs(ctx)
|
||||
s.Require().NoError(err)
|
||||
|
||||
cmtTxs := uint64(txs.Total)
|
||||
|
||||
// check app mempool size
|
||||
appTxDist, err := blockClient.GetTxDistribution(ctx, &blockservicetypes.GetTxDistributionRequest{})
|
||||
s.Require().NoError(err)
|
||||
|
||||
// check parity
|
||||
appTxs := 0
|
||||
for _, tx := range appTxDist.Distribution {
|
||||
appTxs += int(tx)
|
||||
}
|
||||
|
||||
s.Require().Equal(appTxs, int(cmtTxs))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func createFreeTx(delegator sdk.AccAddress, validator sdk.ValAddress, amount sdk.Coin) sdk.Msg {
|
||||
return stakingtypes.NewMsgDelegate(delegator.String(), validator.String(), amount)
|
||||
}
|
||||
|
||||
func getAccount(ctx context.Context, cc authtypes.QueryClient, acc account.Account) (uint64, uint64, error) {
|
||||
resp, err := cc.Account(ctx, &authtypes.QueryAccountRequest{Address: acc.Address().String()})
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
var accI sdk.AccountI
|
||||
if err := cdc.UnpackAny(resp.Account, &accI); err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
return accI.GetSequence(), accI.GetAccountNumber(), nil
|
||||
}
|
||||
|
||||
func (s *NetworkTestSuite) checkParity(
|
||||
ctx context.Context, tmClient *cmthttp.HTTP, blockClient blockservicetypes.ServiceClient,
|
||||
cc *grpc.ClientConn, acc account.Account, lane string, msg sdk.Msg,
|
||||
) error {
|
||||
seq, _, err := getAccount(ctx, authtypes.NewQueryClient(cc), acc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := tmClient.Status(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
height := res.SyncInfo.LatestBlockHeight
|
||||
// send 100 txs to the app and check mempool sizes
|
||||
numTxs := 100
|
||||
txsCh := make(chan []byte, numTxs)
|
||||
done := make(chan struct{})
|
||||
|
||||
// spin GR to wait on tx inclusions
|
||||
go func() {
|
||||
for tx := range txsCh {
|
||||
// check for tx inclusion
|
||||
waitForTxCommit(ctx, tmClient, tx)
|
||||
}
|
||||
close(done)
|
||||
}()
|
||||
|
||||
for i := 0; i < numTxs; i++ {
|
||||
tx, err := s.NetworkSuite.CreateTxBytes(ctx, network.TxGenInfo{
|
||||
Account: acc,
|
||||
GasLimit: 1000000,
|
||||
TimeoutHeight: uint64(height + 10),
|
||||
Fee: sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1000000)),
|
||||
Sequence: seq + uint64(i),
|
||||
OverrideSequence: true,
|
||||
}, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := tmClient.BroadcastTxSync(ctx, tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txsCh <- res.Hash
|
||||
}
|
||||
// all txs are sent
|
||||
close(txsCh)
|
||||
|
||||
// wait for all txs to be included before checking size
|
||||
<-done
|
||||
|
||||
// check comet mempool size
|
||||
txs, err := tmClient.NumUnconfirmedTxs(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmtTxs := uint64(txs.Total)
|
||||
|
||||
// check app mempool size
|
||||
appTxs, err := blockClient.GetTxDistribution(ctx, &blockservicetypes.GetTxDistributionRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmtTxs != appTxs.Distribution[lane] {
|
||||
return fmt.Errorf("mempool size mismatch: %d != %d", cmtTxs, appTxs.Distribution[free])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitForTxCommit(ctx context.Context, client *cmthttp.HTTP, hash []byte) error {
|
||||
_, err := client.Tx(ctx, hash, false)
|
||||
for ; err != nil; _, err = client.Tx(ctx, hash, false) {
|
||||
time.Sleep(time.Millisecond)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -26,8 +26,6 @@ func TestNetworkTestSuite(t *testing.T) {
|
||||
}
|
||||
|
||||
func (s *NetworkTestSuite) TestGetLanes() {
|
||||
s.T().Parallel()
|
||||
|
||||
common := []string{
|
||||
fmt.Sprintf("--%s=json", tmcli.OutputFlag),
|
||||
}
|
||||
@ -6,12 +6,6 @@ import (
|
||||
"os"
|
||||
|
||||
"cosmossdk.io/log"
|
||||
pruningtypes "cosmossdk.io/store/pruning/types"
|
||||
dbm "github.com/cosmos/cosmos-db"
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
"github.com/skip-mev/chaintestutil/network"
|
||||
@ -19,6 +13,18 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
pruningtypes "cosmossdk.io/store/pruning/types"
|
||||
cmtrand "github.com/cometbft/cometbft/libs/rand"
|
||||
dbm "github.com/cosmos/cosmos-db"
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
|
||||
"github.com/skip-mev/chaintestutil/account"
|
||||
|
||||
"github.com/skip-mev/block-sdk/lanes/base"
|
||||
"github.com/skip-mev/block-sdk/lanes/free"
|
||||
"github.com/skip-mev/block-sdk/lanes/mev"
|
||||
@ -27,13 +33,22 @@ import (
|
||||
blocksdktypes "github.com/skip-mev/block-sdk/x/blocksdk/types"
|
||||
)
|
||||
|
||||
// NetworkTestSuite is a test suite for tests that initializes a network instance.
|
||||
var (
|
||||
chainID = "chain-" + cmtrand.NewRand().Str(6)
|
||||
|
||||
genBalance = sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(1000000000000000000))
|
||||
)
|
||||
|
||||
// NetworkTestSuite is a test suite for query tests that initializes a network instance.
|
||||
type NetworkTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
NetworkSuite *network.TestSuite
|
||||
AuctionState auctiontypes.GenesisState
|
||||
BlockSDKState blocksdktypes.GenesisState
|
||||
AuthState authtypes.GenesisState
|
||||
BankState banktypes.GenesisState
|
||||
Accounts []*account.Account
|
||||
}
|
||||
|
||||
// SetupSuite setups the local network with a genesis state.
|
||||
@ -55,6 +70,7 @@ func (nts *NetworkTestSuite) SetupSuite() {
|
||||
}
|
||||
)
|
||||
cfg.AppConstructor = appCons
|
||||
cfg.ChainID = chainID
|
||||
|
||||
updateGenesisConfigState := func(moduleName string, moduleState proto.Message) {
|
||||
buf, err := cfg.Codec.MarshalJSON(moduleState)
|
||||
@ -70,9 +86,51 @@ func (nts *NetworkTestSuite) SetupSuite() {
|
||||
nts.BlockSDKState = populateBlockSDK(r, nts.BlockSDKState)
|
||||
updateGenesisConfigState(blocksdktypes.ModuleName, &nts.BlockSDKState)
|
||||
|
||||
// add genesis accounts
|
||||
nts.Accounts = []*account.Account{
|
||||
account.NewAccount(),
|
||||
}
|
||||
|
||||
require.NoError(nts.T(), cfg.Codec.UnmarshalJSON(cfg.GenesisState[authtypes.ModuleName], &nts.AuthState))
|
||||
require.NoError(nts.T(), cfg.Codec.UnmarshalJSON(cfg.GenesisState[banktypes.ModuleName], &nts.BankState))
|
||||
|
||||
addGenesisAccounts(&nts.AuthState, &nts.BankState, nts.Accounts)
|
||||
|
||||
// update genesis
|
||||
updateGenesisConfigState(authtypes.ModuleName, &nts.AuthState)
|
||||
updateGenesisConfigState(banktypes.ModuleName, &nts.BankState)
|
||||
|
||||
nts.NetworkSuite = network.NewSuite(nts.T(), cfg)
|
||||
}
|
||||
|
||||
// addGenesisAccount adds a genesis account to the auth / bank genesis state.
|
||||
func addGenesisAccounts(authGenState *authtypes.GenesisState, bankGenState *banktypes.GenesisState, accs []*account.Account) {
|
||||
balances := make([]banktypes.Balance, len(accs))
|
||||
accounts := make(authtypes.GenesisAccounts, len(accs))
|
||||
|
||||
// create accounts / update bank state w/ account + gen balance
|
||||
for i, acc := range accs {
|
||||
// base account
|
||||
bacc := authtypes.NewBaseAccount(acc.Address(), acc.PubKey(), 0, 0)
|
||||
|
||||
accounts[i] = bacc
|
||||
balances[i] = banktypes.Balance{
|
||||
Address: acc.Address().String(),
|
||||
Coins: sdk.NewCoins(genBalance),
|
||||
}
|
||||
}
|
||||
|
||||
// update auth state w/ accounts
|
||||
var err error
|
||||
authGenState.Accounts, err = authtypes.PackAccounts(accounts)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// update bank state w/ balances
|
||||
bankGenState.Balances = balances
|
||||
}
|
||||
|
||||
func populateAuction(_ *rand.Rand, auctionState auctiontypes.GenesisState) auctiontypes.GenesisState {
|
||||
// TODO intercept and populate state randomly if desired
|
||||
return auctionState
|
||||
|
||||
Loading…
Reference in New Issue
Block a user