diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ba20e167f9e..45edecfdfe6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * [#261](https://github.com/crypto-org-chain/cosmos-sdk/pull/261) `ctx.BlockHeader` don't do protobuf deep copy, shallow copy seems enough, reduce scope of mutex in `PriorityNonceMempool.Remove`. * [#507](https://github.com/crypto-org-chain/cosmos-sdk/pull/507) mempool respect gas wanted returned by ante handler * [#744](https://github.com/crypto-org-chain/cosmos-sdk/pull/744) Pass raw transactions to tx executor so it can do pre-estimations. +* [#884](https://github.com/crypto-org-chain/cosmos-sdk/pull/884) Avoid decoding tx for in PrepareProposal if it's NopMempool. ## [Unreleased] diff --git a/baseapp/abci_utils.go b/baseapp/abci_utils.go index 1bbd500bd705..dc532c191b0c 100644 --- a/baseapp/abci_utils.go +++ b/baseapp/abci_utils.go @@ -212,6 +212,9 @@ type ( txVerifier ProposalTxVerifier txSelector TxSelector signerExtAdapter mempool.SignerExtractionAdapter + + // fastPrepareProposal together with NoOpMempool will bypass tx selector + fastPrepareProposal bool } ) @@ -224,6 +227,12 @@ func NewDefaultProposalHandler(mp mempool.Mempool, txVerifier ProposalTxVerifier } } +func NewDefaultProposalHandlerFast(mp mempool.Mempool, txVerifier ProposalTxVerifier) *DefaultProposalHandler { + h := NewDefaultProposalHandler(mp, txVerifier) + h.fastPrepareProposal = true + return h +} + // SetTxSelector sets the TxSelector function on the DefaultProposalHandler. func (h *DefaultProposalHandler) SetTxSelector(ts TxSelector) { h.txSelector = ts @@ -264,6 +273,11 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan // Note, we still need to ensure the transactions returned respect req.MaxTxBytes. _, isNoOp := h.mempool.(mempool.NoOpMempool) if h.mempool == nil || isNoOp { + if h.fastPrepareProposal { + txs := h.txSelector.SelectTxForProposalFast(ctx, req.Txs) + return &abci.ResponsePrepareProposal{Txs: txs}, nil + } + for _, txBz := range req.Txs { tx, err := h.txVerifier.TxDecode(txBz) if err != nil { @@ -464,6 +478,12 @@ type TxSelector interface { // return if the caller should halt the transaction selection loop // (typically over a mempool) or otherwise. SelectTxForProposal(ctx context.Context, maxTxBytes, maxBlockGas uint64, memTx sdk.Tx, txBz []byte, gasWanted uint64) bool + + // SelectTxForProposalFast is called in the case of NoOpMempool, + // where cometbft already checked the block gas/size limit, + // so the tx selector should simply accept them all to the proposal. + // But extra validations on the tx are still possible though. + SelectTxForProposalFast(ctx context.Context, txs [][]byte) [][]byte } type defaultTxSelector struct { @@ -485,7 +505,7 @@ func (ts *defaultTxSelector) SelectedTxs(_ context.Context) [][]byte { func (ts *defaultTxSelector) Clear() { ts.totalTxBytes = 0 ts.totalTxGas = 0 - ts.selectedTxs = nil + ts.selectedTxs = ts.selectedTxs[:0] // keep the allocated memory } func (ts *defaultTxSelector) SelectTxForProposal(_ context.Context, maxTxBytes, maxBlockGas uint64, memTx sdk.Tx, txBz []byte, gasWanted uint64) bool { @@ -510,3 +530,7 @@ func (ts *defaultTxSelector) SelectTxForProposal(_ context.Context, maxTxBytes, // check if we've reached capacity; if so, we cannot select any more transactions return ts.totalTxBytes >= maxTxBytes || (maxBlockGas > 0 && (ts.totalTxGas >= maxBlockGas)) } + +func (ts *defaultTxSelector) SelectTxForProposalFast(ctx context.Context, txs [][]byte) [][]byte { + return txs +}