fix(Config): Simplifying config interface (#104)
This commit is contained in:
+25
-85
@@ -16,11 +16,8 @@ var _ sdk.AnteDecorator = BuilderDecorator{}
|
||||
type (
|
||||
Mempool interface {
|
||||
Contains(tx sdk.Tx) (bool, error)
|
||||
IsAuctionTx(tx sdk.Tx) (bool, error)
|
||||
GetAuctionBidInfo(tx sdk.Tx) (mempool.AuctionBidInfo, error)
|
||||
GetBundleSigners(txs [][]byte) ([]map[string]struct{}, error)
|
||||
GetAuctionBidInfo(tx sdk.Tx) (*mempool.AuctionBidInfo, error)
|
||||
GetTopAuctionTx(ctx context.Context) sdk.Tx
|
||||
GetTimeout(tx sdk.Tx) (uint64, error)
|
||||
}
|
||||
|
||||
BuilderDecorator struct {
|
||||
@@ -55,108 +52,51 @@ func (ad BuilderDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool,
|
||||
}
|
||||
}
|
||||
|
||||
isAuctionTx, err := ad.mempool.IsAuctionTx(tx)
|
||||
bidInfo, err := ad.mempool.GetAuctionBidInfo(tx)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// Validate the auction bid if one exists.
|
||||
if isAuctionTx {
|
||||
if bidInfo != nil {
|
||||
// Auction transactions must have a timeout set to a valid block height.
|
||||
if err := ad.HasValidTimeout(ctx, tx); err != nil {
|
||||
return ctx, err
|
||||
if int64(bidInfo.Timeout) < ctx.BlockHeight() {
|
||||
return ctx, fmt.Errorf("timeout height cannot be less than the current block height")
|
||||
}
|
||||
|
||||
bidInfo, err := ad.mempool.GetAuctionBidInfo(tx)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// If the current transaction is the highest bidding transaction, then the highest bid is empty.
|
||||
topBid := sdk.Coin{}
|
||||
|
||||
// We only need to verify the auction bid relative to the local validator's mempool if the mode
|
||||
// is checkTx or recheckTx. Otherwise, the ABCI handlers (VerifyVoteExtension, ExtendVoteExtension, etc.)
|
||||
// will always compare the auction bid to the highest bidding transaction in the mempool leading to
|
||||
// poor liveness guarantees.
|
||||
topBid := sdk.Coin{}
|
||||
if ctx.IsCheckTx() || ctx.IsReCheckTx() {
|
||||
isTopBidTx, err := ad.IsTopBidTx(ctx, tx)
|
||||
if err != nil {
|
||||
return ctx, errors.Wrap(err, "failed to check if current transaction is highest bidding transaction")
|
||||
}
|
||||
|
||||
if !isTopBidTx {
|
||||
// Set the top bid to the highest bidding transaction.
|
||||
topBid, err = ad.GetTopAuctionBid(ctx)
|
||||
if topBidTx := ad.mempool.GetTopAuctionTx(ctx); topBidTx != nil {
|
||||
topBidBz, err := ad.txEncoder(topBidTx)
|
||||
if err != nil {
|
||||
return ctx, errors.Wrap(err, "failed to get highest auction bid")
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
currentTxBz, err := ad.txEncoder(tx)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
// Compare the bytes to see if the current transaction is the highest bidding transaction.
|
||||
if !bytes.Equal(topBidBz, currentTxBz) {
|
||||
topBidInfo, err := ad.mempool.GetAuctionBidInfo(topBidTx)
|
||||
if err != nil {
|
||||
return ctx, err
|
||||
}
|
||||
|
||||
topBid = topBidInfo.Bid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract signers from bundle for verification.
|
||||
signers, err := ad.mempool.GetBundleSigners(bidInfo.Transactions)
|
||||
if err != nil {
|
||||
return ctx, errors.Wrap(err, "failed to get bundle signers")
|
||||
}
|
||||
|
||||
if err := ad.builderKeeper.ValidateBidInfo(ctx, topBid, bidInfo, signers); err != nil {
|
||||
if err := ad.builderKeeper.ValidateBidInfo(ctx, topBid, bidInfo); err != nil {
|
||||
return ctx, errors.Wrap(err, "failed to validate auction bid")
|
||||
}
|
||||
}
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// GetTopAuctionBid returns the highest auction bid if one exists.
|
||||
func (ad BuilderDecorator) GetTopAuctionBid(ctx sdk.Context) (sdk.Coin, error) {
|
||||
auctionTx := ad.mempool.GetTopAuctionTx(ctx)
|
||||
if auctionTx == nil {
|
||||
return sdk.Coin{}, nil
|
||||
}
|
||||
|
||||
auctionBidInfo, err := ad.mempool.GetAuctionBidInfo(auctionTx)
|
||||
if err != nil {
|
||||
return sdk.Coin{}, err
|
||||
}
|
||||
|
||||
return auctionBidInfo.Bid, nil
|
||||
}
|
||||
|
||||
// IsTopBidTx returns true if the transaction inputted is the highest bidding auction transaction in the mempool.
|
||||
func (ad BuilderDecorator) IsTopBidTx(ctx sdk.Context, tx sdk.Tx) (bool, error) {
|
||||
auctionTx := ad.mempool.GetTopAuctionTx(ctx)
|
||||
if auctionTx == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
topBidBz, err := ad.txEncoder(auctionTx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
currentTxBz, err := ad.txEncoder(tx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return bytes.Equal(topBidBz, currentTxBz), nil
|
||||
}
|
||||
|
||||
// HasValidTimeout returns true if the transaction has a valid timeout height.
|
||||
func (ad BuilderDecorator) HasValidTimeout(ctx sdk.Context, tx sdk.Tx) error {
|
||||
timeout, err := ad.mempool.GetTimeout(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if timeout == 0 {
|
||||
return fmt.Errorf("timeout height cannot be zero")
|
||||
}
|
||||
|
||||
if timeout < uint64(ctx.BlockHeight()) {
|
||||
return fmt.Errorf("timeout height cannot be less than the current block height")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -46,8 +46,7 @@ func (suite *AnteTestSuite) SetupTest() {
|
||||
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
|
||||
suite.ctx = suite.ctx.WithIsCheckTx(true)
|
||||
suite.ctx = testCtx.Ctx.WithIsCheckTx(true)
|
||||
|
||||
// Keepers set up
|
||||
ctrl := gomock.NewController(suite.T())
|
||||
@@ -234,6 +233,8 @@ func (suite *AnteTestSuite) TestAnteHandler() {
|
||||
suite.SetupTest()
|
||||
tc.malleate()
|
||||
|
||||
suite.ctx = suite.ctx.WithBlockHeight(1)
|
||||
|
||||
// Set the auction params
|
||||
err := suite.builderKeeper.SetParams(suite.ctx, buildertypes.Params{
|
||||
MaxBundleSize: maxBundleSize,
|
||||
@@ -245,7 +246,7 @@ func (suite *AnteTestSuite) TestAnteHandler() {
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Insert the top bid into the mempool
|
||||
config := mempool.NewDefaultConfig(suite.encodingConfig.TxConfig.TxDecoder())
|
||||
config := mempool.NewDefaultAuctionFactory(suite.encodingConfig.TxConfig.TxDecoder())
|
||||
mempool := mempool.NewAuctionMempool(suite.encodingConfig.TxConfig.TxDecoder(), suite.encodingConfig.TxConfig.TxEncoder(), 0, config)
|
||||
if insertTopBid {
|
||||
topAuctionTx, err := testutils.CreateAuctionTxWithSigners(suite.encodingConfig.TxConfig, topBidder, topBid, 0, timeout, []testutils.Account{})
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
// ValidateBidInfo validates that the bid can be included in the auction.
|
||||
func (k Keeper) ValidateBidInfo(ctx sdk.Context, highestBid sdk.Coin, bidInfo mempool.AuctionBidInfo, signers []map[string]struct{}) error {
|
||||
func (k Keeper) ValidateBidInfo(ctx sdk.Context, highestBid sdk.Coin, bidInfo *mempool.AuctionBidInfo) error {
|
||||
// Validate the bundle size.
|
||||
maxBundleSize, err := k.GetMaxBundleSize(ctx)
|
||||
if err != nil {
|
||||
@@ -31,7 +31,7 @@ func (k Keeper) ValidateBidInfo(ctx sdk.Context, highestBid sdk.Coin, bidInfo me
|
||||
}
|
||||
|
||||
if protectionEnabled {
|
||||
if err := k.ValidateAuctionBundle(bidInfo.Bidder, signers); err != nil {
|
||||
if err := k.ValidateAuctionBundle(bidInfo.Bidder, bidInfo.Signers); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
buildertypes "github.com/skip-mev/pob/x/builder/types"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestValidateAuctionMsg() {
|
||||
func (suite *KeeperTestSuite) TestValidateBidInfo() {
|
||||
var (
|
||||
// Tx building variables
|
||||
accounts = []testutils.Account{} // tracks the order of signers in the bundle
|
||||
@@ -192,16 +192,23 @@ func (suite *KeeperTestSuite) TestValidateAuctionMsg() {
|
||||
bundle = append(bundle, txBz)
|
||||
}
|
||||
|
||||
bidInfo := mempool.AuctionBidInfo{
|
||||
signers := make([]map[string]struct{}, len(accounts))
|
||||
for index, acc := range accounts {
|
||||
txSigners := map[string]struct{}{
|
||||
acc.Address.String(): {},
|
||||
}
|
||||
|
||||
signers[index] = txSigners
|
||||
}
|
||||
|
||||
bidInfo := &mempool.AuctionBidInfo{
|
||||
Bidder: bidder.Address,
|
||||
Bid: bid,
|
||||
Transactions: bundle,
|
||||
Signers: signers,
|
||||
}
|
||||
|
||||
signers, err := suite.mempool.GetBundleSigners(bundle)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
err = suite.builderKeeper.ValidateBidInfo(suite.ctx, highestBid, bidInfo, signers)
|
||||
err := suite.builderKeeper.ValidateBidInfo(suite.ctx, highestBid, bidInfo)
|
||||
if tc.pass {
|
||||
suite.Require().NoError(err)
|
||||
} else {
|
||||
@@ -302,23 +309,17 @@ func (suite *KeeperTestSuite) TestValidateBundle() {
|
||||
// Malleate the test case
|
||||
tc.malleate()
|
||||
|
||||
// Create the bundle of transactions ordered by accounts
|
||||
bundle := make([][]byte, 0)
|
||||
for _, acc := range accounts {
|
||||
// Create a random tx
|
||||
tx, err := testutils.CreateRandomTx(suite.encCfg.TxConfig, acc, 0, 1, 1000)
|
||||
suite.Require().NoError(err)
|
||||
signers := make([]map[string]struct{}, len(accounts))
|
||||
for index, acc := range accounts {
|
||||
txSigners := map[string]struct{}{
|
||||
acc.Address.String(): {},
|
||||
}
|
||||
|
||||
txBz, err := suite.encCfg.TxConfig.TxEncoder()(tx)
|
||||
suite.Require().NoError(err)
|
||||
bundle = append(bundle, txBz)
|
||||
signers[index] = txSigners
|
||||
}
|
||||
|
||||
signers, err := suite.mempool.GetBundleSigners(bundle)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// Validate the bundle
|
||||
err = suite.builderKeeper.ValidateAuctionBundle(bidder.Address, signers)
|
||||
err := suite.builderKeeper.ValidateAuctionBundle(bidder.Address, signers)
|
||||
if tc.pass {
|
||||
suite.Require().NoError(err)
|
||||
} else {
|
||||
|
||||
@@ -64,7 +64,7 @@ func (suite *KeeperTestSuite) SetupTest() {
|
||||
err := suite.builderKeeper.SetParams(suite.ctx, types.DefaultParams())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
config := mempool.NewDefaultConfig(suite.encCfg.TxConfig.TxDecoder())
|
||||
config := mempool.NewDefaultAuctionFactory(suite.encCfg.TxConfig.TxDecoder())
|
||||
suite.mempool = mempool.NewAuctionMempool(suite.encCfg.TxConfig.TxDecoder(), suite.encCfg.TxConfig.TxEncoder(), 0, config)
|
||||
suite.msgServer = keeper.NewMsgServerImpl(suite.builderKeeper)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user