Skip to content

Commit c93bd6b

Browse files
authored
feat(mempool): implement RemoveWithReason (#25663)
1 parent 8448784 commit c93bd6b

File tree

6 files changed

+79
-18
lines changed

6 files changed

+79
-18
lines changed

baseapp/abci_utils.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -285,12 +285,19 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
285285
return &abci.ResponsePrepareProposal{Txs: h.txSelector.SelectedTxs(ctx)}, nil
286286
}
287287

288-
selectedTxsSignersSeqs := make(map[string]uint64)
288+
type invalidTx struct {
289+
tx sdk.Tx
290+
err error
291+
}
292+
289293
var (
290-
resError error
291-
selectedTxsNums int
292-
invalidTxs []sdk.Tx // invalid txs to be removed out of the loop to avoid dead lock
294+
// invalid txs to be removed out of the loop to avoid dead lock
295+
invalidTxs []invalidTx
296+
resError error
297+
selectedTxsNums int
298+
selectedTxsSignersSeqs = make(map[string]uint64)
293299
)
300+
294301
mempool.SelectBy(ctx, h.mempool, req.Txs, func(memTx sdk.Tx) bool {
295302
unorderedTx, ok := memTx.(sdk.TxWithUnordered)
296303
isUnordered := ok && unorderedTx.GetUnordered()
@@ -335,7 +342,7 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
335342
// check again.
336343
txBz, err := h.txVerifier.PrepareProposalVerifyTx(memTx)
337344
if err != nil {
338-
invalidTxs = append(invalidTxs, memTx)
345+
invalidTxs = append(invalidTxs, invalidTx{tx: memTx, err: err})
339346
} else {
340347
stop := h.txSelector.SelectTxForProposal(ctx, uint64(req.MaxTxBytes), maxBlockGas, memTx, txBz)
341348
if stop {
@@ -370,8 +377,13 @@ func (h *DefaultProposalHandler) PrepareProposalHandler() sdk.PrepareProposalHan
370377
return nil, resError
371378
}
372379

373-
for _, tx := range invalidTxs {
374-
err := h.mempool.Remove(tx)
380+
for _, invalidTx := range invalidTxs {
381+
reason := mempool.RemoveReason{
382+
Caller: mempool.CallerPrepareProposalRemoveInvalid,
383+
Error: invalidTx.err,
384+
}
385+
386+
err := mempool.RemoveWithReason(ctx, h.mempool, invalidTx.tx, reason)
375387
if err != nil && !errors.Is(err, mempool.ErrTxNotFound) {
376388
return nil, err
377389
}

baseapp/baseapp.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -881,10 +881,16 @@ func (app *BaseApp) RunTx(mode sdk.ExecMode, txBytes []byte, tx sdk.Tx, txIndex
881881
if err != nil {
882882
if mode == execModeReCheck {
883883
// if the ante handler fails on recheck, we want to remove the tx from the mempool
884-
if mempoolErr := app.mempool.Remove(tx); mempoolErr != nil {
885-
return gInfo, nil, anteEvents, errors.Join(err, mempoolErr)
884+
errMempool := mempool.RemoveWithReason(ctx, app.mempool, tx, mempool.RemoveReason{
885+
Caller: mempool.CallerRunTxRecheck,
886+
Error: err,
887+
})
888+
889+
if errMempool != nil {
890+
return gInfo, nil, anteEvents, errors.Join(err, errMempool)
886891
}
887892
}
893+
888894
return gInfo, nil, nil, err
889895
}
890896

@@ -899,10 +905,10 @@ func (app *BaseApp) RunTx(mode sdk.ExecMode, txBytes []byte, tx sdk.Tx, txIndex
899905
return gInfo, nil, anteEvents, err
900906
}
901907
case execModeFinalize:
902-
err = app.mempool.Remove(tx)
908+
reason := mempool.RemoveReason{Caller: mempool.CallerRunTxFinalize}
909+
err = mempool.RemoveWithReason(ctx, app.mempool, tx, reason)
903910
if err != nil && !errors.Is(err, mempool.ErrTxNotFound) {
904-
return gInfo, nil, anteEvents,
905-
fmt.Errorf("failed to remove tx from mempool: %w", err)
911+
return gInfo, nil, anteEvents, fmt.Errorf("failed to remove tx from mempool: %w", err)
906912
}
907913
}
908914

types/mempool/mempool.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,34 @@ type Mempool interface {
2626

2727
// ExtMempool is an extension of Mempool interface introduced in v0.50
2828
// for not be breaking in a patch release.
29-
// In v0.52+, this interface will be merged into Mempool interface.
29+
// In v0.54+, this function is removed and RemoveWithReason is merged into Mempool interface.
3030
type ExtMempool interface {
3131
Mempool
3232

3333
// SelectBy use callback to iterate over the mempool, it's thread-safe to use.
3434
SelectBy(context.Context, [][]byte, func(sdk.Tx) bool)
35+
36+
// RemoveWithReason removes a transaction from the mempool with specific reason
37+
// allowing the mempool to handle the removal differently.
38+
RemoveWithReason(context.Context, sdk.Tx, RemoveReason) error
39+
}
40+
41+
// RemovalCaller is the origin of the removal
42+
type RemovalCaller string
43+
44+
// Various callers
45+
const (
46+
CallerRunTxRecheck RemovalCaller = "run_tx.recheck"
47+
CallerRunTxFinalize RemovalCaller = "run_tx.finalize"
48+
CallerPrepareProposalRemoveInvalid RemovalCaller = "prepare_proposal.remove_invalid"
49+
)
50+
51+
// RemoveReason is the reason for removing a transaction from the mempool.
52+
type RemoveReason struct {
53+
Caller RemovalCaller
54+
55+
// Error is an optional error that caused the removal.
56+
Error error
3557
}
3658

3759
// Iterator defines an app-side mempool iterator interface that is as minimal as
@@ -65,3 +87,13 @@ func SelectBy(ctx context.Context, mempool Mempool, txs [][]byte, callback func(
6587
iter = iter.Next()
6688
}
6789
}
90+
91+
// RemoveWithReason is compatible with old interface to avoid breaking api.
92+
// In v0.54+, this function is removed and RemoveWithReason is merged into Mempool interface.
93+
func RemoveWithReason(ctx context.Context, mempool Mempool, tx sdk.Tx, reason RemoveReason) error {
94+
if ext, ok := mempool.(ExtMempool); ok {
95+
return ext.RemoveWithReason(ctx, tx, reason)
96+
}
97+
98+
return mempool.Remove(tx)
99+
}

types/mempool/noop.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ var _ ExtMempool = (*NoOpMempool)(nil)
1616
// is FIFO-ordered by default.
1717
type NoOpMempool struct{}
1818

19-
func (NoOpMempool) Insert(context.Context, sdk.Tx) error { return nil }
20-
func (NoOpMempool) Select(context.Context, [][]byte) Iterator { return nil }
21-
func (NoOpMempool) SelectBy(context.Context, [][]byte, func(sdk.Tx) bool) {}
22-
func (NoOpMempool) CountTx() int { return 0 }
23-
func (NoOpMempool) Remove(sdk.Tx) error { return nil }
19+
func (NoOpMempool) Insert(context.Context, sdk.Tx) error { return nil }
20+
func (NoOpMempool) Select(context.Context, [][]byte) Iterator { return nil }
21+
func (NoOpMempool) SelectBy(context.Context, [][]byte, func(sdk.Tx) bool) {}
22+
func (NoOpMempool) CountTx() int { return 0 }
23+
func (NoOpMempool) Remove(sdk.Tx) error { return nil }
24+
func (NoOpMempool) RemoveWithReason(context.Context, sdk.Tx, RemoveReason) error { return nil }

types/mempool/priority_nonce.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,11 @@ func (mp *PriorityNonceMempool[C]) Remove(tx sdk.Tx) error {
485485
return nil
486486
}
487487

488+
// RemoveWithReason is a proxy to Remove for this mempool.
489+
func (mp *PriorityNonceMempool[C]) RemoveWithReason(_ context.Context, tx sdk.Tx, _ RemoveReason) error {
490+
return mp.Remove(tx)
491+
}
492+
488493
func IsEmpty[C comparable](mempool Mempool) error {
489494
mp := mempool.(*PriorityNonceMempool[C])
490495
if mp.priorityIndex.Len() != 0 {

types/mempool/sender_nonce.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,11 @@ func (snm *SenderNonceMempool) Remove(tx sdk.Tx) error {
254254
return nil
255255
}
256256

257+
// RemoveWithReason is a proxy to Remove for this mempool.
258+
func (snm *SenderNonceMempool) RemoveWithReason(_ context.Context, tx sdk.Tx, _ RemoveReason) error {
259+
return snm.Remove(tx)
260+
}
261+
257262
type senderNonceMempoolIterator struct {
258263
rnd *rand.Rand
259264
currentTx *skiplist.Element

0 commit comments

Comments
 (0)