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:
Nikhil Vasan
2023-12-18 18:29:06 -08:00
committed by GitHub
parent 4b6e481c3f
commit b5fe2a772c
16 changed files with 1196 additions and 406 deletions
+175 -175
View File
@@ -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))
})
}
-289
View File
@@ -1,289 +0,0 @@
package mev
import (
"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"
"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
// 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
// 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)
// 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
// CheckTx is baseapp's CheckTx method that checks the validity of a
// transaction.
CheckTx(req *cometabci.RequestCheckTx) (*cometabci.ResponseCheckTx, error)
// Logger is utilized to log errors.
Logger() log.Logger
// 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
// ChainID is utilized to retrieve the chain ID.
ChainID() string
}
)
// NewCheckTxHandler constructs a new CheckTxHandler instance.
func NewCheckTxHandler(
baseApp BaseApp,
txDecoder sdk.TxDecoder,
mevLane MEVLaneI,
anteHandler sdk.AnteHandler,
) *CheckTxHandler {
return &CheckTxHandler{
baseApp: baseApp,
txDecoder: txDecoder,
mevLane: mevLane,
anteHandler: anteHandler,
}
}
// 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. We must verify each bid tx and all of its bundled transactions
// 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 {
return func(req *cometabci.RequestCheckTx) (resp *cometabci.ResponseCheckTx, err error) {
defer func() {
if rec := recover(); rec != nil {
handler.baseApp.Logger().Error(
"panic in check tx handler",
"err", rec,
)
err = fmt.Errorf("panic in check tx handler: %s", rec)
resp = sdkerrors.ResponseCheckTxWithEvents(
err,
0,
0,
nil,
false,
)
}
}()
tx, err := handler.txDecoder(req.Tx)
if err != nil {
handler.baseApp.Logger().Info(
"failed to decode tx",
"err", err,
)
return sdkerrors.ResponseCheckTxWithEvents(
fmt.Errorf("failed to decode tx: %w", err),
0,
0,
nil,
false,
), nil
}
// Attempt to get the bid info of the transaction.
bidInfo, err := handler.mevLane.GetAuctionBidInfo(tx)
if err != nil {
handler.baseApp.Logger().Info(
"failed to get auction bid info",
"err", err,
)
return sdkerrors.ResponseCheckTxWithEvents(
fmt.Errorf("failed to get auction bid info: %w", err),
0,
0,
nil,
false,
), nil
}
// If this is not a bid transaction, we just execute it normally.
if bidInfo == nil {
resp, err := handler.baseApp.CheckTx(req)
if err != nil {
handler.baseApp.Logger().Info(
"failed to execute check tx",
"err", err,
)
}
return resp, err
}
// We attempt to get the latest committed state in order to verify transactions
// as if they were to be executed at the top of the block. After verification, this
// context will be discarded and will not apply any state changes.
ctx := handler.GetContextForBidTx(req)
// Verify the bid transaction.
gasInfo, err := handler.ValidateBidTx(ctx, tx, bidInfo)
if err != nil {
handler.baseApp.Logger().Info(
"invalid bid tx",
"err", err,
"height", ctx.BlockHeight(),
"bid_height", bidInfo.Timeout,
"bidder", bidInfo.Bidder,
"bid", bidInfo.Bid,
"is_recheck_tx", ctx.IsReCheckTx(),
)
// attempt to remove the bid from the MEVLane (if it exists)
if handler.mevLane.Contains(tx) {
if err := handler.mevLane.Remove(tx); err != nil {
handler.baseApp.Logger().Error(
"failed to remove bid transaction from mev-lane",
"err", err,
)
}
}
return sdkerrors.ResponseCheckTxWithEvents(
fmt.Errorf("invalid bid tx: %w", err),
gasInfo.GasWanted,
gasInfo.GasUsed,
nil,
false,
), nil
}
handler.baseApp.Logger().Info(
"valid bid tx",
"height", ctx.BlockHeight(),
"bid_height", bidInfo.Timeout,
"bidder", bidInfo.Bidder,
"bid", bidInfo.Bid,
"inserting tx into mempool", true,
)
// If the bid transaction is valid, we know we can insert it into the mempool for consideration in the next block.
if err := handler.mevLane.Insert(ctx, tx); err != nil {
handler.baseApp.Logger().Info(
"invalid bid tx; failed to insert bid transaction into mempool",
"err", err,
)
return sdkerrors.ResponseCheckTxWithEvents(
fmt.Errorf("invalid bid tx; failed to insert bid transaction into mempool: %w", err),
gasInfo.GasWanted,
gasInfo.GasUsed,
nil,
false,
), nil
}
return &cometabci.ResponseCheckTx{
Code: cometabci.CodeTypeOK,
GasWanted: int64(gasInfo.GasWanted),
GasUsed: int64(gasInfo.GasUsed),
}, nil
}
}
// 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) {
// Verify the bid transaction.
ctx, err := handler.anteHandler(ctx, bidTx, false)
if err != nil {
return sdk.GasInfo{}, fmt.Errorf("invalid bid tx; failed to execute ante handler: %w", err)
}
// Store the gas info and priority of the bid transaction before applying changes with other transactions.
gasInfo := sdk.GasInfo{
GasWanted: ctx.GasMeter().Limit(),
GasUsed: ctx.GasMeter().GasConsumed(),
}
// Verify all of the bundled transactions.
for _, tx := range bidInfo.Transactions {
bundledTx, err := handler.mevLane.WrapBundleTransaction(tx)
if err != nil {
return gasInfo, fmt.Errorf("invalid bid tx; failed to decode bundled tx: %w", err)
}
// bid txs cannot be included in bundled txs
bidInfo, _ := handler.mevLane.GetAuctionBidInfo(bundledTx)
if bidInfo != nil {
return gasInfo, fmt.Errorf("invalid bid tx; bundled tx cannot be a bid tx")
}
if ctx, err = handler.anteHandler(ctx, bundledTx, false); err != nil {
return gasInfo, fmt.Errorf("invalid bid tx; failed to execute bundled transaction: %w", err)
}
}
return gasInfo, nil
}
// GetContextForBidTx is returns the latest committed state and sets the context given
// the checkTx request.
func (handler *CheckTxHandler) 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()
// Create a new context based off of the latest committed state.
header := cmtproto.Header{
Height: handler.baseApp.LastBlockHeight(),
ChainID: handler.baseApp.ChainID(),
}
ctx, _ := sdk.NewContext(ms, header, true, handler.baseApp.Logger()).CacheContext()
// Set the context to the correct checking mode.
switch req.Type {
case cometabci.CheckTxType_New:
ctx = ctx.WithIsCheckTx(true)
case cometabci.CheckTxType_Recheck:
ctx = ctx.WithIsReCheckTx(true)
default:
panic("unknown check tx type")
}
// Set the remaining important context values.
ctx = ctx.
WithTxBytes(req.Tx).
WithEventManager(sdk.NewEventManager()).
WithConsensusParams(handler.baseApp.GetConsensusParams(ctx))
return ctx
}
+56 -56
View File
@@ -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 {
-15
View File
@@ -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
+5 -87
View File
@@ -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
View 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
}