@@ -201,7 +201,7 @@ type (
201201 // to verify a transaction.
202202 ProposalTxVerifier interface {
203203 PrepareProposalVerifyTx (tx sdk.Tx ) ([]byte , error )
204- ProcessProposalVerifyTx (txBz []byte ) (sdk.Tx , error )
204+ ProcessProposalVerifyTx (txBz []byte ) (sdk.Tx , uint64 , error )
205205 TxDecode (txBz []byte ) (sdk.Tx , error )
206206 TxEncode (tx sdk.Tx ) ([]byte , error )
207207 }
@@ -213,6 +213,9 @@ type (
213213 txVerifier ProposalTxVerifier
214214 txSelector TxSelector
215215 signerExtAdapter mempool.SignerExtractionAdapter
216+
217+ // fastPrepareProposal together with NoOpMempool will bypass tx selector
218+ fastPrepareProposal bool
216219 }
217220)
218221
@@ -225,6 +228,12 @@ func NewDefaultProposalHandler(mp mempool.Mempool, txVerifier ProposalTxVerifier
225228 }
226229}
227230
231+ func NewDefaultProposalHandlerFast (mp mempool.Mempool , txVerifier ProposalTxVerifier ) * DefaultProposalHandler {
232+ h := NewDefaultProposalHandler (mp , txVerifier )
233+ h .fastPrepareProposal = true
234+ return h
235+ }
236+
228237// SetTxSelector sets the TxSelector function on the DefaultProposalHandler.
229238func (h * DefaultProposalHandler ) SetTxSelector (ts TxSelector ) {
230239 h .txSelector = ts
@@ -265,13 +274,23 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
265274 // Note, we still need to ensure the transactions returned respect req.MaxTxBytes.
266275 _ , isNoOp := h .mempool .(mempool.NoOpMempool )
267276 if h .mempool == nil || isNoOp {
277+ if h .fastPrepareProposal {
278+ txs := h .txSelector .SelectTxForProposalFast (ctx , req .Txs )
279+ return & abci.ResponsePrepareProposal {Txs : txs }, nil
280+ }
281+
268282 for _ , txBz := range req .Txs {
269283 tx , err := h .txVerifier .TxDecode (txBz )
270284 if err != nil {
271285 return nil , err
272286 }
273287
274- stop := h .txSelector .SelectTxForProposal (ctx , uint64 (req .MaxTxBytes ), maxBlockGas , tx , txBz )
288+ var txGasLimit uint64
289+ if gasTx , ok := tx .(mempool.GasTx ); ok {
290+ txGasLimit = gasTx .GetGas ()
291+ }
292+
293+ stop := h .txSelector .SelectTxForProposal (ctx , uint64 (req .MaxTxBytes ), maxBlockGas , tx , txBz , txGasLimit )
275294 if stop {
276295 break
277296 }
@@ -286,14 +305,14 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
286305 selectedTxsNums int
287306 invalidTxs []sdk.Tx // invalid txs to be removed out of the loop to avoid dead lock
288307 )
289- mempool .SelectBy (ctx , h .mempool , req .Txs , func (memTx sdk .Tx ) bool {
290- unorderedTx , ok := memTx .(sdk.TxWithUnordered )
308+ mempool .SelectBy (ctx , h .mempool , req .Txs , func (memTx mempool .Tx ) bool {
309+ unorderedTx , ok := memTx .Tx . (sdk.TxWithUnordered )
291310 isUnordered := ok && unorderedTx .GetUnordered ()
292311 txSignersSeqs := make (map [string ]uint64 )
293312
294313 // if the tx is unordered, we don't need to check the sequence, we just add it
295314 if ! isUnordered {
296- signerData , err := h .signerExtAdapter .GetSigners (memTx )
315+ signerData , err := h .signerExtAdapter .GetSigners (memTx . Tx )
297316 if err != nil {
298317 // propagate the error to the caller
299318 resError = err
@@ -328,11 +347,11 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
328347 // which calls mempool.Insert, in theory everything in the pool should be
329348 // valid. But some mempool implementations may insert invalid txs, so we
330349 // check again.
331- txBz , err := h .txVerifier .PrepareProposalVerifyTx (memTx )
350+ txBz , err := h .txVerifier .PrepareProposalVerifyTx (memTx . Tx )
332351 if err != nil {
333- invalidTxs = append (invalidTxs , memTx )
352+ invalidTxs = append (invalidTxs , memTx . Tx )
334353 } else {
335- stop := h .txSelector .SelectTxForProposal (ctx , uint64 (req .MaxTxBytes ), maxBlockGas , memTx , txBz )
354+ stop := h .txSelector .SelectTxForProposal (ctx , uint64 (req .MaxTxBytes ), maxBlockGas , memTx . Tx , txBz , memTx . GasWanted )
336355 if stop {
337356 return false
338357 }
@@ -404,17 +423,13 @@ func (h *DefaultProposalHandler) ProcessProposalHandler() sdk.ProcessProposalHan
404423 }
405424
406425 for _ , txBytes := range req .Txs {
407- tx , err := h .txVerifier .ProcessProposalVerifyTx (txBytes )
426+ _ , gasWanted , err := h .txVerifier .ProcessProposalVerifyTx (txBytes )
408427 if err != nil {
409428 return & abci.ResponseProcessProposal {Status : abci .ResponseProcessProposal_REJECT }, nil
410429 }
411430
412431 if maxBlockGas > 0 {
413- gasTx , ok := tx .(GasTx )
414- if ok {
415- totalTxGas += gasTx .GetGas ()
416- }
417-
432+ totalTxGas += gasWanted
418433 if totalTxGas > uint64 (maxBlockGas ) {
419434 return & abci.ResponseProcessProposal {Status : abci .ResponseProcessProposal_REJECT }, nil
420435 }
@@ -472,7 +487,13 @@ type TxSelector interface {
472487 // a proposal based on inclusion criteria defined by the TxSelector. It must
473488 // return <true> if the caller should halt the transaction selection loop
474489 // (typically over a mempool) or <false> otherwise.
475- SelectTxForProposal (ctx context.Context , maxTxBytes , maxBlockGas uint64 , memTx sdk.Tx , txBz []byte ) bool
490+ SelectTxForProposal (ctx context.Context , maxTxBytes , maxBlockGas uint64 , memTx sdk.Tx , txBz []byte , gasWanted uint64 ) bool
491+
492+ // SelectTxForProposalFast is called in the case of NoOpMempool,
493+ // where cometbft already checked the block gas/size limit,
494+ // so the tx selector should simply accept them all to the proposal.
495+ // But extra validations on the tx are still possible though.
496+ SelectTxForProposalFast (ctx context.Context , txs [][]byte ) [][]byte
476497}
477498
478499type defaultTxSelector struct {
@@ -494,26 +515,19 @@ func (ts *defaultTxSelector) SelectedTxs(_ context.Context) [][]byte {
494515func (ts * defaultTxSelector ) Clear () {
495516 ts .totalTxBytes = 0
496517 ts .totalTxGas = 0
497- ts .selectedTxs = nil
518+ ts .selectedTxs = ts . selectedTxs [: 0 ] // keep the allocated memory
498519}
499520
500- func (ts * defaultTxSelector ) SelectTxForProposal (_ context.Context , maxTxBytes , maxBlockGas uint64 , memTx sdk.Tx , txBz []byte ) bool {
521+ func (ts * defaultTxSelector ) SelectTxForProposal (_ context.Context , maxTxBytes , maxBlockGas uint64 , memTx sdk.Tx , txBz []byte , gasWanted uint64 ) bool {
501522 txSize := uint64 (cmttypes .ComputeProtoSizeForTxs ([]cmttypes.Tx {txBz }))
502523
503- var txGasLimit uint64
504- if memTx != nil {
505- if gasTx , ok := memTx .(GasTx ); ok {
506- txGasLimit = gasTx .GetGas ()
507- }
508- }
509-
510524 // only add the transaction to the proposal if we have enough capacity
511525 if (txSize + ts .totalTxBytes ) <= maxTxBytes {
512526 // If there is a max block gas limit, add the tx only if the limit has
513527 // not been met.
514528 if maxBlockGas > 0 {
515- if (txGasLimit + ts .totalTxGas ) <= maxBlockGas {
516- ts .totalTxGas += txGasLimit
529+ if (gasWanted + ts .totalTxGas ) <= maxBlockGas {
530+ ts .totalTxGas += gasWanted
517531 ts .totalTxBytes += txSize
518532 ts .selectedTxs = append (ts .selectedTxs , txBz )
519533 }
@@ -526,3 +540,7 @@ func (ts *defaultTxSelector) SelectTxForProposal(_ context.Context, maxTxBytes,
526540 // check if we've reached capacity; if so, we cannot select any more transactions
527541 return ts .totalTxBytes >= maxTxBytes || (maxBlockGas > 0 && (ts .totalTxGas >= maxBlockGas ))
528542}
543+
544+ func (ts * defaultTxSelector ) SelectTxForProposalFast (ctx context.Context , txs [][]byte ) [][]byte {
545+ return txs
546+ }
0 commit comments