From 8d1fe85a1ea24d45389b858de025ba28af762891 Mon Sep 17 00:00:00 2001 From: beer-1 <147697694+beer-1@users.noreply.github.com> Date: Wed, 13 Dec 2023 14:03:40 +0900 Subject: [PATCH] use custom free lane --- app/app.go | 8 +-- app/lanes/free.go | 36 ++++++++-- app/lanes/mempool.go | 132 +++++++++++++++++++++++++++++++++++ app/lanes/priority.go | 159 +++--------------------------------------- 4 files changed, 173 insertions(+), 162 deletions(-) create mode 100644 app/lanes/mempool.go diff --git a/app/app.go b/app/app.go index 71780991..a71e5796 100644 --- a/app/app.go +++ b/app/app.go @@ -151,7 +151,6 @@ import ( signer_extraction "github.com/skip-mev/block-sdk/adapters/signer_extraction_adapter" "github.com/skip-mev/block-sdk/block" blockbase "github.com/skip-mev/block-sdk/block/base" - freelane "github.com/skip-mev/block-sdk/lanes/free" "github.com/skip-mev/block-sdk/lanes/mev" "github.com/skip-mev/block-sdk/x/auction" auctionante "github.com/skip-mev/block-sdk/x/auction/ante" @@ -1002,12 +1001,7 @@ func NewInitiaApp( MaxTxs: 10, SignerExtractor: signerExtractor, } - - freeLane := freelane.NewFreeLane( - freeConfig, - blockbase.DefaultTxPriority(), - applanes.FreeLaneMatchHandler(), - ) + freeLane := applanes.NewFreeLane(freeConfig, applanes.FreeLaneMatchHandler()) priorityLaneConfig := blockbase.LaneConfig{ Logger: app.Logger(), diff --git a/app/lanes/free.go b/app/lanes/free.go index 39394095..fab9b9ba 100644 --- a/app/lanes/free.go +++ b/app/lanes/free.go @@ -5,23 +5,49 @@ import ( channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - "github.com/skip-mev/block-sdk/block/base" + "github.com/skip-mev/block-sdk/block" + blockbase "github.com/skip-mev/block-sdk/block/base" ) // FreeLaneMatchHandler returns the default match handler for the free lane. The // default implementation matches transactions that are ibc related. In particular, // any transaction that is a MsgTimeout, MsgAcknowledgement. -func FreeLaneMatchHandler() base.MatchHandler { +func FreeLaneMatchHandler() blockbase.MatchHandler { return func(ctx sdk.Context, tx sdk.Tx) bool { for _, msg := range tx.GetMsgs() { switch msg.(type) { case *channeltypes.MsgTimeout: - return true + continue case *channeltypes.MsgAcknowledgement: - return true + continue + default: + return false } } - return false + return true } } + +const ( + // FreeLaneName defines the name of the free lane. + FreeLaneName = "free" +) + +// NewFreeLane returns a new free lane. +func NewFreeLane( + cfg blockbase.LaneConfig, + matchFn blockbase.MatchHandler, +) block.Lane { + lane, err := blockbase.NewBaseLane( + cfg, + FreeLaneName, + blockbase.WithMatchHandler(matchFn), + blockbase.WithMempool(NewMempool(blockbase.NewDefaultTxPriority(), cfg.SignerExtractor, cfg.MaxTxs)), + ) + if err != nil { + panic(err) + } + + return lane +} diff --git a/app/lanes/mempool.go b/app/lanes/mempool.go new file mode 100644 index 00000000..c9a9ac2a --- /dev/null +++ b/app/lanes/mempool.go @@ -0,0 +1,132 @@ +package lanes + +import ( + "context" + "errors" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" + signer_extraction "github.com/skip-mev/block-sdk/adapters/signer_extraction_adapter" + blockbase "github.com/skip-mev/block-sdk/block/base" +) + +type ( + txKey struct { + nonce uint64 + sender string + } + + // Mempool defines a mempool that orders transactions based on the + // txPriority. The mempool is a wrapper on top of the SDK's Priority Nonce mempool. + // It include's additional helper functions that allow users to determine if a + // transaction is already in the mempool and to compare the priority of two + // transactions. + Mempool[C comparable] struct { + // index defines an index of transactions. + index sdkmempool.Mempool + + // signerExtractor defines the signer extraction adapter that allows us to + // extract the signer from a transaction. + extractor signer_extraction.Adapter + + // txCache is a map of all transactions in the mempool. It is used + // to quickly check if a transaction is already in the mempool. + txCache map[txKey]struct{} + } +) + +// NewMempool returns a new Mempool. +func NewMempool[C comparable](txPriority blockbase.TxPriority[C], extractor signer_extraction.Adapter, maxTx int) *Mempool[C] { + return &Mempool[C]{ + index: blockbase.NewPriorityMempool( + blockbase.PriorityNonceMempoolConfig[C]{ + TxPriority: txPriority, + MaxTx: maxTx, + }, + extractor, + ), + extractor: extractor, + txCache: make(map[txKey]struct{}), + } +} + +// Priority returns the priority of the transaction. +func (cm *Mempool[C]) Priority(ctx sdk.Context, tx sdk.Tx) any { + return 1 +} + +// CountTx returns the number of transactions in the mempool. +func (cm *Mempool[C]) CountTx() int { + return cm.index.CountTx() +} + +// Select returns an iterator of all transactions in the mempool. NOTE: If you +// remove a transaction from the mempool while iterating over the transactions, +// the iterator will not be aware of the removal and will continue to iterate +// over the removed transaction. Be sure to reset the iterator if you remove a transaction. +func (cm *Mempool[C]) Select(ctx context.Context, txs [][]byte) sdkmempool.Iterator { + return cm.index.Select(ctx, txs) +} + +// Compare return 0 to ignore priority check in ProcessLaneHandler. +func (cm *Mempool[C]) Compare(ctx sdk.Context, this sdk.Tx, other sdk.Tx) (int, error) { + return 0, nil +} + +// Contains returns true if the transaction is contained in the mempool. +func (cm *Mempool[C]) Contains(tx sdk.Tx) bool { + if key, err := cm.getTxKey(tx); err != nil { + return false + } else { + if _, ok := cm.txCache[key]; ok { + return true + } else { + return false + } + } +} + +// Insert inserts a transaction into the mempool. +func (cm *Mempool[C]) Insert(ctx context.Context, tx sdk.Tx) error { + if err := cm.index.Insert(ctx, tx); err != nil { + return fmt.Errorf("failed to insert tx into auction index: %w", err) + } + + if key, err := cm.getTxKey(tx); err != nil { + return err + } else { + cm.txCache[key] = struct{}{} + } + + return nil +} + +// Remove removes a transaction from the mempool. +func (cm *Mempool[C]) Remove(tx sdk.Tx) error { + if err := cm.index.Remove(tx); err != nil && !errors.Is(err, sdkmempool.ErrTxNotFound) { + return fmt.Errorf("failed to remove transaction from the mempool: %w", err) + } + + if key, err := cm.getTxKey(tx); err != nil { + return err + } else { + delete(cm.txCache, key) + } + + return nil +} + +func (cm *Mempool[C]) getTxKey(tx sdk.Tx) (txKey, error) { + signers, err := cm.extractor.GetSigners(tx) + if err != nil { + return txKey{}, err + } + if len(signers) == 0 { + return txKey{}, fmt.Errorf("attempted to remove a tx with no signatures") + } + sig := signers[0] + sender := sig.Signer.String() + nonce := sig.Sequence + return txKey{nonce, sender}, nil +} diff --git a/app/lanes/priority.go b/app/lanes/priority.go index fd4f849d..789ffd9e 100644 --- a/app/lanes/priority.go +++ b/app/lanes/priority.go @@ -1,171 +1,30 @@ package lanes import ( - "context" - "errors" - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - sdkmempool "github.com/cosmos/cosmos-sdk/types/mempool" - - signer_extraction "github.com/skip-mev/block-sdk/adapters/signer_extraction_adapter" "github.com/skip-mev/block-sdk/block" blockbase "github.com/skip-mev/block-sdk/block/base" ) const ( - // LaneName defines the name of the default lane. - LaneName = "priority" + // PriorityLaneName defines the name of the priority lane. + PriorityLaneName = "priority" ) -var _ block.Lane = (*PriorityLane)(nil) - -// DefaultLane defines a default lane implementation. The default lane orders -// transactions by the transaction fees. The default lane accepts any transaction +// PriorityLane defines a priority lane implementation. The priority lane orders +// transactions by the transaction fees. The priority lane accepts any transaction // that should not be ignored (as defined by the IgnoreList in the LaneConfig). -// The default lane builds and verifies blocks in a similar fashion to how the +// The priority lane builds and verifies blocks in a similar fashion to how the // CometBFT/Tendermint consensus engine builds and verifies blocks pre SDK version // 0.47.0. -type PriorityLane struct { - *blockbase.BaseLane -} - -// NewPriorityLane returns a new default lane. -func NewPriorityLane(cfg blockbase.LaneConfig) *PriorityLane { +func NewPriorityLane(cfg blockbase.LaneConfig) block.Lane { lane, err := blockbase.NewBaseLane( cfg, - LaneName, + PriorityLaneName, + blockbase.WithMempool(NewMempool(blockbase.NewDefaultTxPriority(), cfg.SignerExtractor, cfg.MaxTxs)), ) if err != nil { panic(err) } - lane.LaneMempool = NewMempool(blockbase.NewDefaultTxPriority(), cfg.SignerExtractor, cfg.MaxTxs) - - if err := lane.ValidateBasic(); err != nil { - panic(err) - } - - return &PriorityLane{ - BaseLane: lane, - } -} - -type ( - txKey struct { - nonce uint64 - sender string - } - - // Mempool defines a mempool that orders transactions based on the - // txPriority. The mempool is a wrapper on top of the SDK's Priority Nonce mempool. - // It include's additional helper functions that allow users to determine if a - // transaction is already in the mempool and to compare the priority of two - // transactions. - Mempool[C comparable] struct { - // index defines an index of transactions. - index sdkmempool.Mempool - - // signerExtractor defines the signer extraction adapter that allows us to - // extract the signer from a transaction. - extractor signer_extraction.Adapter - - // txCache is a map of all transactions in the mempool. It is used - // to quickly check if a transaction is already in the mempool. - txCache map[txKey]struct{} - } -) - -// NewMempool returns a new Mempool. -func NewMempool[C comparable](txPriority blockbase.TxPriority[C], extractor signer_extraction.Adapter, maxTx int) *Mempool[C] { - return &Mempool[C]{ - index: blockbase.NewPriorityMempool( - blockbase.PriorityNonceMempoolConfig[C]{ - TxPriority: txPriority, - MaxTx: maxTx, - }, - extractor, - ), - extractor: extractor, - txCache: make(map[txKey]struct{}), - } -} -// Priority returns the priority of the transaction. -func (cm *Mempool[C]) Priority(ctx sdk.Context, tx sdk.Tx) any { - return 1 -} - -// CountTx returns the number of transactions in the mempool. -func (cm *Mempool[C]) CountTx() int { - return cm.index.CountTx() -} - -// Select returns an iterator of all transactions in the mempool. NOTE: If you -// remove a transaction from the mempool while iterating over the transactions, -// the iterator will not be aware of the removal and will continue to iterate -// over the removed transaction. Be sure to reset the iterator if you remove a transaction. -func (cm *Mempool[C]) Select(ctx context.Context, txs [][]byte) sdkmempool.Iterator { - return cm.index.Select(ctx, txs) -} - -// Compare return 0 to ignore priority check in ProcessLaneHandler. -func (cm *Mempool[C]) Compare(ctx sdk.Context, this sdk.Tx, other sdk.Tx) (int, error) { - return 0, nil -} - -// Contains returns true if the transaction is contained in the mempool. -func (cm *Mempool[C]) Contains(tx sdk.Tx) bool { - if key, err := cm.getTxKey(tx); err != nil { - return false - } else { - if _, ok := cm.txCache[key]; ok { - return true - } else { - return false - } - } -} - -// Insert inserts a transaction into the mempool. -func (cm *Mempool[C]) Insert(ctx context.Context, tx sdk.Tx) error { - if err := cm.index.Insert(ctx, tx); err != nil { - return fmt.Errorf("failed to insert tx into auction index: %w", err) - } - - if key, err := cm.getTxKey(tx); err != nil { - return err - } else { - cm.txCache[key] = struct{}{} - } - - return nil -} - -// Remove removes a transaction from the mempool. -func (cm *Mempool[C]) Remove(tx sdk.Tx) error { - if err := cm.index.Remove(tx); err != nil && !errors.Is(err, sdkmempool.ErrTxNotFound) { - return fmt.Errorf("failed to remove transaction from the mempool: %w", err) - } - - if key, err := cm.getTxKey(tx); err != nil { - return err - } else { - delete(cm.txCache, key) - } - - return nil -} - -func (cm *Mempool[C]) getTxKey(tx sdk.Tx) (txKey, error) { - signers, err := cm.extractor.GetSigners(tx) - if err != nil { - return txKey{}, err - } - if len(signers) == 0 { - return txKey{}, fmt.Errorf("attempted to remove a tx with no signatures") - } - sig := signers[0] - sender := sig.Signer.String() - nonce := sig.Sequence - return txKey{nonce, sender}, nil + return lane }