From 1b33121674c6a94acc3c3fc7629ed5a3698dc073 Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Thu, 4 Jan 2024 10:58:37 -0500 Subject: [PATCH] [EVM] Add pending nonce support (#390) - Adding an expiration handler callback that lets the mempool - https://github.com/sei-protocol/sei-tendermint/pull/179 - e2e testing with hardhat tests --- baseapp/abci.go | 5 +++-- baseapp/baseapp.go | 12 +++++++----- baseapp/test_helpers.go | 6 +++--- types/context.go | 10 ++++++++++ 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index bb7d94fcb..8a7c789e9 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -225,7 +225,7 @@ func (app *BaseApp) CheckTx(ctx context.Context, req *abci.RequestCheckTx) (*abc res := sdkerrors.ResponseCheckTx(err, 0, 0, app.trace) return &abci.ResponseCheckTxV2{ResponseCheckTx: &res}, err } - gInfo, result, _, priority, pendingTxChecker, err := app.runTx(sdkCtx, mode, tx, sha256.Sum256(req.Tx)) + gInfo, result, _, priority, pendingTxChecker, expireTxHandler, err := app.runTx(sdkCtx, mode, tx, sha256.Sum256(req.Tx)) if err != nil { res := sdkerrors.ResponseCheckTx(err, gInfo.GasWanted, gInfo.GasUsed, app.trace) return &abci.ResponseCheckTxV2{ResponseCheckTx: &res}, err @@ -240,6 +240,7 @@ func (app *BaseApp) CheckTx(ctx context.Context, req *abci.RequestCheckTx) (*abc res.IsPendingTransaction = true res.Checker = pendingTxChecker } + res.ExpireTxHandler = expireTxHandler return res, nil } @@ -287,7 +288,7 @@ func (app *BaseApp) DeliverTx(ctx sdk.Context, req abci.RequestDeliverTx, tx sdk telemetry.SetGauge(float32(gInfo.GasWanted), "tx", "gas", "wanted") }() - gInfo, result, anteEvents, _, _, err := app.runTx(ctx.WithTxBytes(req.Tx).WithVoteInfos(app.voteInfos), runTxModeDeliver, tx, checksum) + gInfo, result, anteEvents, _, _, _, err := app.runTx(ctx.WithTxBytes(req.Tx).WithVoteInfos(app.voteInfos), runTxModeDeliver, tx, checksum) if err != nil { resultStr = "failed" // if we have a result, use those events instead of just the anteEvents diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 259b02f2b..ca79049db 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -835,6 +835,7 @@ func (app *BaseApp) runTx(ctx sdk.Context, mode runTxMode, tx sdk.Tx, checksum [ anteEvents []abci.Event, priority int64, pendingTxChecker abci.PendingTxChecker, + expireHandler abci.ExpireTxHandler, err error, ) { defer telemetry.MeasureThroughputSinceWithLabels( @@ -884,13 +885,13 @@ func (app *BaseApp) runTx(ctx sdk.Context, mode runTxMode, tx sdk.Tx, checksum [ }() if tx == nil { - return sdk.GasInfo{}, nil, nil, 0, nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx decode error") + return sdk.GasInfo{}, nil, nil, 0, nil, nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx decode error") } msgs := tx.GetMsgs() if err := validateBasicTxMsgs(msgs); err != nil { - return sdk.GasInfo{}, nil, nil, 0, nil, err + return sdk.GasInfo{}, nil, nil, 0, nil, nil, err } if app.anteHandler != nil { @@ -935,7 +936,7 @@ func (app *BaseApp) runTx(ctx sdk.Context, mode runTxMode, tx sdk.Tx, checksum [ // GasMeter expected to be set in AnteHandler gasWanted = ctx.GasMeter().Limit() if err != nil { - return gInfo, nil, nil, 0, nil, err + return gInfo, nil, nil, 0, nil, nil, err } // Dont need to validate in checkTx mode @@ -951,12 +952,13 @@ func (app *BaseApp) runTx(ctx sdk.Context, mode runTxMode, tx sdk.Tx, checksum [ op.EmitValidationFailMetrics() } errMessage := fmt.Sprintf("Invalid Concurrent Execution antehandler missing %d access operations", len(missingAccessOps)) - return gInfo, nil, nil, 0, nil, sdkerrors.Wrap(sdkerrors.ErrInvalidConcurrencyExecution, errMessage) + return gInfo, nil, nil, 0, nil, nil, sdkerrors.Wrap(sdkerrors.ErrInvalidConcurrencyExecution, errMessage) } } priority = ctx.Priority() pendingTxChecker = ctx.PendingTxChecker() + expireHandler = ctx.ExpireTxHandler() msCache.Write() anteEvents = events.ToABCIEvents() if app.TracingEnabled { @@ -985,7 +987,7 @@ func (app *BaseApp) runTx(ctx sdk.Context, mode runTxMode, tx sdk.Tx, checksum [ if ctx.CheckTxCallback() != nil { ctx.CheckTxCallback()(err) } - return gInfo, result, anteEvents, priority, pendingTxChecker, err + return gInfo, result, anteEvents, priority, pendingTxChecker, expireHandler, err } // runMsgs iterates through a list of messages and executes them with the provided diff --git a/baseapp/test_helpers.go b/baseapp/test_helpers.go index 7652b078e..1cc05327a 100644 --- a/baseapp/test_helpers.go +++ b/baseapp/test_helpers.go @@ -17,7 +17,7 @@ func (app *BaseApp) Check(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *sdk return sdk.GasInfo{}, nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "%s", err) } ctx := app.checkState.ctx.WithTxBytes(bz).WithVoteInfos(app.voteInfos).WithConsensusParams(app.GetConsensusParams(app.checkState.ctx)) - gasInfo, result, _, _, _, err := app.runTx(ctx, runTxModeCheck, tx, sha256.Sum256(bz)) + gasInfo, result, _, _, _, _, err := app.runTx(ctx, runTxModeCheck, tx, sha256.Sum256(bz)) if len(ctx.MultiStore().GetEvents()) > 0 { panic("Expected checkTx events to be empty") } @@ -31,7 +31,7 @@ func (app *BaseApp) Simulate(txBytes []byte) (sdk.GasInfo, *sdk.Result, error) { if err != nil { return sdk.GasInfo{}, nil, err } - gasInfo, result, _, _, _, err := app.runTx(ctx, runTxModeSimulate, tx, sha256.Sum256(txBytes)) + gasInfo, result, _, _, _, _, err := app.runTx(ctx, runTxModeSimulate, tx, sha256.Sum256(txBytes)) if len(ctx.MultiStore().GetEvents()) > 0 { panic("Expected simulate events to be empty") } @@ -49,7 +49,7 @@ func (app *BaseApp) Deliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, *s if err != nil { return sdk.GasInfo{}, &sdk.Result{}, err } - gasInfo, result, _, _, _, err := app.runTx(ctx, runTxModeDeliver, decoded, sha256.Sum256(bz)) + gasInfo, result, _, _, _, _, err := app.runTx(ctx, runTxModeDeliver, decoded, sha256.Sum256(bz)) return gasInfo, result, err } diff --git a/types/context.go b/types/context.go index 2ee371e13..25d1a33fb 100644 --- a/types/context.go +++ b/types/context.go @@ -42,6 +42,7 @@ type Context struct { priority int64 // The tx priority, only relevant in CheckTx pendingTxChecker abci.PendingTxChecker // Checker for pending transaction, only relevant in CheckTx checkTxCallback func(error) // callback to make at the end of CheckTx. Input param is the error (nil-able) of `runMsgs` + expireTxHandler func() // callback that the mempool invokes when a tx is expired txBlockingChannels acltypes.MessageAccessOpsChannelMapping txCompletionChannels acltypes.MessageAccessOpsChannelMapping @@ -118,6 +119,10 @@ func (c Context) Priority() int64 { return c.priority } +func (c Context) ExpireTxHandler() abci.ExpireTxHandler { + return c.expireTxHandler +} + func (c Context) PendingTxChecker() abci.PendingTxChecker { return c.pendingTxChecker } @@ -369,6 +374,11 @@ func (c Context) WithCheckTxCallback(checkTxCallback func(error)) Context { return c } +func (c Context) WithExpireTxHandler(expireTxHandler func()) Context { + c.expireTxHandler = expireTxHandler + return c +} + // TODO: remove??? func (c Context) IsZero() bool { return c.ms == nil