refactor: separate v1 and v2 (VE) (#142)
This commit is contained in:
parent
0e5519baee
commit
5fa7309ca5
286
abci/abci.go
Normal file
286
abci/abci.go
Normal file
@ -0,0 +1,286 @@
|
||||
package abci
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
"github.com/cometbft/cometbft/libs/log"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool"
|
||||
"github.com/skip-mev/pob/mempool"
|
||||
)
|
||||
|
||||
type (
|
||||
Mempool interface {
|
||||
sdkmempool.Mempool
|
||||
|
||||
// The AuctionFactory interface is utilized to retrieve, validate, and wrap bid
|
||||
// information into the block proposal.
|
||||
mempool.AuctionFactory
|
||||
|
||||
// AuctionBidSelect returns an iterator that iterates over the top bid
|
||||
// transactions in the mempool.
|
||||
AuctionBidSelect(ctx context.Context) sdkmempool.Iterator
|
||||
}
|
||||
|
||||
ProposalHandler struct {
|
||||
mempool Mempool
|
||||
logger log.Logger
|
||||
anteHandler sdk.AnteHandler
|
||||
txEncoder sdk.TxEncoder
|
||||
txDecoder sdk.TxDecoder
|
||||
}
|
||||
)
|
||||
|
||||
func NewProposalHandler(
|
||||
mp Mempool,
|
||||
logger log.Logger,
|
||||
anteHandler sdk.AnteHandler,
|
||||
txEncoder sdk.TxEncoder,
|
||||
txDecoder sdk.TxDecoder,
|
||||
) *ProposalHandler {
|
||||
return &ProposalHandler{
|
||||
mempool: mp,
|
||||
logger: logger,
|
||||
anteHandler: anteHandler,
|
||||
txEncoder: txEncoder,
|
||||
txDecoder: txDecoder,
|
||||
}
|
||||
}
|
||||
|
||||
// PrepareProposalHandler returns the PrepareProposal ABCI handler that performs
|
||||
// top-of-block auctioning and general block proposal construction.
|
||||
func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler {
|
||||
return func(ctx sdk.Context, req abci.RequestPrepareProposal) abci.ResponsePrepareProposal {
|
||||
var (
|
||||
selectedTxs [][]byte
|
||||
totalTxBytes int64
|
||||
)
|
||||
|
||||
bidTxIterator := h.mempool.AuctionBidSelect(ctx)
|
||||
txsToRemove := make(map[sdk.Tx]struct{}, 0)
|
||||
seenTxs := make(map[string]struct{}, 0)
|
||||
|
||||
// Attempt to select the highest bid transaction that is valid and whose
|
||||
// bundled transactions are valid.
|
||||
selectBidTxLoop:
|
||||
for ; bidTxIterator != nil; bidTxIterator = bidTxIterator.Next() {
|
||||
cacheCtx, write := ctx.CacheContext()
|
||||
tmpBidTx := bidTxIterator.Tx()
|
||||
|
||||
bidTxBz, err := h.PrepareProposalVerifyTx(cacheCtx, tmpBidTx)
|
||||
if err != nil {
|
||||
txsToRemove[tmpBidTx] = struct{}{}
|
||||
continue selectBidTxLoop
|
||||
}
|
||||
|
||||
bidTxSize := int64(len(bidTxBz))
|
||||
if bidTxSize <= req.MaxTxBytes {
|
||||
bidInfo, err := h.mempool.GetAuctionBidInfo(tmpBidTx)
|
||||
if err != nil {
|
||||
// Some transactions in the bundle may be malformatted or invalid, so
|
||||
// we remove the bid transaction and try the next top bid.
|
||||
txsToRemove[tmpBidTx] = struct{}{}
|
||||
continue selectBidTxLoop
|
||||
}
|
||||
|
||||
// store the bytes of each ref tx as sdk.Tx bytes in order to build a valid proposal
|
||||
bundledTransactions := bidInfo.Transactions
|
||||
sdkTxBytes := make([][]byte, len(bundledTransactions))
|
||||
|
||||
// Ensure that the bundled transactions are valid
|
||||
for index, rawRefTx := range bundledTransactions {
|
||||
refTx, err := h.mempool.WrapBundleTransaction(rawRefTx)
|
||||
if err != nil {
|
||||
// Malformed bundled transaction, so we remove the bid transaction
|
||||
// and try the next top bid.
|
||||
txsToRemove[tmpBidTx] = struct{}{}
|
||||
continue selectBidTxLoop
|
||||
}
|
||||
|
||||
txBz, err := h.PrepareProposalVerifyTx(cacheCtx, refTx)
|
||||
if err != nil {
|
||||
// Invalid bundled transaction, so we remove the bid transaction
|
||||
// and try the next top bid.
|
||||
txsToRemove[tmpBidTx] = struct{}{}
|
||||
continue selectBidTxLoop
|
||||
}
|
||||
|
||||
sdkTxBytes[index] = txBz
|
||||
}
|
||||
|
||||
// At this point, both the bid transaction itself and all the bundled
|
||||
// transactions are valid. So we select the bid transaction along with
|
||||
// all the bundled transactions. We also mark these transactions as seen and
|
||||
// update the total size selected thus far.
|
||||
totalTxBytes += bidTxSize
|
||||
selectedTxs = append(selectedTxs, bidTxBz)
|
||||
selectedTxs = append(selectedTxs, sdkTxBytes...)
|
||||
|
||||
for _, refTxRaw := range sdkTxBytes {
|
||||
hash := sha256.Sum256(refTxRaw)
|
||||
txHash := hex.EncodeToString(hash[:])
|
||||
seenTxs[txHash] = struct{}{}
|
||||
}
|
||||
|
||||
// Write the cache context to the original context when we know we have a
|
||||
// valid top of block bundle.
|
||||
write()
|
||||
|
||||
break selectBidTxLoop
|
||||
}
|
||||
|
||||
txsToRemove[tmpBidTx] = struct{}{}
|
||||
h.logger.Info(
|
||||
"failed to select auction bid tx; tx size is too large",
|
||||
"tx_size", bidTxSize,
|
||||
"max_size", req.MaxTxBytes,
|
||||
)
|
||||
}
|
||||
|
||||
// Remove all invalid transactions from the mempool.
|
||||
for tx := range txsToRemove {
|
||||
h.RemoveTx(tx)
|
||||
}
|
||||
|
||||
iterator := h.mempool.Select(ctx, nil)
|
||||
txsToRemove = map[sdk.Tx]struct{}{}
|
||||
|
||||
// Select remaining transactions for the block proposal until we've reached
|
||||
// size capacity.
|
||||
selectTxLoop:
|
||||
for ; iterator != nil; iterator = iterator.Next() {
|
||||
memTx := iterator.Tx()
|
||||
|
||||
// If the transaction is already included in the proposal, then we skip it.
|
||||
txBz, err := h.txEncoder(memTx)
|
||||
if err != nil {
|
||||
txsToRemove[memTx] = struct{}{}
|
||||
continue selectTxLoop
|
||||
}
|
||||
|
||||
hash := sha256.Sum256(txBz)
|
||||
txHash := hex.EncodeToString(hash[:])
|
||||
if _, ok := seenTxs[txHash]; ok {
|
||||
continue selectTxLoop
|
||||
}
|
||||
|
||||
txBz, err = h.PrepareProposalVerifyTx(ctx, memTx)
|
||||
if err != nil {
|
||||
txsToRemove[memTx] = struct{}{}
|
||||
continue selectTxLoop
|
||||
}
|
||||
|
||||
txSize := int64(len(txBz))
|
||||
if totalTxBytes += txSize; totalTxBytes <= req.MaxTxBytes {
|
||||
selectedTxs = append(selectedTxs, txBz)
|
||||
} else {
|
||||
// We've reached capacity per req.MaxTxBytes so we cannot select any
|
||||
// more transactions.
|
||||
break selectTxLoop
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all invalid transactions from the mempool.
|
||||
for tx := range txsToRemove {
|
||||
h.RemoveTx(tx)
|
||||
}
|
||||
|
||||
return abci.ResponsePrepareProposal{Txs: selectedTxs}
|
||||
}
|
||||
}
|
||||
|
||||
// ProcessProposalHandler returns the ProcessProposal ABCI handler that performs
|
||||
// block proposal verification.
|
||||
func (h *ProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHandler {
|
||||
return func(ctx sdk.Context, req abci.RequestProcessProposal) abci.ResponseProcessProposal {
|
||||
for index, txBz := range req.Txs {
|
||||
tx, err := h.ProcessProposalVerifyTx(ctx, txBz)
|
||||
if err != nil {
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
|
||||
}
|
||||
|
||||
bidInfo, err := h.mempool.GetAuctionBidInfo(tx)
|
||||
if err != nil {
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
|
||||
}
|
||||
|
||||
// If the transaction is an auction bid, then we need to ensure that it is
|
||||
// the first transaction in the block proposal and that the order of
|
||||
// transactions in the block proposal follows the order of transactions in
|
||||
// the bid.
|
||||
if bidInfo != nil {
|
||||
if index != 0 {
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
|
||||
}
|
||||
|
||||
bundledTransactions := bidInfo.Transactions
|
||||
if len(req.Txs) < len(bundledTransactions)+1 {
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
|
||||
}
|
||||
|
||||
for i, refTxRaw := range bundledTransactions {
|
||||
// Wrap and then encode the bundled transaction to ensure that the underlying
|
||||
// reference transaction can be processed as an sdk.Tx.
|
||||
wrappedTx, err := h.mempool.WrapBundleTransaction(refTxRaw)
|
||||
if err != nil {
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
|
||||
}
|
||||
|
||||
refTxBz, err := h.txEncoder(wrappedTx)
|
||||
if err != nil {
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
|
||||
}
|
||||
|
||||
if !bytes.Equal(refTxBz, req.Txs[i+1]) {
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_REJECT}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}
|
||||
}
|
||||
}
|
||||
|
||||
// PrepareProposalVerifyTx encodes a transaction and verifies it.
|
||||
func (h *ProposalHandler) PrepareProposalVerifyTx(ctx sdk.Context, tx sdk.Tx) ([]byte, error) {
|
||||
txBz, err := h.txEncoder(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return txBz, h.verifyTx(ctx, tx)
|
||||
}
|
||||
|
||||
// ProcessProposalVerifyTx decodes a transaction and verifies it.
|
||||
func (h *ProposalHandler) ProcessProposalVerifyTx(ctx sdk.Context, txBz []byte) (sdk.Tx, error) {
|
||||
tx, err := h.txDecoder(txBz)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tx, h.verifyTx(ctx, tx)
|
||||
}
|
||||
|
||||
// VerifyTx verifies a transaction against the application's state.
|
||||
func (h *ProposalHandler) verifyTx(ctx sdk.Context, tx sdk.Tx) error {
|
||||
if h.anteHandler != nil {
|
||||
_, err := h.anteHandler(ctx, tx, false)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *ProposalHandler) RemoveTx(tx sdk.Tx) {
|
||||
if err := h.mempool.Remove(tx); err != nil && !errors.Is(err, sdkmempool.ErrTxNotFound) {
|
||||
panic(fmt.Errorf("failed to remove invalid transaction from the mempool: %w", err))
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,15 @@
|
||||
package abci_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
comettypes "github.com/cometbft/cometbft/abci/types"
|
||||
abcitypes "github.com/cometbft/cometbft/abci/types"
|
||||
"github.com/cometbft/cometbft/libs/log"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
@ -25,13 +29,12 @@ type ABCITestSuite struct {
|
||||
ctx sdk.Context
|
||||
|
||||
// mempool setup
|
||||
mempool *mempool.AuctionMempool
|
||||
logger log.Logger
|
||||
encodingConfig testutils.EncodingConfig
|
||||
proposalHandler *abci.ProposalHandler
|
||||
voteExtensionHandler *abci.VoteExtensionHandler
|
||||
config mempool.AuctionFactory
|
||||
txs map[string]struct{}
|
||||
mempool *mempool.AuctionMempool
|
||||
logger log.Logger
|
||||
encodingConfig testutils.EncodingConfig
|
||||
proposalHandler *abci.ProposalHandler
|
||||
config mempool.AuctionFactory
|
||||
txs map[string]struct{}
|
||||
|
||||
// auction bid setup
|
||||
auctionBidAmount sdk.Coin
|
||||
@ -97,7 +100,7 @@ func (suite *ABCITestSuite) SetupTest() {
|
||||
suite.builderDecorator = ante.NewBuilderDecorator(suite.builderKeeper, suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), suite.mempool)
|
||||
|
||||
// Accounts set up
|
||||
suite.accounts = testutils.RandomAccounts(suite.random, 10)
|
||||
suite.accounts = testutils.RandomAccounts(suite.random, 1)
|
||||
suite.balances = sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1000000000000000000)))
|
||||
suite.nonces = make(map[string]uint64)
|
||||
for _, acc := range suite.accounts {
|
||||
@ -107,14 +110,13 @@ func (suite *ABCITestSuite) SetupTest() {
|
||||
// Proposal handler set up
|
||||
suite.logger = log.NewNopLogger()
|
||||
suite.proposalHandler = abci.NewProposalHandler(suite.mempool, suite.logger, suite.anteHandler, suite.encodingConfig.TxConfig.TxEncoder(), suite.encodingConfig.TxConfig.TxDecoder())
|
||||
suite.voteExtensionHandler = abci.NewVoteExtensionHandler(suite.mempool, suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), suite.anteHandler)
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) anteHandler(ctx sdk.Context, tx sdk.Tx, _ bool) (sdk.Context, error) {
|
||||
func (suite *ABCITestSuite) anteHandler(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) {
|
||||
signer := tx.GetMsgs()[0].GetSigners()[0]
|
||||
suite.bankKeeper.EXPECT().GetAllBalances(ctx, signer).AnyTimes().Return(suite.balances)
|
||||
|
||||
next := func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
|
||||
next := func(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
@ -123,12 +125,24 @@ func (suite *ABCITestSuite) anteHandler(ctx sdk.Context, tx sdk.Tx, _ bool) (sdk
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
bz, err := suite.encodingConfig.TxConfig.TxEncoder()(tx)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
if !simulate {
|
||||
hash := sha256.Sum256(bz)
|
||||
txHash := hex.EncodeToString(hash[:])
|
||||
if _, ok := suite.txs[txHash]; ok {
|
||||
return ctx, fmt.Errorf("tx already in mempool")
|
||||
}
|
||||
suite.txs[txHash] = struct{}{}
|
||||
}
|
||||
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createFilledMempool(numNormalTxs, numAuctionTxs, numBundledTxs int, insertRefTxs bool) int {
|
||||
suite.mempool = mempool.NewAuctionMempool(suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), 0, suite.config)
|
||||
|
||||
// Insert a bunch of normal transactions into the global mempool
|
||||
for i := 0; i < numNormalTxs; i++ {
|
||||
// randomly select an account to create the tx
|
||||
@ -212,10 +226,28 @@ func (suite *ABCITestSuite) createFilledMempool(numNormalTxs, numAuctionTxs, num
|
||||
return totalNumTxs
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) exportMempool() [][]byte {
|
||||
func (suite *ABCITestSuite) exportMempool(exportRefTxs bool) [][]byte {
|
||||
txs := make([][]byte, 0)
|
||||
seenTxs := make(map[string]bool)
|
||||
|
||||
auctionIterator := suite.mempool.AuctionBidSelect(suite.ctx)
|
||||
for ; auctionIterator != nil; auctionIterator = auctionIterator.Next() {
|
||||
auctionTx := auctionIterator.Tx()
|
||||
txBz, err := suite.encodingConfig.TxConfig.TxEncoder()(auctionTx)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
txs = append(txs, txBz)
|
||||
|
||||
if exportRefTxs {
|
||||
for _, refRawTx := range auctionTx.GetMsgs()[0].(*buildertypes.MsgAuctionBid).GetTransactions() {
|
||||
txs = append(txs, refRawTx)
|
||||
seenTxs[string(refRawTx)] = true
|
||||
}
|
||||
}
|
||||
|
||||
seenTxs[string(txBz)] = true
|
||||
}
|
||||
|
||||
iterator := suite.mempool.Select(suite.ctx, nil)
|
||||
for ; iterator != nil; iterator = iterator.Next() {
|
||||
txBz, err := suite.encodingConfig.TxConfig.TxEncoder()(iterator.Tx())
|
||||
@ -229,107 +261,510 @@ func (suite *ABCITestSuite) exportMempool() [][]byte {
|
||||
return txs
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createPrepareProposalRequest(maxBytes int64) comettypes.RequestPrepareProposal {
|
||||
voteExtensions := make([]comettypes.ExtendedVoteInfo, 0)
|
||||
func (suite *ABCITestSuite) TestPrepareProposal() {
|
||||
var (
|
||||
// the modified transactions cannot exceed this size
|
||||
maxTxBytes int64 = 1000000000000000000
|
||||
|
||||
auctionIterator := suite.mempool.AuctionBidSelect(suite.ctx)
|
||||
for ; auctionIterator != nil; auctionIterator = auctionIterator.Next() {
|
||||
tx := auctionIterator.Tx()
|
||||
// mempool configuration
|
||||
numNormalTxs = 100
|
||||
numAuctionTxs = 100
|
||||
numBundledTxs = 3
|
||||
insertRefTxs = false
|
||||
|
||||
txBz, err := suite.encodingConfig.TxConfig.TxEncoder()(tx)
|
||||
suite.Require().NoError(err)
|
||||
// auction configuration
|
||||
maxBundleSize uint32 = 10
|
||||
reserveFee = sdk.NewCoin("foo", sdk.NewInt(1000))
|
||||
frontRunningProtection = true
|
||||
)
|
||||
|
||||
voteExtensions = append(voteExtensions, comettypes.ExtendedVoteInfo{
|
||||
VoteExtension: txBz,
|
||||
})
|
||||
}
|
||||
|
||||
return comettypes.RequestPrepareProposal{
|
||||
MaxTxBytes: maxBytes,
|
||||
LocalLastCommit: comettypes.ExtendedCommitInfo{
|
||||
Votes: voteExtensions,
|
||||
cases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
expectedNumberProposalTxs int
|
||||
expectedNumberTxsInMempool int
|
||||
isTopBidValid bool
|
||||
}{
|
||||
{
|
||||
"single bundle in the mempool",
|
||||
func() {
|
||||
numNormalTxs = 0
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 3
|
||||
insertRefTxs = true
|
||||
},
|
||||
4,
|
||||
3,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"single bundle in the mempool, no ref txs in mempool",
|
||||
func() {
|
||||
numNormalTxs = 0
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 3
|
||||
insertRefTxs = false
|
||||
},
|
||||
4,
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"single bundle in the mempool, not valid",
|
||||
func() {
|
||||
reserveFee = sdk.NewCoin("foo", sdk.NewInt(100000))
|
||||
suite.auctionBidAmount = sdk.NewCoin("foo", sdk.NewInt(10000)) // this will fail the ante handler
|
||||
numNormalTxs = 0
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 3
|
||||
},
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"single bundle in the mempool, not valid with ref txs in mempool",
|
||||
func() {
|
||||
reserveFee = sdk.NewCoin("foo", sdk.NewInt(100000))
|
||||
suite.auctionBidAmount = sdk.NewCoin("foo", sdk.NewInt(10000)) // this will fail the ante handler
|
||||
numNormalTxs = 0
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 3
|
||||
insertRefTxs = true
|
||||
},
|
||||
3,
|
||||
3,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"multiple bundles in the mempool, no normal txs + no ref txs in mempool",
|
||||
func() {
|
||||
reserveFee = sdk.NewCoin("foo", sdk.NewInt(1000))
|
||||
suite.auctionBidAmount = sdk.NewCoin("foo", sdk.NewInt(10000000))
|
||||
numNormalTxs = 0
|
||||
numAuctionTxs = 10
|
||||
numBundledTxs = 3
|
||||
insertRefTxs = false
|
||||
},
|
||||
4,
|
||||
0,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"multiple bundles in the mempool, no normal txs + ref txs in mempool",
|
||||
func() {
|
||||
numNormalTxs = 0
|
||||
numAuctionTxs = 10
|
||||
numBundledTxs = 3
|
||||
insertRefTxs = true
|
||||
},
|
||||
31,
|
||||
30,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"normal txs only",
|
||||
func() {
|
||||
numNormalTxs = 1
|
||||
numAuctionTxs = 0
|
||||
numBundledTxs = 0
|
||||
},
|
||||
1,
|
||||
1,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"many normal txs only",
|
||||
func() {
|
||||
numNormalTxs = 100
|
||||
numAuctionTxs = 0
|
||||
numBundledTxs = 0
|
||||
},
|
||||
100,
|
||||
100,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"single normal tx, single auction tx",
|
||||
func() {
|
||||
numNormalTxs = 1
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 0
|
||||
},
|
||||
2,
|
||||
1,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"single normal tx, single auction tx with ref txs",
|
||||
func() {
|
||||
numNormalTxs = 1
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 3
|
||||
insertRefTxs = false
|
||||
},
|
||||
5,
|
||||
1,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"single normal tx, single failing auction tx with ref txs",
|
||||
func() {
|
||||
numNormalTxs = 1
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 3
|
||||
insertRefTxs = true
|
||||
suite.auctionBidAmount = sdk.NewCoin("foo", sdk.NewInt(2000)) // this will fail the ante handler
|
||||
reserveFee = sdk.NewCoin("foo", sdk.NewInt(1000000000))
|
||||
},
|
||||
4,
|
||||
4,
|
||||
false,
|
||||
},
|
||||
{
|
||||
"many normal tx, single auction tx with no ref txs",
|
||||
func() {
|
||||
reserveFee = sdk.NewCoin("foo", sdk.NewInt(1000))
|
||||
suite.auctionBidAmount = sdk.NewCoin("foo", sdk.NewInt(2000000))
|
||||
numNormalTxs = 100
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 0
|
||||
},
|
||||
101,
|
||||
100,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"many normal tx, single auction tx with ref txs",
|
||||
func() {
|
||||
numNormalTxs = 100
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 3
|
||||
insertRefTxs = true
|
||||
},
|
||||
104,
|
||||
103,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"many normal tx, single auction tx with ref txs",
|
||||
func() {
|
||||
numNormalTxs = 100
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 3
|
||||
insertRefTxs = false
|
||||
},
|
||||
104,
|
||||
100,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"many normal tx, many auction tx with ref txs",
|
||||
func() {
|
||||
numNormalTxs = 100
|
||||
numAuctionTxs = 100
|
||||
numBundledTxs = 1
|
||||
insertRefTxs = true
|
||||
},
|
||||
201,
|
||||
200,
|
||||
true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createExtendedCommitInfoFromTxBzs(txs [][]byte) []byte {
|
||||
voteExtensions := make([]comettypes.ExtendedVoteInfo, 0)
|
||||
for _, tc := range cases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
tc.malleate()
|
||||
|
||||
for _, txBz := range txs {
|
||||
voteExtensions = append(voteExtensions, comettypes.ExtendedVoteInfo{
|
||||
VoteExtension: txBz,
|
||||
suite.createFilledMempool(numNormalTxs, numAuctionTxs, numBundledTxs, insertRefTxs)
|
||||
|
||||
// create a new auction
|
||||
params := buildertypes.Params{
|
||||
MaxBundleSize: maxBundleSize,
|
||||
ReserveFee: reserveFee,
|
||||
FrontRunningProtection: frontRunningProtection,
|
||||
MinBidIncrement: suite.minBidIncrement,
|
||||
}
|
||||
suite.builderKeeper.SetParams(suite.ctx, params)
|
||||
suite.builderDecorator = ante.NewBuilderDecorator(suite.builderKeeper, suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), suite.mempool)
|
||||
|
||||
handler := suite.proposalHandler.PrepareProposalHandler()
|
||||
res := handler(suite.ctx, abcitypes.RequestPrepareProposal{
|
||||
MaxTxBytes: maxTxBytes,
|
||||
})
|
||||
|
||||
// -------------------- Check Invariants -------------------- //
|
||||
// 1. The auction tx must fail if we know it is invalid
|
||||
suite.Require().Equal(tc.isTopBidValid, suite.isTopBidValid())
|
||||
|
||||
// 2. total bytes must be less than or equal to maxTxBytes
|
||||
totalBytes := int64(0)
|
||||
if suite.isTopBidValid() {
|
||||
totalBytes += int64(len(res.Txs[0]))
|
||||
|
||||
for _, tx := range res.Txs[1+numBundledTxs:] {
|
||||
totalBytes += int64(len(tx))
|
||||
}
|
||||
} else {
|
||||
for _, tx := range res.Txs {
|
||||
totalBytes += int64(len(tx))
|
||||
}
|
||||
}
|
||||
suite.Require().LessOrEqual(totalBytes, maxTxBytes)
|
||||
|
||||
// 3. the number of transactions in the response must be equal to the number of expected transactions
|
||||
suite.Require().Equal(tc.expectedNumberProposalTxs, len(res.Txs))
|
||||
|
||||
// 4. if there are auction transactions, the first transaction must be the top bid
|
||||
// and the rest of the bundle must be in the response
|
||||
if suite.isTopBidValid() {
|
||||
auctionTx, err := suite.encodingConfig.TxConfig.TxDecoder()(res.Txs[0])
|
||||
suite.Require().NoError(err)
|
||||
|
||||
bidInfo, err := suite.mempool.GetAuctionBidInfo(auctionTx)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
for index, tx := range bidInfo.Transactions {
|
||||
suite.Require().Equal(tx, res.Txs[index+1])
|
||||
}
|
||||
}
|
||||
|
||||
// 5. All of the transactions must be unique
|
||||
uniqueTxs := make(map[string]bool)
|
||||
for _, tx := range res.Txs {
|
||||
suite.Require().False(uniqueTxs[string(tx)])
|
||||
uniqueTxs[string(tx)] = true
|
||||
}
|
||||
|
||||
// 6. The number of transactions in the mempool must be correct
|
||||
suite.Require().Equal(tc.expectedNumberTxsInMempool, suite.mempool.CountTx())
|
||||
})
|
||||
}
|
||||
|
||||
commitInfo := comettypes.ExtendedCommitInfo{
|
||||
Votes: voteExtensions,
|
||||
}
|
||||
|
||||
commitInfoBz, err := commitInfo.Marshal()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return commitInfoBz
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createAuctionInfoFromTxBzs(txs [][]byte, numTxs uint64) []byte {
|
||||
auctionInfo := abci.AuctionInfo{
|
||||
ExtendedCommitInfo: suite.createExtendedCommitInfoFromTxBzs(txs),
|
||||
NumTxs: numTxs,
|
||||
MaxTxBytes: int64(len(txs[0])),
|
||||
func (suite *ABCITestSuite) TestProcessProposal() {
|
||||
var (
|
||||
// mempool set up
|
||||
numNormalTxs = 100
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 3
|
||||
insertRefTxs = true
|
||||
exportRefTxs = true
|
||||
frontRunningTx sdk.Tx
|
||||
|
||||
// auction set up
|
||||
maxBundleSize uint32 = 10
|
||||
reserveFee = sdk.NewCoin("foo", sdk.NewInt(1000))
|
||||
frontRunningProtection = true
|
||||
)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
isTopBidValid bool
|
||||
response abcitypes.ResponseProcessProposal_ProposalStatus
|
||||
}{
|
||||
{
|
||||
"single normal tx, no auction tx",
|
||||
func() {
|
||||
numNormalTxs = 1
|
||||
numAuctionTxs = 0
|
||||
numBundledTxs = 0
|
||||
},
|
||||
false,
|
||||
abcitypes.ResponseProcessProposal_ACCEPT,
|
||||
},
|
||||
{
|
||||
"single auction tx, no normal txs",
|
||||
func() {
|
||||
numNormalTxs = 0
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 0
|
||||
},
|
||||
true,
|
||||
abcitypes.ResponseProcessProposal_ACCEPT,
|
||||
},
|
||||
{
|
||||
"single auction tx, single auction tx",
|
||||
func() {
|
||||
numNormalTxs = 1
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 0
|
||||
},
|
||||
true,
|
||||
abcitypes.ResponseProcessProposal_ACCEPT,
|
||||
},
|
||||
{
|
||||
"single auction tx, single auction tx with ref txs",
|
||||
func() {
|
||||
numNormalTxs = 1
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 4
|
||||
},
|
||||
true,
|
||||
abcitypes.ResponseProcessProposal_ACCEPT,
|
||||
},
|
||||
{
|
||||
"single auction tx, single auction tx with no ref txs",
|
||||
func() {
|
||||
numNormalTxs = 1
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 4
|
||||
insertRefTxs = false
|
||||
exportRefTxs = false
|
||||
},
|
||||
true,
|
||||
abcitypes.ResponseProcessProposal_REJECT,
|
||||
},
|
||||
{
|
||||
"multiple auction txs, single normal tx",
|
||||
func() {
|
||||
numNormalTxs = 1
|
||||
numAuctionTxs = 2
|
||||
numBundledTxs = 4
|
||||
insertRefTxs = true
|
||||
exportRefTxs = true
|
||||
},
|
||||
true,
|
||||
abcitypes.ResponseProcessProposal_REJECT,
|
||||
},
|
||||
{
|
||||
"single auction txs, multiple normal tx",
|
||||
func() {
|
||||
numNormalTxs = 100
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 4
|
||||
},
|
||||
true,
|
||||
abcitypes.ResponseProcessProposal_ACCEPT,
|
||||
},
|
||||
{
|
||||
"single invalid auction tx, multiple normal tx",
|
||||
func() {
|
||||
numNormalTxs = 100
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 4
|
||||
reserveFee = sdk.NewCoin("foo", sdk.NewInt(100000000000000000))
|
||||
insertRefTxs = true
|
||||
},
|
||||
false,
|
||||
abcitypes.ResponseProcessProposal_REJECT,
|
||||
},
|
||||
{
|
||||
"single valid auction txs but missing ref txs",
|
||||
func() {
|
||||
numNormalTxs = 0
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 4
|
||||
reserveFee = sdk.NewCoin("foo", sdk.NewInt(1000))
|
||||
insertRefTxs = false
|
||||
exportRefTxs = false
|
||||
},
|
||||
true,
|
||||
abcitypes.ResponseProcessProposal_REJECT,
|
||||
},
|
||||
{
|
||||
"single valid auction txs but missing ref txs, with many normal txs",
|
||||
func() {
|
||||
numNormalTxs = 100
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 4
|
||||
reserveFee = sdk.NewCoin("foo", sdk.NewInt(1000))
|
||||
insertRefTxs = false
|
||||
exportRefTxs = false
|
||||
},
|
||||
true,
|
||||
abcitypes.ResponseProcessProposal_REJECT,
|
||||
},
|
||||
{
|
||||
"auction tx with frontrunning",
|
||||
func() {
|
||||
randomAccount := testutils.RandomAccounts(suite.random, 1)[0]
|
||||
bidder := suite.accounts[0]
|
||||
bid := sdk.NewCoin("foo", sdk.NewInt(696969696969))
|
||||
nonce := suite.nonces[bidder.Address.String()]
|
||||
frontRunningTx, _ = testutils.CreateAuctionTxWithSigners(suite.encodingConfig.TxConfig, suite.accounts[0], bid, nonce+1, 1000, []testutils.Account{bidder, randomAccount})
|
||||
suite.Require().NotNil(frontRunningTx)
|
||||
|
||||
numNormalTxs = 100
|
||||
numAuctionTxs = 1
|
||||
numBundledTxs = 4
|
||||
insertRefTxs = true
|
||||
exportRefTxs = true
|
||||
},
|
||||
false,
|
||||
abcitypes.ResponseProcessProposal_REJECT,
|
||||
},
|
||||
{
|
||||
"auction tx with frontrunning, but frontrunning protection disabled",
|
||||
func() {
|
||||
randomAccount := testutils.RandomAccounts(suite.random, 1)[0]
|
||||
bidder := suite.accounts[0]
|
||||
bid := sdk.NewCoin("foo", sdk.NewInt(696969696969))
|
||||
nonce := suite.nonces[bidder.Address.String()]
|
||||
frontRunningTx, _ = testutils.CreateAuctionTxWithSigners(suite.encodingConfig.TxConfig, suite.accounts[0], bid, nonce+1, 1000, []testutils.Account{bidder, randomAccount})
|
||||
suite.Require().NotNil(frontRunningTx)
|
||||
|
||||
numAuctionTxs = 0
|
||||
frontRunningProtection = false
|
||||
},
|
||||
true,
|
||||
abcitypes.ResponseProcessProposal_ACCEPT,
|
||||
},
|
||||
}
|
||||
|
||||
auctionInfoBz, err := auctionInfo.Marshal()
|
||||
suite.Require().NoError(err)
|
||||
for _, tc := range cases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset
|
||||
tc.malleate()
|
||||
|
||||
return auctionInfoBz
|
||||
suite.createFilledMempool(numNormalTxs, numAuctionTxs, numBundledTxs, insertRefTxs)
|
||||
|
||||
if frontRunningTx != nil {
|
||||
suite.Require().NoError(suite.mempool.Insert(suite.ctx, frontRunningTx))
|
||||
}
|
||||
|
||||
// create a new auction
|
||||
params := buildertypes.Params{
|
||||
MaxBundleSize: maxBundleSize,
|
||||
ReserveFee: reserveFee,
|
||||
FrontRunningProtection: frontRunningProtection,
|
||||
MinBidIncrement: suite.minBidIncrement,
|
||||
}
|
||||
suite.builderKeeper.SetParams(suite.ctx, params)
|
||||
suite.builderDecorator = ante.NewBuilderDecorator(suite.builderKeeper, suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), suite.mempool)
|
||||
suite.Require().Equal(tc.isTopBidValid, suite.isTopBidValid())
|
||||
|
||||
txs := suite.exportMempool(exportRefTxs)
|
||||
|
||||
if frontRunningTx != nil {
|
||||
txBz, err := suite.encodingConfig.TxConfig.TxEncoder()(frontRunningTx)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Require().True(bytes.Equal(txs[0], txBz))
|
||||
}
|
||||
|
||||
handler := suite.proposalHandler.ProcessProposalHandler()
|
||||
res := handler(suite.ctx, abcitypes.RequestProcessProposal{
|
||||
Txs: txs,
|
||||
})
|
||||
|
||||
// Check if the response is valid
|
||||
suite.Require().Equal(tc.response, res.Status)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) getAllAuctionTxs() ([]sdk.Tx, [][]byte) {
|
||||
auctionIterator := suite.mempool.AuctionBidSelect(suite.ctx)
|
||||
txs := make([]sdk.Tx, 0)
|
||||
txBzs := make([][]byte, 0)
|
||||
|
||||
for ; auctionIterator != nil; auctionIterator = auctionIterator.Next() {
|
||||
txs = append(txs, auctionIterator.Tx())
|
||||
|
||||
bz, err := suite.encodingConfig.TxConfig.TxEncoder()(auctionIterator.Tx())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
txBzs = append(txBzs, bz)
|
||||
// isTopBidValid returns true if the top bid is valid. We purposefully insert invalid
|
||||
// auction transactions into the mempool to test the handlers.
|
||||
func (suite *ABCITestSuite) isTopBidValid() bool {
|
||||
iterator := suite.mempool.AuctionBidSelect(suite.ctx)
|
||||
if iterator == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return txs, txBzs
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createExtendedCommitInfoFromTxs(txs []sdk.Tx) comettypes.ExtendedCommitInfo {
|
||||
voteExtensions := make([][]byte, 0)
|
||||
for _, tx := range txs {
|
||||
bz, err := suite.encodingConfig.TxConfig.TxEncoder()(tx)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
voteExtensions = append(voteExtensions, bz)
|
||||
}
|
||||
|
||||
return suite.createExtendedCommitInfo(voteExtensions)
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createExtendedVoteInfo(voteExtensions [][]byte) []comettypes.ExtendedVoteInfo {
|
||||
commitInfo := make([]comettypes.ExtendedVoteInfo, 0)
|
||||
for _, voteExtension := range voteExtensions {
|
||||
info := comettypes.ExtendedVoteInfo{
|
||||
VoteExtension: voteExtension,
|
||||
}
|
||||
|
||||
commitInfo = append(commitInfo, info)
|
||||
}
|
||||
|
||||
return commitInfo
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createExtendedCommitInfo(voteExtensions [][]byte) comettypes.ExtendedCommitInfo {
|
||||
commitInfo := comettypes.ExtendedCommitInfo{
|
||||
Votes: suite.createExtendedVoteInfo(voteExtensions),
|
||||
}
|
||||
|
||||
return commitInfo
|
||||
// check if the top bid is valid
|
||||
_, err := suite.anteHandler(suite.ctx, iterator.Tx(), true)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
336
abci/v2/abci_test.go
Normal file
336
abci/v2/abci_test.go
Normal file
@ -0,0 +1,336 @@
|
||||
package v2_test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
comettypes "github.com/cometbft/cometbft/abci/types"
|
||||
"github.com/cometbft/cometbft/libs/log"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/skip-mev/pob/abci"
|
||||
v2 "github.com/skip-mev/pob/abci/v2"
|
||||
"github.com/skip-mev/pob/mempool"
|
||||
testutils "github.com/skip-mev/pob/testutils"
|
||||
"github.com/skip-mev/pob/x/builder/ante"
|
||||
"github.com/skip-mev/pob/x/builder/keeper"
|
||||
buildertypes "github.com/skip-mev/pob/x/builder/types"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type ABCITestSuite struct {
|
||||
suite.Suite
|
||||
ctx sdk.Context
|
||||
|
||||
// mempool setup
|
||||
mempool *mempool.AuctionMempool
|
||||
logger log.Logger
|
||||
encodingConfig testutils.EncodingConfig
|
||||
proposalHandler *v2.ProposalHandler
|
||||
voteExtensionHandler *v2.VoteExtensionHandler
|
||||
config mempool.AuctionFactory
|
||||
txs map[string]struct{}
|
||||
|
||||
// auction bid setup
|
||||
auctionBidAmount sdk.Coin
|
||||
minBidIncrement sdk.Coin
|
||||
|
||||
// builder setup
|
||||
builderKeeper keeper.Keeper
|
||||
bankKeeper *testutils.MockBankKeeper
|
||||
accountKeeper *testutils.MockAccountKeeper
|
||||
distrKeeper *testutils.MockDistributionKeeper
|
||||
stakingKeeper *testutils.MockStakingKeeper
|
||||
builderDecorator ante.BuilderDecorator
|
||||
key *storetypes.KVStoreKey
|
||||
authorityAccount sdk.AccAddress
|
||||
|
||||
// account set up
|
||||
accounts []testutils.Account
|
||||
balances sdk.Coins
|
||||
random *rand.Rand
|
||||
nonces map[string]uint64
|
||||
}
|
||||
|
||||
func TestABCISuite(t *testing.T) {
|
||||
suite.Run(t, new(ABCITestSuite))
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) SetupTest() {
|
||||
// General config
|
||||
suite.encodingConfig = testutils.CreateTestEncodingConfig()
|
||||
suite.random = rand.New(rand.NewSource(time.Now().Unix()))
|
||||
suite.key = storetypes.NewKVStoreKey(buildertypes.StoreKey)
|
||||
testCtx := testutil.DefaultContextWithDB(suite.T(), suite.key, storetypes.NewTransientStoreKey("transient_test"))
|
||||
suite.ctx = testCtx.Ctx.WithBlockHeight(1)
|
||||
|
||||
// Mempool set up
|
||||
suite.config = mempool.NewDefaultAuctionFactory(suite.encodingConfig.TxConfig.TxDecoder())
|
||||
suite.mempool = mempool.NewAuctionMempool(suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), 0, suite.config)
|
||||
suite.txs = make(map[string]struct{})
|
||||
suite.auctionBidAmount = sdk.NewCoin("foo", sdk.NewInt(1000000000))
|
||||
suite.minBidIncrement = sdk.NewCoin("foo", sdk.NewInt(1000))
|
||||
|
||||
// Mock keepers set up
|
||||
ctrl := gomock.NewController(suite.T())
|
||||
suite.accountKeeper = testutils.NewMockAccountKeeper(ctrl)
|
||||
suite.accountKeeper.EXPECT().GetModuleAddress(buildertypes.ModuleName).Return(sdk.AccAddress{}).AnyTimes()
|
||||
suite.bankKeeper = testutils.NewMockBankKeeper(ctrl)
|
||||
suite.distrKeeper = testutils.NewMockDistributionKeeper(ctrl)
|
||||
suite.stakingKeeper = testutils.NewMockStakingKeeper(ctrl)
|
||||
suite.authorityAccount = sdk.AccAddress([]byte("authority"))
|
||||
|
||||
// Builder keeper / decorator set up
|
||||
suite.builderKeeper = keeper.NewKeeper(
|
||||
suite.encodingConfig.Codec,
|
||||
suite.key,
|
||||
suite.accountKeeper,
|
||||
suite.bankKeeper,
|
||||
suite.distrKeeper,
|
||||
suite.stakingKeeper,
|
||||
suite.authorityAccount.String(),
|
||||
)
|
||||
err := suite.builderKeeper.SetParams(suite.ctx, buildertypes.DefaultParams())
|
||||
suite.Require().NoError(err)
|
||||
suite.builderDecorator = ante.NewBuilderDecorator(suite.builderKeeper, suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), suite.mempool)
|
||||
|
||||
// Accounts set up
|
||||
suite.accounts = testutils.RandomAccounts(suite.random, 10)
|
||||
suite.balances = sdk.NewCoins(sdk.NewCoin("foo", sdk.NewInt(1000000000000000000)))
|
||||
suite.nonces = make(map[string]uint64)
|
||||
for _, acc := range suite.accounts {
|
||||
suite.nonces[acc.Address.String()] = 0
|
||||
}
|
||||
|
||||
// Proposal handler set up
|
||||
suite.logger = log.NewNopLogger()
|
||||
suite.proposalHandler = v2.NewProposalHandler(suite.mempool, suite.logger, suite.anteHandler, suite.encodingConfig.TxConfig.TxEncoder(), suite.encodingConfig.TxConfig.TxDecoder())
|
||||
suite.voteExtensionHandler = v2.NewVoteExtensionHandler(suite.mempool, suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), suite.anteHandler)
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) anteHandler(ctx sdk.Context, tx sdk.Tx, _ bool) (sdk.Context, error) {
|
||||
signer := tx.GetMsgs()[0].GetSigners()[0]
|
||||
suite.bankKeeper.EXPECT().GetAllBalances(ctx, signer).AnyTimes().Return(suite.balances)
|
||||
|
||||
next := func(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
ctx, err := suite.builderDecorator.AnteHandle(ctx, tx, false, next)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createFilledMempool(numNormalTxs, numAuctionTxs, numBundledTxs int, insertRefTxs bool) int {
|
||||
suite.mempool = mempool.NewAuctionMempool(suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), 0, suite.config)
|
||||
|
||||
// Insert a bunch of normal transactions into the global mempool
|
||||
for i := 0; i < numNormalTxs; i++ {
|
||||
// randomly select an account to create the tx
|
||||
randomIndex := suite.random.Intn(len(suite.accounts))
|
||||
acc := suite.accounts[randomIndex]
|
||||
|
||||
// create a few random msgs
|
||||
randomMsgs := testutils.CreateRandomMsgs(acc.Address, 3)
|
||||
|
||||
nonce := suite.nonces[acc.Address.String()]
|
||||
randomTx, err := testutils.CreateTx(suite.encodingConfig.TxConfig, acc, nonce, 1000, randomMsgs)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.nonces[acc.Address.String()]++
|
||||
priority := suite.random.Int63n(100) + 1
|
||||
suite.Require().NoError(suite.mempool.Insert(suite.ctx.WithPriority(priority), randomTx))
|
||||
}
|
||||
|
||||
suite.Require().Equal(numNormalTxs, suite.mempool.CountTx())
|
||||
suite.Require().Equal(0, suite.mempool.CountAuctionTx())
|
||||
|
||||
// Insert a bunch of auction transactions into the global mempool and auction mempool
|
||||
for i := 0; i < numAuctionTxs; i++ {
|
||||
// randomly select a bidder to create the tx
|
||||
randomIndex := suite.random.Intn(len(suite.accounts))
|
||||
acc := suite.accounts[randomIndex]
|
||||
|
||||
// create a new auction bid msg with numBundledTxs bundled transactions
|
||||
nonce := suite.nonces[acc.Address.String()]
|
||||
bidMsg, err := testutils.CreateMsgAuctionBid(suite.encodingConfig.TxConfig, acc, suite.auctionBidAmount, nonce, numBundledTxs)
|
||||
suite.nonces[acc.Address.String()] += uint64(numBundledTxs)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// create the auction tx
|
||||
nonce = suite.nonces[acc.Address.String()]
|
||||
auctionTx, err := testutils.CreateTx(suite.encodingConfig.TxConfig, acc, nonce, 1000, []sdk.Msg{bidMsg})
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// insert the auction tx into the global mempool
|
||||
priority := suite.random.Int63n(100) + 1
|
||||
suite.Require().NoError(suite.mempool.Insert(suite.ctx.WithPriority(priority), auctionTx))
|
||||
suite.nonces[acc.Address.String()]++
|
||||
|
||||
if insertRefTxs {
|
||||
for _, refRawTx := range bidMsg.GetTransactions() {
|
||||
refTx, err := suite.encodingConfig.TxConfig.TxDecoder()(refRawTx)
|
||||
suite.Require().NoError(err)
|
||||
priority := suite.random.Int63n(100) + 1
|
||||
suite.Require().NoError(suite.mempool.Insert(suite.ctx.WithPriority(priority), refTx))
|
||||
}
|
||||
}
|
||||
|
||||
// decrement the bid amount for the next auction tx
|
||||
suite.auctionBidAmount = suite.auctionBidAmount.Sub(suite.minBidIncrement)
|
||||
}
|
||||
|
||||
numSeenGlobalTxs := 0
|
||||
for iterator := suite.mempool.Select(suite.ctx, nil); iterator != nil; iterator = iterator.Next() {
|
||||
numSeenGlobalTxs++
|
||||
}
|
||||
|
||||
numSeenAuctionTxs := 0
|
||||
for iterator := suite.mempool.AuctionBidSelect(suite.ctx); iterator != nil; iterator = iterator.Next() {
|
||||
numSeenAuctionTxs++
|
||||
}
|
||||
|
||||
var totalNumTxs int
|
||||
suite.Require().Equal(numAuctionTxs, suite.mempool.CountAuctionTx())
|
||||
if insertRefTxs {
|
||||
totalNumTxs = numNormalTxs + numAuctionTxs*(numBundledTxs)
|
||||
suite.Require().Equal(totalNumTxs, suite.mempool.CountTx())
|
||||
suite.Require().Equal(totalNumTxs, numSeenGlobalTxs)
|
||||
} else {
|
||||
totalNumTxs = numNormalTxs
|
||||
suite.Require().Equal(totalNumTxs, suite.mempool.CountTx())
|
||||
suite.Require().Equal(totalNumTxs, numSeenGlobalTxs)
|
||||
}
|
||||
|
||||
suite.Require().Equal(numAuctionTxs, numSeenAuctionTxs)
|
||||
|
||||
return totalNumTxs
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) exportMempool() [][]byte {
|
||||
txs := make([][]byte, 0)
|
||||
seenTxs := make(map[string]bool)
|
||||
|
||||
iterator := suite.mempool.Select(suite.ctx, nil)
|
||||
for ; iterator != nil; iterator = iterator.Next() {
|
||||
txBz, err := suite.encodingConfig.TxConfig.TxEncoder()(iterator.Tx())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
if !seenTxs[string(txBz)] {
|
||||
txs = append(txs, txBz)
|
||||
}
|
||||
}
|
||||
|
||||
return txs
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createPrepareProposalRequest(maxBytes int64) comettypes.RequestPrepareProposal {
|
||||
voteExtensions := make([]comettypes.ExtendedVoteInfo, 0)
|
||||
|
||||
auctionIterator := suite.mempool.AuctionBidSelect(suite.ctx)
|
||||
for ; auctionIterator != nil; auctionIterator = auctionIterator.Next() {
|
||||
tx := auctionIterator.Tx()
|
||||
|
||||
txBz, err := suite.encodingConfig.TxConfig.TxEncoder()(tx)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
voteExtensions = append(voteExtensions, comettypes.ExtendedVoteInfo{
|
||||
VoteExtension: txBz,
|
||||
})
|
||||
}
|
||||
|
||||
return comettypes.RequestPrepareProposal{
|
||||
MaxTxBytes: maxBytes,
|
||||
LocalLastCommit: comettypes.ExtendedCommitInfo{
|
||||
Votes: voteExtensions,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createExtendedCommitInfoFromTxBzs(txs [][]byte) []byte {
|
||||
voteExtensions := make([]comettypes.ExtendedVoteInfo, 0)
|
||||
|
||||
for _, txBz := range txs {
|
||||
voteExtensions = append(voteExtensions, comettypes.ExtendedVoteInfo{
|
||||
VoteExtension: txBz,
|
||||
})
|
||||
}
|
||||
|
||||
commitInfo := comettypes.ExtendedCommitInfo{
|
||||
Votes: voteExtensions,
|
||||
}
|
||||
|
||||
commitInfoBz, err := commitInfo.Marshal()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return commitInfoBz
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createAuctionInfoFromTxBzs(txs [][]byte, numTxs uint64) []byte {
|
||||
auctionInfo := abci.AuctionInfo{
|
||||
ExtendedCommitInfo: suite.createExtendedCommitInfoFromTxBzs(txs),
|
||||
NumTxs: numTxs,
|
||||
MaxTxBytes: int64(len(txs[0])),
|
||||
}
|
||||
|
||||
auctionInfoBz, err := auctionInfo.Marshal()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return auctionInfoBz
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) getAllAuctionTxs() ([]sdk.Tx, [][]byte) {
|
||||
auctionIterator := suite.mempool.AuctionBidSelect(suite.ctx)
|
||||
txs := make([]sdk.Tx, 0)
|
||||
txBzs := make([][]byte, 0)
|
||||
|
||||
for ; auctionIterator != nil; auctionIterator = auctionIterator.Next() {
|
||||
txs = append(txs, auctionIterator.Tx())
|
||||
|
||||
bz, err := suite.encodingConfig.TxConfig.TxEncoder()(auctionIterator.Tx())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
txBzs = append(txBzs, bz)
|
||||
}
|
||||
|
||||
return txs, txBzs
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createExtendedCommitInfoFromTxs(txs []sdk.Tx) comettypes.ExtendedCommitInfo {
|
||||
voteExtensions := make([][]byte, 0)
|
||||
for _, tx := range txs {
|
||||
bz, err := suite.encodingConfig.TxConfig.TxEncoder()(tx)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
voteExtensions = append(voteExtensions, bz)
|
||||
}
|
||||
|
||||
return suite.createExtendedCommitInfo(voteExtensions)
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createExtendedVoteInfo(voteExtensions [][]byte) []comettypes.ExtendedVoteInfo {
|
||||
commitInfo := make([]comettypes.ExtendedVoteInfo, 0)
|
||||
for _, voteExtension := range voteExtensions {
|
||||
info := comettypes.ExtendedVoteInfo{
|
||||
VoteExtension: voteExtension,
|
||||
}
|
||||
|
||||
commitInfo = append(commitInfo, info)
|
||||
}
|
||||
|
||||
return commitInfo
|
||||
}
|
||||
|
||||
func (suite *ABCITestSuite) createExtendedCommitInfo(voteExtensions [][]byte) comettypes.ExtendedCommitInfo {
|
||||
commitInfo := comettypes.ExtendedCommitInfo{
|
||||
Votes: suite.createExtendedVoteInfo(voteExtensions),
|
||||
}
|
||||
|
||||
return commitInfo
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package abci_test
|
||||
package v2_test
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -1,4 +1,4 @@
|
||||
package abci
|
||||
package v2
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
@ -9,6 +9,7 @@ import (
|
||||
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
pobabci "github.com/skip-mev/pob/abci"
|
||||
)
|
||||
|
||||
// TopOfBlock contains information about how the top of block should be built.
|
||||
@ -30,8 +31,9 @@ func NewTopOfBlock() TopOfBlock {
|
||||
}
|
||||
}
|
||||
|
||||
// BuildTOB inputs all of the vote extensions and outputs a top of block proposal that includes
|
||||
// the highest bidding valid transaction along with all the bundled transactions.
|
||||
// BuildTOB inputs all of the vote extensions and outputs a top of block proposal
|
||||
// that includes the highest bidding valid transaction along with all the bundled
|
||||
// transactions.
|
||||
func (h *ProposalHandler) BuildTOB(ctx sdk.Context, voteExtensionInfo abci.ExtendedCommitInfo, maxBytes int64) TopOfBlock {
|
||||
// Get the bid transactions from the vote extensions.
|
||||
sortedBidTxs := h.GetBidsFromVoteExtensions(voteExtensionInfo.Votes)
|
||||
@ -86,14 +88,14 @@ func (h *ProposalHandler) BuildTOB(ctx sdk.Context, voteExtensionInfo abci.Exten
|
||||
|
||||
// VerifyTOB verifies that the set of vote extensions used in prepare proposal deterministically
|
||||
// produce the same top of block proposal.
|
||||
func (h *ProposalHandler) VerifyTOB(ctx sdk.Context, proposalTxs [][]byte) (*AuctionInfo, error) {
|
||||
func (h *ProposalHandler) VerifyTOB(ctx sdk.Context, proposalTxs [][]byte) (*pobabci.AuctionInfo, error) {
|
||||
// Proposal must include at least the auction info.
|
||||
if len(proposalTxs) < NumInjectedTxs {
|
||||
return nil, fmt.Errorf("proposal is too small; expected at least %d slots", NumInjectedTxs)
|
||||
}
|
||||
|
||||
// Extract the auction info from the proposal.
|
||||
auctionInfo := &AuctionInfo{}
|
||||
auctionInfo := &pobabci.AuctionInfo{}
|
||||
if err := auctionInfo.Unmarshal(proposalTxs[AuctionInfoIndex]); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal auction info: %w", err)
|
||||
}
|
||||
@ -103,7 +105,7 @@ func (h *ProposalHandler) VerifyTOB(ctx sdk.Context, proposalTxs [][]byte) (*Auc
|
||||
return nil, fmt.Errorf("number of txs in proposal do not match expected in auction info; expected at least %d slots", auctionInfo.NumTxs+NumInjectedTxs)
|
||||
}
|
||||
|
||||
// Unmarshall the vote extension information from the auction info.
|
||||
// unmarshal the vote extension information from the auction info
|
||||
lastCommitInfo := abci.ExtendedCommitInfo{}
|
||||
if err := lastCommitInfo.Unmarshal(auctionInfo.ExtendedCommitInfo); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal last commit info from auction info: %w", err)
|
||||
@ -155,9 +157,10 @@ func (h *ProposalHandler) GetBidsFromVoteExtensions(voteExtensions []abci.Extend
|
||||
return bidTxs
|
||||
}
|
||||
|
||||
// buildTOB verifies that the auction and bundled transactions are valid and returns the transactions that
|
||||
// should be included in the top of block, size of the auction transaction and bundle, and a cache
|
||||
// of all transactions that should be ignored.
|
||||
// buildTOB verifies that the auction and bundled transactions are valid and
|
||||
// returns the transactions that should be included in the top of block, size
|
||||
// of the auction transaction and bundle, and a cache of all transactions that
|
||||
// should be ignored.
|
||||
func (h *ProposalHandler) buildTOB(ctx sdk.Context, bidTx sdk.Tx) (TopOfBlock, error) {
|
||||
proposal := NewTopOfBlock()
|
||||
|
||||
@ -210,7 +213,8 @@ func (h *ProposalHandler) buildTOB(ctx sdk.Context, bidTx sdk.Tx) (TopOfBlock, e
|
||||
return proposal, nil
|
||||
}
|
||||
|
||||
// getAuctionTxFromVoteExtension extracts the auction transaction from the vote extension.
|
||||
// getAuctionTxFromVoteExtension extracts the auction transaction from the vote
|
||||
// extension.
|
||||
func (h *ProposalHandler) getAuctionTxFromVoteExtension(voteExtension []byte) (sdk.Tx, error) {
|
||||
if len(voteExtension) == 0 {
|
||||
return nil, fmt.Errorf("vote extension is empty")
|
||||
@ -1,4 +1,4 @@
|
||||
package abci
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"github.com/cometbft/cometbft/libs/log"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool"
|
||||
pobabci "github.com/skip-mev/pob/abci"
|
||||
mempool "github.com/skip-mev/pob/mempool"
|
||||
)
|
||||
|
||||
@ -89,7 +90,7 @@ func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler {
|
||||
return abci.ResponsePrepareProposal{Txs: proposal}
|
||||
}
|
||||
|
||||
auctionInfo := AuctionInfo{
|
||||
auctionInfo := pobabci.AuctionInfo{
|
||||
ExtendedCommitInfo: lastCommitInfo,
|
||||
MaxTxBytes: req.MaxTxBytes,
|
||||
NumTxs: uint64(len(topOfBlock.Txs)),
|
||||
@ -1,9 +1,10 @@
|
||||
package abci_test
|
||||
package v2_test
|
||||
|
||||
import (
|
||||
comettypes "github.com/cometbft/cometbft/abci/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/skip-mev/pob/abci"
|
||||
v2 "github.com/skip-mev/pob/abci/v2"
|
||||
testutils "github.com/skip-mev/pob/testutils"
|
||||
"github.com/skip-mev/pob/x/builder/ante"
|
||||
buildertypes "github.com/skip-mev/pob/x/builder/types"
|
||||
@ -298,7 +299,7 @@ func (suite *ABCITestSuite) TestPrepareProposal() {
|
||||
suite.builderDecorator = ante.NewBuilderDecorator(suite.builderKeeper, suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), suite.mempool)
|
||||
|
||||
// Reset the proposal handler with the new mempool.
|
||||
suite.proposalHandler = abci.NewProposalHandler(suite.mempool, suite.logger, suite.anteHandler, suite.encodingConfig.TxConfig.TxEncoder(), suite.encodingConfig.TxConfig.TxDecoder())
|
||||
suite.proposalHandler = v2.NewProposalHandler(suite.mempool, suite.logger, suite.anteHandler, suite.encodingConfig.TxConfig.TxEncoder(), suite.encodingConfig.TxConfig.TxDecoder())
|
||||
|
||||
// Create a prepare proposal request based on the current state of the mempool.
|
||||
handler := suite.proposalHandler.PrepareProposalHandler()
|
||||
@ -308,12 +309,12 @@ func (suite *ABCITestSuite) TestPrepareProposal() {
|
||||
// -------------------- Check Invariants -------------------- //
|
||||
// The first slot in the proposal must be the auction info
|
||||
auctionInfo := abci.AuctionInfo{}
|
||||
err := auctionInfo.Unmarshal(res.Txs[abci.AuctionInfoIndex])
|
||||
err := auctionInfo.Unmarshal(res.Txs[v2.AuctionInfoIndex])
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Total bytes must be less than or equal to maxTxBytes
|
||||
totalBytes := int64(0)
|
||||
for _, tx := range res.Txs[abci.NumInjectedTxs:] {
|
||||
for _, tx := range res.Txs[v2.NumInjectedTxs:] {
|
||||
totalBytes += int64(len(tx))
|
||||
}
|
||||
suite.Require().LessOrEqual(totalBytes, maxTxBytes)
|
||||
@ -331,13 +332,13 @@ func (suite *ABCITestSuite) TestPrepareProposal() {
|
||||
suite.Require().NoError(err)
|
||||
|
||||
for index, tx := range bidInfo.Transactions {
|
||||
suite.Require().Equal(tx, res.Txs[abci.NumInjectedTxs+index+1])
|
||||
suite.Require().Equal(tx, res.Txs[v2.NumInjectedTxs+index+1])
|
||||
}
|
||||
}
|
||||
|
||||
// 5. All of the transactions must be unique
|
||||
uniqueTxs := make(map[string]bool)
|
||||
for _, tx := range res.Txs[abci.NumInjectedTxs:] {
|
||||
for _, tx := range res.Txs[v2.NumInjectedTxs:] {
|
||||
suite.Require().False(uniqueTxs[string(tx)])
|
||||
uniqueTxs[string(tx)] = true
|
||||
}
|
||||
@ -751,7 +752,7 @@ func (suite *ABCITestSuite) TestProcessProposal() {
|
||||
suite.builderDecorator = ante.NewBuilderDecorator(suite.builderKeeper, suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), suite.mempool)
|
||||
|
||||
// reset the proposal handler with the new mempool
|
||||
suite.proposalHandler = abci.NewProposalHandler(suite.mempool, suite.logger, suite.anteHandler, suite.encodingConfig.TxConfig.TxEncoder(), suite.encodingConfig.TxConfig.TxDecoder())
|
||||
suite.proposalHandler = v2.NewProposalHandler(suite.mempool, suite.logger, suite.anteHandler, suite.encodingConfig.TxConfig.TxEncoder(), suite.encodingConfig.TxConfig.TxDecoder())
|
||||
|
||||
handler := suite.proposalHandler.ProcessProposalHandler()
|
||||
res := handler(suite.ctx, comettypes.RequestProcessProposal{
|
||||
@ -1,10 +1,10 @@
|
||||
/*
|
||||
NOTE: These types are TEMPORARY and will be removed once the Cosmos SDK v0.38
|
||||
NOTE: These types are TEMPORARY and will be removed once the Cosmos SDK v0.48
|
||||
alpha/RC tag is released. These types are simply used to prototype and develop
|
||||
against.
|
||||
*/
|
||||
//nolint
|
||||
package abci
|
||||
package v2
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -1,4 +1,4 @@
|
||||
package abci
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
@ -1,8 +1,8 @@
|
||||
package abci_test
|
||||
package v2_test
|
||||
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/skip-mev/pob/abci"
|
||||
v2 "github.com/skip-mev/pob/abci/v2"
|
||||
"github.com/skip-mev/pob/mempool"
|
||||
testutils "github.com/skip-mev/pob/testutils"
|
||||
"github.com/skip-mev/pob/x/builder/types"
|
||||
@ -132,7 +132,7 @@ func (suite *ABCITestSuite) TestExtendVoteExtensionHandler() {
|
||||
expectedVE := tc.getExpectedVE()
|
||||
|
||||
// Reset the handler with the new mempool
|
||||
suite.voteExtensionHandler = abci.NewVoteExtensionHandler(suite.mempool, suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), suite.anteHandler)
|
||||
suite.voteExtensionHandler = v2.NewVoteExtensionHandler(suite.mempool, suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), suite.anteHandler)
|
||||
|
||||
handler := suite.voteExtensionHandler.ExtendVoteHandler()
|
||||
resp, err := handler(suite.ctx, nil)
|
||||
@ -156,13 +156,13 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
req func() *abci.RequestVerifyVoteExtension
|
||||
req func() *v2.RequestVerifyVoteExtension
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
"invalid vote extension bytes",
|
||||
func() *abci.RequestVerifyVoteExtension {
|
||||
return &abci.RequestVerifyVoteExtension{
|
||||
func() *v2.RequestVerifyVoteExtension {
|
||||
return &v2.RequestVerifyVoteExtension{
|
||||
VoteExtension: []byte("invalid vote extension"),
|
||||
}
|
||||
},
|
||||
@ -170,8 +170,8 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
},
|
||||
{
|
||||
"empty vote extension bytes",
|
||||
func() *abci.RequestVerifyVoteExtension {
|
||||
return &abci.RequestVerifyVoteExtension{
|
||||
func() *v2.RequestVerifyVoteExtension {
|
||||
return &v2.RequestVerifyVoteExtension{
|
||||
VoteExtension: []byte{},
|
||||
}
|
||||
},
|
||||
@ -179,8 +179,8 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
},
|
||||
{
|
||||
"nil vote extension bytes",
|
||||
func() *abci.RequestVerifyVoteExtension {
|
||||
return &abci.RequestVerifyVoteExtension{
|
||||
func() *v2.RequestVerifyVoteExtension {
|
||||
return &v2.RequestVerifyVoteExtension{
|
||||
VoteExtension: nil,
|
||||
}
|
||||
},
|
||||
@ -188,14 +188,14 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
},
|
||||
{
|
||||
"invalid extension with bid tx with bad timeout",
|
||||
func() *abci.RequestVerifyVoteExtension {
|
||||
func() *v2.RequestVerifyVoteExtension {
|
||||
bidder := suite.accounts[0]
|
||||
bid := sdk.NewCoin("foo", sdk.NewInt(10))
|
||||
signers := []testutils.Account{bidder}
|
||||
timeout := 0
|
||||
|
||||
bz := suite.createAuctionTxBz(bidder, bid, signers, timeout)
|
||||
return &abci.RequestVerifyVoteExtension{
|
||||
return &v2.RequestVerifyVoteExtension{
|
||||
VoteExtension: bz,
|
||||
}
|
||||
},
|
||||
@ -203,14 +203,14 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
},
|
||||
{
|
||||
"invalid vote extension with bid tx with bad bid",
|
||||
func() *abci.RequestVerifyVoteExtension {
|
||||
func() *v2.RequestVerifyVoteExtension {
|
||||
bidder := suite.accounts[0]
|
||||
bid := sdk.NewCoin("foo", sdk.NewInt(0))
|
||||
signers := []testutils.Account{bidder}
|
||||
timeout := 10
|
||||
|
||||
bz := suite.createAuctionTxBz(bidder, bid, signers, timeout)
|
||||
return &abci.RequestVerifyVoteExtension{
|
||||
return &v2.RequestVerifyVoteExtension{
|
||||
VoteExtension: bz,
|
||||
}
|
||||
},
|
||||
@ -218,14 +218,14 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
},
|
||||
{
|
||||
"valid vote extension",
|
||||
func() *abci.RequestVerifyVoteExtension {
|
||||
func() *v2.RequestVerifyVoteExtension {
|
||||
bidder := suite.accounts[0]
|
||||
bid := params.ReserveFee
|
||||
signers := []testutils.Account{bidder}
|
||||
timeout := 10
|
||||
|
||||
bz := suite.createAuctionTxBz(bidder, bid, signers, timeout)
|
||||
return &abci.RequestVerifyVoteExtension{
|
||||
return &v2.RequestVerifyVoteExtension{
|
||||
VoteExtension: bz,
|
||||
}
|
||||
},
|
||||
@ -233,7 +233,7 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
},
|
||||
{
|
||||
"invalid vote extension with front running bid tx",
|
||||
func() *abci.RequestVerifyVoteExtension {
|
||||
func() *v2.RequestVerifyVoteExtension {
|
||||
bidder := suite.accounts[0]
|
||||
bid := params.ReserveFee
|
||||
timeout := 10
|
||||
@ -242,7 +242,7 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
signers := []testutils.Account{bidder, bundlee}
|
||||
|
||||
bz := suite.createAuctionTxBz(bidder, bid, signers, timeout)
|
||||
return &abci.RequestVerifyVoteExtension{
|
||||
return &v2.RequestVerifyVoteExtension{
|
||||
VoteExtension: bz,
|
||||
}
|
||||
},
|
||||
@ -250,7 +250,7 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
},
|
||||
{
|
||||
"invalid vote extension with too many bundle txs",
|
||||
func() *abci.RequestVerifyVoteExtension {
|
||||
func() *v2.RequestVerifyVoteExtension {
|
||||
// disable front running protection
|
||||
params.FrontRunningProtection = false
|
||||
err := suite.builderKeeper.SetParams(suite.ctx, params)
|
||||
@ -262,7 +262,7 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
timeout := 10
|
||||
|
||||
bz := suite.createAuctionTxBz(bidder, bid, signers, timeout)
|
||||
return &abci.RequestVerifyVoteExtension{
|
||||
return &v2.RequestVerifyVoteExtension{
|
||||
VoteExtension: bz,
|
||||
}
|
||||
},
|
||||
@ -270,7 +270,7 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
},
|
||||
{
|
||||
"invalid vote extension with a failing bundle tx",
|
||||
func() *abci.RequestVerifyVoteExtension {
|
||||
func() *v2.RequestVerifyVoteExtension {
|
||||
bidder := suite.accounts[0]
|
||||
bid := params.ReserveFee
|
||||
|
||||
@ -286,7 +286,7 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
bz, err := suite.encodingConfig.TxConfig.TxEncoder()(bidTx)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
return &abci.RequestVerifyVoteExtension{
|
||||
return &v2.RequestVerifyVoteExtension{
|
||||
VoteExtension: bz,
|
||||
}
|
||||
},
|
||||
@ -294,7 +294,7 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
},
|
||||
{
|
||||
"valid vote extension + no comparison to local mempool",
|
||||
func() *abci.RequestVerifyVoteExtension {
|
||||
func() *v2.RequestVerifyVoteExtension {
|
||||
bidder := suite.accounts[0]
|
||||
bid := params.ReserveFee
|
||||
signers := []testutils.Account{bidder}
|
||||
@ -313,7 +313,7 @@ func (suite *ABCITestSuite) TestVerifyVoteExtensionHandler() {
|
||||
tx := suite.mempool.GetTopAuctionTx(suite.ctx)
|
||||
suite.Require().NotNil(tx)
|
||||
|
||||
return &abci.RequestVerifyVoteExtension{
|
||||
return &v2.RequestVerifyVoteExtension{
|
||||
VoteExtension: bz,
|
||||
}
|
||||
},
|
||||
5
go.mod
5
go.mod
@ -178,3 +178,8 @@ require (
|
||||
pgregory.net/rapid v0.5.5 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
|
||||
github.com/syndtr/goleveldb => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
|
||||
)
|
||||
|
||||
27
go.sum
27
go.sum
@ -205,8 +205,6 @@ filippo.io/edwards25519 v1.0.0 h1:0wAIcmJUqRdI8IJ/3eGi5/HwXZWPujYXXlkrQogz0Ek=
|
||||
filippo.io/edwards25519 v1.0.0/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs=
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4=
|
||||
github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o=
|
||||
github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
@ -337,6 +335,8 @@ github.com/cosmos/gogoproto v1.4.10 h1:QH/yT8X+c0F4ZDacDv3z+xE3WU1P1Z3wQoLMBRJoK
|
||||
github.com/cosmos/gogoproto v1.4.10/go.mod h1:3aAZzeRWpAwr+SS/LLkICX2/kDFyaYVzckBDzygIxek=
|
||||
github.com/cosmos/iavl v0.20.0 h1:fTVznVlepH0KK8NyKq8w+U7c2L6jofa27aFX6YGlm38=
|
||||
github.com/cosmos/iavl v0.20.0/go.mod h1:WO7FyvaZJoH65+HFOsDir7xU9FWk2w9cHXNW1XHcl7A=
|
||||
github.com/cosmos/keyring v1.2.0 h1:8C1lBP9xhImmIabyXW4c3vFjjLiBdGCmfLUfeZlV1Yo=
|
||||
github.com/cosmos/keyring v1.2.0/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1 h1:sMBxza5p/rNK/06nBSNmsI/WDqI0pVJFVNihy1Y984w=
|
||||
github.com/cosmos/ledger-cosmos-go v0.12.1/go.mod h1:dhO6kj+Y+AHIOgAe4L9HL/6NDdyyth4q238I9yFpD2g=
|
||||
github.com/cosmos/rosetta-sdk-go v0.10.0 h1:E5RhTruuoA7KTIXUcMicL76cffyeoyvNybzUGSKFTcM=
|
||||
@ -412,7 +412,6 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
@ -445,7 +444,6 @@ github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GO
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
|
||||
@ -553,7 +551,6 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
@ -777,22 +774,17 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
@ -940,7 +932,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
@ -948,8 +939,8 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
|
||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||
github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E=
|
||||
github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME=
|
||||
github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg=
|
||||
@ -1102,6 +1093,7 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
@ -1112,7 +1104,6 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
@ -1216,16 +1207,17 @@ golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -1349,7 +1341,6 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u
|
||||
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
|
||||
@ -12,13 +12,14 @@ func (s *IntegrationTestSuite) TestGetBuilderParams() {
|
||||
s.Require().NotNil(params)
|
||||
}
|
||||
|
||||
// TestBundles tests the execution of various auction bids. There are a few invarients that are
|
||||
// tested:
|
||||
// TestBundles tests the execution of various auction bids. There are a few
|
||||
// invariants that are tested:
|
||||
//
|
||||
// 1. The order of transactions in a bundle is preserved when bids are valid.
|
||||
// 2. All transactions execute as expected.
|
||||
// 3. The balance of the escrow account should be updated correctly.
|
||||
// 4. Top of block bids will be included in block proposals before other transactions that are
|
||||
// included in the same block.
|
||||
// 4. Top of block bids will be included in block proposals before other transactions
|
||||
// that are included in the same block.
|
||||
func (s *IntegrationTestSuite) TestBundles() {
|
||||
// Create the accounts that will create transactions to be included in bundles
|
||||
initBalance := sdk.NewInt64Coin(app.BondDenom, 10000000000)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user