From e8a949dbcecef2a26656fe0e88b94c14148ef0bf Mon Sep 17 00:00:00 2001 From: Steven Landers Date: Fri, 19 Jan 2024 11:05:40 -0500 Subject: [PATCH] [EVM] Allow multiple txs from same account in a block (#397) - needs tendermint pr and go.mod update - adds evm properties to the `ResponseCheckTxV2` - adds evm properties to context - hardhat tests on sei-chain repo - unit tests on tendermint repo --- baseapp/abci.go | 21 +++++++++++++-------- baseapp/baseapp.go | 11 ++++++----- baseapp/test_helpers.go | 6 +++--- types/context.go | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 16 deletions(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index 8a7c789e9..61a7f4ad4 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -225,22 +225,27 @@ 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, expireTxHandler, err := app.runTx(sdkCtx, mode, tx, sha256.Sum256(req.Tx)) + gInfo, result, _, priority, pendingTxChecker, expireTxHandler, txCtx, 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 } - res := &abci.ResponseCheckTxV2{ResponseCheckTx: &abci.ResponseCheckTx{ - GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints? - Data: result.Data, - Priority: priority, - }} + res := &abci.ResponseCheckTxV2{ + ResponseCheckTx: &abci.ResponseCheckTx{ + GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints? + Data: result.Data, + Priority: priority, + }, + ExpireTxHandler: expireTxHandler, + EVMNonce: txCtx.EVMNonce(), + EVMSenderAddress: txCtx.EVMSenderAddress(), + IsEVM: txCtx.IsEVM(), + } if pendingTxChecker != nil { res.IsPendingTransaction = true res.Checker = pendingTxChecker } - res.ExpireTxHandler = expireTxHandler return res, nil } @@ -288,7 +293,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 ca79049db..20b978fbb 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -836,6 +836,7 @@ func (app *BaseApp) runTx(ctx sdk.Context, mode runTxMode, tx sdk.Tx, checksum [ priority int64, pendingTxChecker abci.PendingTxChecker, expireHandler abci.ExpireTxHandler, + txCtx sdk.Context, err error, ) { defer telemetry.MeasureThroughputSinceWithLabels( @@ -885,13 +886,13 @@ func (app *BaseApp) runTx(ctx sdk.Context, mode runTxMode, tx sdk.Tx, checksum [ }() if tx == nil { - return sdk.GasInfo{}, nil, nil, 0, nil, nil, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx decode error") + return sdk.GasInfo{}, nil, nil, 0, nil, nil, ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "tx decode error") } msgs := tx.GetMsgs() if err := validateBasicTxMsgs(msgs); err != nil { - return sdk.GasInfo{}, nil, nil, 0, nil, nil, err + return sdk.GasInfo{}, nil, nil, 0, nil, nil, ctx, err } if app.anteHandler != nil { @@ -936,7 +937,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, nil, err + return gInfo, nil, nil, 0, nil, nil, ctx, err } // Dont need to validate in checkTx mode @@ -952,7 +953,7 @@ 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, nil, sdkerrors.Wrap(sdkerrors.ErrInvalidConcurrencyExecution, errMessage) + return gInfo, nil, nil, 0, nil, nil, ctx, sdkerrors.Wrap(sdkerrors.ErrInvalidConcurrencyExecution, errMessage) } } @@ -987,7 +988,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, expireHandler, err + return gInfo, result, anteEvents, priority, pendingTxChecker, expireHandler, ctx, 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 1cc05327a..dc8b5150f 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 25d1a33fb..81d0ab14b 100644 --- a/types/context.go +++ b/types/context.go @@ -48,6 +48,11 @@ type Context struct { txCompletionChannels acltypes.MessageAccessOpsChannelMapping txMsgAccessOps map[int][]acltypes.AccessOperation + // EVM properties + evm bool // EVM transaction flag + evmNonce uint64 // EVM Transaction nonce + evmSenderAddress string // EVM Sender address + msgValidator *acltypes.MsgValidator messageIndex int // Used to track current message being processed txIndex int @@ -123,6 +128,18 @@ func (c Context) ExpireTxHandler() abci.ExpireTxHandler { return c.expireTxHandler } +func (c Context) EVMSenderAddress() string { + return c.evmSenderAddress +} + +func (c Context) EVMNonce() uint64 { + return c.evmNonce +} + +func (c Context) IsEVM() bool { + return c.evm +} + func (c Context) PendingTxChecker() abci.PendingTxChecker { return c.pendingTxChecker } @@ -364,6 +381,21 @@ func (c Context) WithTraceSpanContext(ctx context.Context) Context { return c } +func (c Context) WithEVMSenderAddress(address string) Context { + c.evmSenderAddress = address + return c +} + +func (c Context) WithEVMNonce(nonce uint64) Context { + c.evmNonce = nonce + return c +} + +func (c Context) WithIsEVM(isEVM bool) Context { + c.evm = isEVM + return c +} + func (c Context) WithPendingTxChecker(checker abci.PendingTxChecker) Context { c.pendingTxChecker = checker return c