feat(BB): Better proposal, better docs, better logging, papa johns (#172)

This commit is contained in:
David Terpay
2023-06-09 14:50:49 +00:00
committed by GitHub
parent 3d505edf31
commit cee39a9eb7
17 changed files with 404 additions and 165 deletions
+2 -2
View File
@@ -272,11 +272,11 @@ func (suite *ABCITestSuite) createExtendedCommitInfoFromTxBzs(txs [][]byte) []by
return commitInfoBz
}
func (suite *ABCITestSuite) createAuctionInfoFromTxBzs(txs [][]byte, numTxs uint64) []byte {
func (suite *ABCITestSuite) createAuctionInfoFromTxBzs(txs [][]byte, numTxs uint64, maxTxBytes int64) []byte {
auctionInfo := abci.AuctionInfo{
ExtendedCommitInfo: suite.createExtendedCommitInfoFromTxBzs(txs),
NumTxs: numTxs,
MaxTxBytes: int64(len(txs[0])),
MaxTxBytes: maxTxBytes,
}
auctionInfoBz, err := auctionInfo.Marshal()
+6 -6
View File
@@ -481,11 +481,11 @@ func (suite *ABCITestSuite) TestBuildTOB() {
proposal := suite.proposalHandler.BuildTOB(suite.ctx, commitInfo, tc.maxBytes)
// Size of the proposal should be less than or equal to the max bytes
suite.Require().LessOrEqual(proposal.TotalTxBytes, tc.maxBytes)
suite.Require().LessOrEqual(proposal.GetTotalTxBytes(), tc.maxBytes)
if winningBid == nil {
suite.Require().Len(proposal.Txs, 0)
suite.Require().Equal(proposal.TotalTxBytes, int64(0))
suite.Require().Len(proposal.GetTxs(), 0)
suite.Require().Equal(proposal.GetTotalTxBytes(), int64(0))
} else {
// Get info about the winning bid
winningBidBz, err := suite.encodingConfig.TxConfig.TxEncoder()(winningBid)
@@ -496,13 +496,13 @@ func (suite *ABCITestSuite) TestBuildTOB() {
// Verify that the size of the proposal is the size of the winning bid
// plus the size of the bundle
suite.Require().Equal(len(proposal.Txs), len(auctionBidInfo.Transactions)+1)
suite.Require().Equal(len(proposal.GetTxs()), len(auctionBidInfo.Transactions)+1)
// Verify that the winning bid is the first transaction in the proposal
suite.Require().Equal(proposal.Txs[0], winningBidBz)
suite.Require().Equal(proposal.GetTxs()[0], winningBidBz)
// Verify the ordering of transactions in the proposal
for index, tx := range proposal.Txs[1:] {
for index, tx := range proposal.GetTxs()[1:] {
suite.Equal(tx, auctionBidInfo.Transactions[index])
}
}
+15 -13
View File
@@ -91,7 +91,7 @@ func (h *ProposalHandler) VerifyTOB(ctx sdk.Context, proposalTxs [][]byte) (*Auc
// Verify that the top of block txs matches the top of block proposal txs.
actualTOBTxs := proposalTxs[NumInjectedTxs : auctionInfo.NumTxs+NumInjectedTxs]
if !reflect.DeepEqual(actualTOBTxs, expectedTOB.Txs) {
if !reflect.DeepEqual(actualTOBTxs, expectedTOB.GetTxs()) {
return nil, fmt.Errorf("expected top of block txs does not match top of block proposal")
}
@@ -140,16 +140,17 @@ func (h *ProposalHandler) buildTOB(ctx sdk.Context, bidTx sdk.Tx, maxBytes int64
proposal := blockbuster.NewProposal(maxBytes)
// cache the bytes of the bid transaction
txBz, hash, err := utils.GetTxHashStr(h.txEncoder, bidTx)
txBz, _, err := utils.GetTxHashStr(h.txEncoder, bidTx)
if err != nil {
return proposal, err
}
proposal.Cache[hash] = struct{}{}
proposal.TotalTxBytes = int64(len(txBz))
proposal.Txs = append(proposal.Txs, txBz)
if int64(len(txBz)) > maxBytes {
maxBytesForLane := utils.GetMaxTxBytesForLane(
proposal.GetMaxTxBytes(),
proposal.GetTotalTxBytes(),
h.tobLane.GetMaxBlockSpace(),
)
if int64(len(txBz)) > maxBytesForLane {
return proposal, fmt.Errorf("bid transaction is too large; got %d, max %d", len(txBz), maxBytes)
}
@@ -164,10 +165,10 @@ func (h *ProposalHandler) buildTOB(ctx sdk.Context, bidTx sdk.Tx, maxBytes int64
}
// store the bytes of each ref tx as sdk.Tx bytes in order to build a valid proposal
sdkTxBytes := make([][]byte, len(bidInfo.Transactions))
txs := [][]byte{txBz}
// Ensure that the bundled transactions are valid
for index, rawRefTx := range bidInfo.Transactions {
for _, rawRefTx := range bidInfo.Transactions {
// convert the bundled raw transaction to a sdk.Tx
refTx, err := h.tobLane.WrapBundleTransaction(rawRefTx)
if err != nil {
@@ -175,17 +176,18 @@ func (h *ProposalHandler) buildTOB(ctx sdk.Context, bidTx sdk.Tx, maxBytes int64
}
// convert the sdk.Tx to a hash and bytes
txBz, hash, err := utils.GetTxHashStr(h.txEncoder, refTx)
txBz, _, err := utils.GetTxHashStr(h.txEncoder, refTx)
if err != nil {
return proposal, err
}
proposal.Cache[hash] = struct{}{}
sdkTxBytes[index] = txBz
txs = append(txs, txBz)
}
// Add the bundled transactions to the proposal.
proposal.Txs = append(proposal.Txs, sdkTxBytes...)
if err := proposal.UpdateProposal(h.tobLane, txs); err != nil {
return proposal, err
}
return proposal, nil
}
+18 -4
View File
@@ -42,6 +42,16 @@ type (
// ProcessLaneBasic is utilized to verify the rest of the proposal according to
// the preferences of the top of block lane.
ProcessLaneBasic(txs []sdk.Tx) error
// GetMaxBlockSpace returns the maximum block space that can be used by the top of
// block lane as a percentage of the total block space.
GetMaxBlockSpace() sdk.Dec
// Logger returns the logger for the top of block lane.
Logger() log.Logger
// Name returns the name of the top of block lane.
Name() string
}
// ProposalHandler contains the functionality and handlers required to\
@@ -94,7 +104,7 @@ func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler {
auctionInfo := &AuctionInfo{
ExtendedCommitInfo: lastCommitInfo,
MaxTxBytes: req.MaxTxBytes,
NumTxs: uint64(len(topOfBlock.Txs)),
NumTxs: uint64(topOfBlock.GetNumTxs()),
}
// Add the auction info and top of block transactions into the proposal.
@@ -104,13 +114,17 @@ func (h *ProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHandler {
return cometabci.ResponsePrepareProposal{Txs: nil}
}
topOfBlock.Txs = append([][]byte{auctionInfoBz}, topOfBlock.Txs...)
topOfBlock.AddVoteExtension(auctionInfoBz)
// Prepare the proposal by selecting transactions from each lane according to
// each lane's selection logic.
proposal := h.prepareLanesHandler(ctx, topOfBlock)
proposal, err := h.prepareLanesHandler(ctx, topOfBlock)
if err != nil {
h.logger.Error("failed to prepare proposal", "err", err)
return cometabci.ResponsePrepareProposal{Txs: nil}
}
return cometabci.ResponsePrepareProposal{Txs: proposal.Txs}
return cometabci.ResponsePrepareProposal{Txs: proposal.GetProposal()}
}
}
+15 -10
View File
@@ -13,6 +13,8 @@ import (
buildertypes "github.com/skip-mev/pob/x/builder/types"
)
// TODO:
// - Add tests that can that trigger a panic for the tob of block lane
func (suite *ABCITestSuite) TestPrepareProposal() {
var (
// the modified transactions cannot exceed this size
@@ -355,12 +357,15 @@ func (suite *ABCITestSuite) TestPrepareProposal() {
}
}
// TODO:
// - Add tests that ensure that the top of block lane does not propose more transactions than it is allowed to
func (suite *ABCITestSuite) TestProcessProposal() {
var (
// auction configuration
maxBundleSize uint32 = 10
reserveFee = sdk.NewCoin("foo", sdk.NewInt(1000))
frontRunningProtection = true
maxTxBytes int64 = 1000000000000000000
// mempool configuration
proposal [][]byte
@@ -448,7 +453,7 @@ func (suite *ABCITestSuite) TestProcessProposal() {
normalTx, err := testutils.CreateRandomTxBz(suite.encodingConfig.TxConfig, account, nonce, numberMsgs, timeout)
suite.Require().NoError(err)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTx}, 2)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTx}, 2, maxTxBytes)
proposal = [][]byte{
auctionInfo,
@@ -470,7 +475,7 @@ func (suite *ABCITestSuite) TestProcessProposal() {
bidTxBz, err := testutils.CreateAuctionTxWithSignerBz(suite.encodingConfig.TxConfig, bidder, bid, nonce, timeout, signers)
suite.Require().NoError(err)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, 2)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, 2, maxTxBytes)
bidInfo := suite.getAuctionBidInfoFromTxBz(bidTxBz)
@@ -496,7 +501,7 @@ func (suite *ABCITestSuite) TestProcessProposal() {
bidTxBz, err := testutils.CreateAuctionTxWithSignerBz(suite.encodingConfig.TxConfig, bidder, bid, nonce, timeout, signers)
suite.Require().NoError(err)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, 3)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, 3, maxTxBytes)
bidInfo := suite.getAuctionBidInfoFromTxBz(bidTxBz)
@@ -521,7 +526,7 @@ func (suite *ABCITestSuite) TestProcessProposal() {
bidTxBz, err := testutils.CreateAuctionTxWithSignerBz(suite.encodingConfig.TxConfig, bidder, bid, nonce, timeout, signers)
suite.Require().NoError(err)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, 3)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, 3, maxTxBytes)
bidInfo := suite.getAuctionBidInfoFromTxBz(bidTxBz)
proposal = append(
@@ -555,7 +560,7 @@ func (suite *ABCITestSuite) TestProcessProposal() {
bidTxBz2, err := testutils.CreateAuctionTxWithSignerBz(suite.encodingConfig.TxConfig, bidder, bid, nonce, timeout, signers)
suite.Require().NoError(err)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz, bidTxBz2}, 3)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz, bidTxBz2}, 3, maxTxBytes)
bidInfo := suite.getAuctionBidInfoFromTxBz(bidTxBz)
@@ -590,7 +595,7 @@ func (suite *ABCITestSuite) TestProcessProposal() {
bidTxBz2, err := testutils.CreateAuctionTxWithSignerBz(suite.encodingConfig.TxConfig, bidder, bid, nonce, timeout, signers)
suite.Require().NoError(err)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz, bidTxBz2}, 2)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz, bidTxBz2}, 2, maxTxBytes)
bidInfo := suite.getAuctionBidInfoFromTxBz(bidTxBz2)
@@ -625,7 +630,7 @@ func (suite *ABCITestSuite) TestProcessProposal() {
bidTxBz2, err := testutils.CreateAuctionTxWithSignerBz(suite.encodingConfig.TxConfig, bidder, bid, nonce, timeout, signers)
suite.Require().NoError(err)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz, bidTxBz2}, 2)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz, bidTxBz2}, 2, maxTxBytes)
bidInfo := suite.getAuctionBidInfoFromTxBz(bidTxBz2)
bidInfo2 := suite.getAuctionBidInfoFromTxBz(bidTxBz)
@@ -655,7 +660,7 @@ func (suite *ABCITestSuite) TestProcessProposal() {
bidTxBz, err := testutils.CreateAuctionTxWithSignerBz(suite.encodingConfig.TxConfig, bidder, bid, nonce, timeout, signers)
suite.Require().NoError(err)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, 2)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, 2, maxTxBytes)
bidInfo := suite.getAuctionBidInfoFromTxBz(bidTxBz)
@@ -683,7 +688,7 @@ func (suite *ABCITestSuite) TestProcessProposal() {
bidTxBz, err := testutils.CreateAuctionTxWithSignerBz(suite.encodingConfig.TxConfig, bidder, bid, nonce, timeout, signers)
suite.Require().NoError(err)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, 2)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, 2, maxTxBytes)
bidInfo := suite.getAuctionBidInfoFromTxBz(bidTxBz)
@@ -717,7 +722,7 @@ func (suite *ABCITestSuite) TestProcessProposal() {
bidTxBz, err := testutils.CreateAuctionTxWithSignerBz(suite.encodingConfig.TxConfig, bidder, bid, nonce, timeout, signers)
suite.Require().NoError(err)
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, uint64(len(signers)+1))
auctionInfo := suite.createAuctionInfoFromTxBzs([][]byte{bidTxBz}, uint64(len(signers)+1), maxTxBytes)
bidInfo := suite.getAuctionBidInfoFromTxBz(bidTxBz)