From 136c9da5be129b38e73572bedeb800decdc4c8be Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Mon, 30 Sep 2024 09:29:26 +0200 Subject: [PATCH 01/12] create checktx handler --- baseapp/baseapp.go | 1 + baseapp/options.go | 9 +++++++++ types/abci.go | 3 +++ 3 files changed, 13 insertions(+) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 89748eadf053..37e22731102e 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -91,6 +91,7 @@ type BaseApp struct { prepareCheckStater sdk.PrepareCheckStater // logic to run during commit using the checkState precommiter sdk.Precommiter // logic to run during commit using the deliverState versionModifier server.VersionModifier // interface to get and set the app version + checkTxHandler sdk.CheckTxHandler addrPeerFilter sdk.PeerFilter // filter peers by address and port idPeerFilter sdk.PeerFilter // filter peers by node ID diff --git a/baseapp/options.go b/baseapp/options.go index 53286b2540b9..c1039727ac2b 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -367,6 +367,15 @@ func (app *BaseApp) SetPrepareProposal(handler sdk.PrepareProposalHandler) { app.prepareProposal = handler } +// SetCheckTx sets the checkTx function for the BaseApp. +func (app *BaseApp) SetCheckTx(handler sdk.CheckTxHandler) { + if app.sealed { + panic("SetCheckTx() on sealed BaseApp") + } + + app.checkTxHandler = handler +} + func (app *BaseApp) SetExtendVoteHandler(handler sdk.ExtendVoteHandler) { if app.sealed { panic("SetExtendVoteHandler() on sealed BaseApp") diff --git a/types/abci.go b/types/abci.go index 30e6beee391e..6f19fcba1d2a 100644 --- a/types/abci.go +++ b/types/abci.go @@ -23,6 +23,9 @@ type ProcessProposalHandler func(Context, *abci.ProcessProposalRequest) (*abci.P // PrepareProposalHandler defines a function type alias for preparing a proposal type PrepareProposalHandler func(Context, *abci.PrepareProposalRequest) (*abci.PrepareProposalResponse, error) +// CheckTxHandler defines a function type alias for executing logic before transactions are executed. +type CheckTxHandler func(Context, *abci.CheckTxRequest) (*abci.CheckTxResponse, error) + // ExtendVoteHandler defines a function type alias for extending a pre-commit vote. type ExtendVoteHandler func(Context, *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error) From 94f6f3dd3aafe22624ff68e3b81d0a693a247288 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Mon, 30 Sep 2024 10:06:02 +0200 Subject: [PATCH 02/12] allow custom checktx --- baseapp/abci.go | 12 +++++++++++- baseapp/baseapp.go | 18 ++++++++++-------- baseapp/test_helpers.go | 6 +++--- types/abci.go | 2 +- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index f0f24ef52844..93363557cbab 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -367,7 +367,17 @@ func (app *BaseApp) CheckTx(req *abci.CheckTxRequest) (*abci.CheckTxResponse, er return nil, fmt.Errorf("unknown RequestCheckTx type: %s", req.Type) } - gInfo, result, anteEvents, err := app.runTx(mode, req.Tx) + var decodedTx sdk.Tx = nil + ctx := app.getContextForTx(mode, req.Tx) + if app.checkTxHandler != nil { + tx, err := app.checkTxHandler(ctx, req.Tx) + if err != nil { + return nil, fmt.Errorf("checkTxHandler error: %w", err) + } + decodedTx = tx + } + + gInfo, result, anteEvents, err := app.runTx(mode, req.Tx, decodedTx) if err != nil { return responseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace), nil } diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 37e22731102e..e2371ff41a73 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -689,7 +689,6 @@ func (app *BaseApp) getContextForTx(mode execMode, txBytes []byte) sdk.Context { // a branched multi-store. func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) (sdk.Context, storetypes.CacheMultiStore) { ms := ctx.MultiStore() - // TODO: https://github.com/cosmos/cosmos-sdk/issues/2824 msCache := ms.CacheMultiStore() if msCache.TracingEnabled() { msCache = msCache.SetTracingContext( @@ -762,7 +761,7 @@ func (app *BaseApp) deliverTx(tx []byte) *abci.ExecTxResult { telemetry.SetGauge(float32(gInfo.GasWanted), "tx", "gas", "wanted") }() - gInfo, result, anteEvents, err := app.runTx(execModeFinalize, tx) + gInfo, result, anteEvents, err := app.runTx(execModeFinalize, tx, nil) if err != nil { resultStr = "failed" resp = responseExecTxResultWithEvents( @@ -823,7 +822,7 @@ type HasNestedMsgs interface { // Note, gas execution info is always returned. A reference to a Result is // returned if the tx does not run out of gas and if all the messages are valid // and execute successfully. An error is returned otherwise. -func (app *BaseApp) runTx(mode execMode, txBytes []byte) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) { +func (app *BaseApp) runTx(mode execMode, txBytes []byte, tx sdk.Tx) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) { // NOTE: GasWanted should be returned by the AnteHandler. GasUsed is // determined by the GasMeter. We need access to the context to get the gas // meter, so we initialize upfront. @@ -871,9 +870,12 @@ func (app *BaseApp) runTx(mode execMode, txBytes []byte) (gInfo sdk.GasInfo, res defer consumeBlockGas() } - tx, err := app.txDecoder(txBytes) - if err != nil { - return sdk.GasInfo{GasUsed: 0, GasWanted: 0}, nil, nil, sdkerrors.ErrTxDecode.Wrap(err.Error()) + // if the transaction is not decoded, decode it here + if tx == nil { + tx, err = app.txDecoder(txBytes) + if err != nil { + return sdk.GasInfo{GasUsed: 0, GasWanted: 0}, nil, nil, sdkerrors.ErrTxDecode.Wrap(err.Error()) + } } msgs := tx.GetMsgs() @@ -1161,7 +1163,7 @@ func (app *BaseApp) PrepareProposalVerifyTx(tx sdk.Tx) ([]byte, error) { return nil, err } - _, _, _, err = app.runTx(execModePrepareProposal, bz) + _, _, _, err = app.runTx(execModePrepareProposal, bz, tx) // TODO: we should remove encoding here if err != nil { return nil, err } @@ -1180,7 +1182,7 @@ func (app *BaseApp) ProcessProposalVerifyTx(txBz []byte) (sdk.Tx, error) { return nil, err } - _, _, _, err = app.runTx(execModeProcessProposal, txBz) + _, _, _, err = app.runTx(execModeProcessProposal, txBz, tx) if err != nil { return nil, err } diff --git a/baseapp/test_helpers.go b/baseapp/test_helpers.go index fcd0e55c8447..7cae8e541b7d 100644 --- a/baseapp/test_helpers.go +++ b/baseapp/test_helpers.go @@ -19,13 +19,13 @@ func (app *BaseApp) SimCheck(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, * return sdk.GasInfo{}, nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "%s", err) } - gasInfo, result, _, err := app.runTx(execModeCheck, bz) + gasInfo, result, _, err := app.runTx(execModeCheck, bz, tx) return gasInfo, result, err } // Simulate executes a tx in simulate mode to get result and gas info. func (app *BaseApp) Simulate(txBytes []byte) (sdk.GasInfo, *sdk.Result, error) { - gasInfo, result, _, err := app.runTx(execModeSimulate, txBytes) + gasInfo, result, _, err := app.runTx(execModeSimulate, txBytes, nil) return gasInfo, result, err } @@ -36,7 +36,7 @@ func (app *BaseApp) SimDeliver(txEncoder sdk.TxEncoder, tx sdk.Tx) (sdk.GasInfo, return sdk.GasInfo{}, nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "%s", err) } - gasInfo, result, _, err := app.runTx(execModeFinalize, bz) + gasInfo, result, _, err := app.runTx(execModeFinalize, bz, tx) return gasInfo, result, err } diff --git a/types/abci.go b/types/abci.go index 6f19fcba1d2a..17843f92d562 100644 --- a/types/abci.go +++ b/types/abci.go @@ -24,7 +24,7 @@ type ProcessProposalHandler func(Context, *abci.ProcessProposalRequest) (*abci.P type PrepareProposalHandler func(Context, *abci.PrepareProposalRequest) (*abci.PrepareProposalResponse, error) // CheckTxHandler defines a function type alias for executing logic before transactions are executed. -type CheckTxHandler func(Context, *abci.CheckTxRequest) (*abci.CheckTxResponse, error) +type CheckTxHandler func(Context, []byte) (Tx, error) // ExtendVoteHandler defines a function type alias for extending a pre-commit vote. type ExtendVoteHandler func(Context, *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error) From c71365c3322de76555dd12e7f1dbd6c5585fa169 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Mon, 30 Sep 2024 10:26:06 +0200 Subject: [PATCH 03/12] add docs on checktx handler --- baseapp/baseapp.go | 2 +- baseapp/options.go | 2 +- docs/build/abci/04-checktx.md | 87 ++++++++++++++++++++++ docs/build/building-apps/02-app-mempool.md | 2 +- 4 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 docs/build/abci/04-checktx.md diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index e2371ff41a73..7c7fe525e445 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -1163,7 +1163,7 @@ func (app *BaseApp) PrepareProposalVerifyTx(tx sdk.Tx) ([]byte, error) { return nil, err } - _, _, _, err = app.runTx(execModePrepareProposal, bz, tx) // TODO: we should remove encoding here + _, _, _, err = app.runTx(execModePrepareProposal, bz, tx) if err != nil { return nil, err } diff --git a/baseapp/options.go b/baseapp/options.go index c1039727ac2b..1d03048f02ec 100644 --- a/baseapp/options.go +++ b/baseapp/options.go @@ -368,7 +368,7 @@ func (app *BaseApp) SetPrepareProposal(handler sdk.PrepareProposalHandler) { } // SetCheckTx sets the checkTx function for the BaseApp. -func (app *BaseApp) SetCheckTx(handler sdk.CheckTxHandler) { +func (app *BaseApp) SetCheckTxHandler(handler sdk.CheckTxHandler) { if app.sealed { panic("SetCheckTx() on sealed BaseApp") } diff --git a/docs/build/abci/04-checktx.md b/docs/build/abci/04-checktx.md new file mode 100644 index 000000000000..bdad561ea0e4 --- /dev/null +++ b/docs/build/abci/04-checktx.md @@ -0,0 +1,87 @@ +# CheckTx + +CheckTx is called by the `BaseApp` when comet receives a transaction from a client, over the p2p network or RPC. The CheckTx method is responsible for validating the transaction and returning an error if the transaction is invalid. + +```mermaid +graph TD + subgraph SDK[Cosmos SDK] + B[Baseapp] + A[AnteHandlers] + B <-->|Validate TX| A + end + C[CometBFT] <-->|CheckTx|SDK + U((User)) -->|Submit TX| C + N[P2P] -->|Receive TX| C +``` + +```go +// CheckTx implements the ABCI interface. +func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { + var mode execMode + + switch { + case req.Type == abci.CHECK_TX_TYPE_CHECK: + mode = execModeCheck + + case req.Type == abci.CHECK_TX_TYPE_RECHECK: + mode = execModeReCheck + + default: + return nil, fmt.Errorf("unknown RequestCheckTx type: %s", req.Type) + } + + var decodedTx sdk.Tx = nil + ctx := app.getContextForTx(mode, req.Tx) + if app.checkTxHandler != nil { + tx, err := app.checkTxHandler(ctx, req.Tx) + if err != nil { + return nil, fmt.Errorf("checkTxHandler error: %w", err) + } + decodedTx = tx + } + + gInfo, result, anteEvents, err := app.runTx(mode, req.Tx, decodedTx) + if err != nil { + return responseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace), nil + } + + return &abci.CheckTxResponse{ + GasWanted: int64(gInfo.GasWanted), + GasUsed: int64(gInfo.GasUsed), + Log: result.Log, + Data: result.Data, + Events: sdk.MarkEventsToIndex(result.Events, app.indexEvents), + }, nil +} +``` + +## CheckTx Handler + +`CheckTxHandler` allows users to extend the logic of `CheckTx`. `CheckTxHandler` is called by pasding context and the transaction bytes received through ABCI. It is required that the handler returns deterministic results given the same transaction bytes. + +:::note +we return the raw decoded transaction here to avoid decoding it twice. +::: + +```go +type CheckTxHandler func(ctx sdk.Context, tx []byte) (Tx, error) +``` + +Setting a custom `CheckTxHandler` is optional. It can be done from your app.go file: + +```go +func NewSimApp( + logger log.Logger, + db corestore.KVStoreWithBatch, + traceStore io.Writer, + loadLatest bool, + appOpts servertypes.AppOptions, + baseAppOptions ...func(*baseapp.BaseApp), +) *SimApp { + ... + // Create ChecktxHandler + checktxHandler := abci.NewCustomCheckTxHandler(...) + app.SetCheckTxHandler(checktxHandler) + ... +} +``` diff --git a/docs/build/building-apps/02-app-mempool.md b/docs/build/building-apps/02-app-mempool.md index 45719af4824d..d22832b3f166 100644 --- a/docs/build/building-apps/02-app-mempool.md +++ b/docs/build/building-apps/02-app-mempool.md @@ -22,7 +22,7 @@ Notably it introduces the `PrepareProposal` and `ProcessProposal` steps of ABCI+ ## Mempool -+ Before we delve into `PrepareProposal` and `ProcessProposal`, let's first walk through the mempool concepts. +* Before we delve into `PrepareProposal` and `ProcessProposal`, let's first walk through the mempool concepts. There are countless designs that an application developer can write for a mempool, the SDK opted to provide only simple mempool implementations. Namely, the SDK provides the following mempools: From a789bbe00a742e61f3d0f3bd05379a79c8a2c1ba Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Mon, 30 Sep 2024 11:09:39 +0200 Subject: [PATCH 04/12] adjust for handler to take in the type --- baseapp/abci.go | 2 +- baseapp/baseapp.go | 2 +- types/abci.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index 93363557cbab..93c44e9c4f01 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -370,7 +370,7 @@ func (app *BaseApp) CheckTx(req *abci.CheckTxRequest) (*abci.CheckTxResponse, er var decodedTx sdk.Tx = nil ctx := app.getContextForTx(mode, req.Tx) if app.checkTxHandler != nil { - tx, err := app.checkTxHandler(ctx, req.Tx) + tx, err := app.checkTxHandler(ctx, mode, req.Tx) if err != nil { return nil, fmt.Errorf("checkTxHandler error: %w", err) } diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 7c7fe525e445..a44825d24307 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -37,7 +37,7 @@ import ( ) type ( - execMode uint8 + execMode = uint8 // StoreLoader defines a customizable function to control how we load the // CommitMultiStore from disk. This is useful for state migration, when diff --git a/types/abci.go b/types/abci.go index 17843f92d562..fdb7df6d50fb 100644 --- a/types/abci.go +++ b/types/abci.go @@ -24,7 +24,7 @@ type ProcessProposalHandler func(Context, *abci.ProcessProposalRequest) (*abci.P type PrepareProposalHandler func(Context, *abci.PrepareProposalRequest) (*abci.PrepareProposalResponse, error) // CheckTxHandler defines a function type alias for executing logic before transactions are executed. -type CheckTxHandler func(Context, []byte) (Tx, error) +type CheckTxHandler func(ctx Context, mode uint8, txBytes []byte) (Tx, error) // ExtendVoteHandler defines a function type alias for extending a pre-commit vote. type ExtendVoteHandler func(Context, *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error) From 38b7154b319c008e50a210f066d59dbab9706953 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Mon, 30 Sep 2024 11:10:41 +0200 Subject: [PATCH 05/12] changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba6219268f7c..9aac848e00a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i * (client/keys) [#21829](https://github.com/cosmos/cosmos-sdk/pull/21829) Add support for importing hex key using standard input. * (x/validate) [#21822](https://github.com/cosmos/cosmos-sdk/pull/21822) New module solely responsible for providing ante/post handlers and tx validators for v2. It can be extended by the app developer to provide extra tx validators. * In comparison to x/auth/tx/config, there is no app config to skip ante/post handlers, as overwriting them in baseapp or not injecting the x/validate module has the same effect. +* (baeapp) [#21979](https://github.com/cosmos/cosmos-sdk/pull/21979) Create CheckTxHandler to allow extending the logic of CheckTx. ### Improvements From 1ade678f5e143688b15373d55b087f32f41cd61e Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Mon, 30 Sep 2024 12:55:47 +0200 Subject: [PATCH 06/12] invert it --- baseapp/abci.go | 28 +++++++++++----------------- docs/build/abci/04-checktx.md | 9 --------- types/abci.go | 4 +++- 3 files changed, 14 insertions(+), 27 deletions(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index 93c44e9c4f01..e23ac46d7ff5 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -367,28 +367,22 @@ func (app *BaseApp) CheckTx(req *abci.CheckTxRequest) (*abci.CheckTxResponse, er return nil, fmt.Errorf("unknown RequestCheckTx type: %s", req.Type) } - var decodedTx sdk.Tx = nil - ctx := app.getContextForTx(mode, req.Tx) - if app.checkTxHandler != nil { - tx, err := app.checkTxHandler(ctx, mode, req.Tx) + if app.checkTxHandler == nil { + gInfo, result, anteEvents, err := app.runTx(mode, req.Tx, nil) if err != nil { - return nil, fmt.Errorf("checkTxHandler error: %w", err) + return responseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace), nil } - decodedTx = tx - } - gInfo, result, anteEvents, err := app.runTx(mode, req.Tx, decodedTx) - if err != nil { - return responseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace), nil + return &abci.CheckTxResponse{ + GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints? + GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints? + Log: result.Log, + Data: result.Data, + Events: sdk.MarkEventsToIndex(result.Events, app.indexEvents), + }, nil } - return &abci.CheckTxResponse{ - GasWanted: int64(gInfo.GasWanted), // TODO: Should type accept unsigned ints? - GasUsed: int64(gInfo.GasUsed), // TODO: Should type accept unsigned ints? - Log: result.Log, - Data: result.Data, - Events: sdk.MarkEventsToIndex(result.Events, app.indexEvents), - }, nil + return app.checkTxHandler(app.runTx, req) } // PrepareProposal implements the PrepareProposal ABCI method and returns a diff --git a/docs/build/abci/04-checktx.md b/docs/build/abci/04-checktx.md index bdad561ea0e4..00bcc73f02cc 100644 --- a/docs/build/abci/04-checktx.md +++ b/docs/build/abci/04-checktx.md @@ -30,15 +30,6 @@ func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { return nil, fmt.Errorf("unknown RequestCheckTx type: %s", req.Type) } - var decodedTx sdk.Tx = nil - ctx := app.getContextForTx(mode, req.Tx) - if app.checkTxHandler != nil { - tx, err := app.checkTxHandler(ctx, req.Tx) - if err != nil { - return nil, fmt.Errorf("checkTxHandler error: %w", err) - } - decodedTx = tx - } gInfo, result, anteEvents, err := app.runTx(mode, req.Tx, decodedTx) if err != nil { diff --git a/types/abci.go b/types/abci.go index fdb7df6d50fb..8ca5a2618d8e 100644 --- a/types/abci.go +++ b/types/abci.go @@ -24,7 +24,9 @@ type ProcessProposalHandler func(Context, *abci.ProcessProposalRequest) (*abci.P type PrepareProposalHandler func(Context, *abci.PrepareProposalRequest) (*abci.PrepareProposalResponse, error) // CheckTxHandler defines a function type alias for executing logic before transactions are executed. -type CheckTxHandler func(ctx Context, mode uint8, txBytes []byte) (Tx, error) +type CheckTxHandler func(runTx, *abci.CheckTxRequest) (*abci.CheckTxResponse, error) + +type runTx func(mode uint8, txBytes []byte, tx Tx) (gInfo GasInfo, result *Result, anteEvents []abci.Event, err error) // ExtendVoteHandler defines a function type alias for extending a pre-commit vote. type ExtendVoteHandler func(Context, *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error) From b2c856aa7b4b2c03694dc17cb62c0beb898957f8 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Mon, 30 Sep 2024 12:59:17 +0200 Subject: [PATCH 07/12] godoc --- docs/build/abci/04-checktx.md | 32 ++------------------------------ types/abci.go | 6 ++++-- 2 files changed, 6 insertions(+), 32 deletions(-) diff --git a/docs/build/abci/04-checktx.md b/docs/build/abci/04-checktx.md index 00bcc73f02cc..64d3f346bb1c 100644 --- a/docs/build/abci/04-checktx.md +++ b/docs/build/abci/04-checktx.md @@ -14,36 +14,8 @@ graph TD N[P2P] -->|Receive TX| C ``` -```go -// CheckTx implements the ABCI interface. -func (app *BaseApp) CheckTx(req abci.RequestCheckTx) abci.ResponseCheckTx { - var mode execMode - - switch { - case req.Type == abci.CHECK_TX_TYPE_CHECK: - mode = execModeCheck - - case req.Type == abci.CHECK_TX_TYPE_RECHECK: - mode = execModeReCheck - - default: - return nil, fmt.Errorf("unknown RequestCheckTx type: %s", req.Type) - } - - - gInfo, result, anteEvents, err := app.runTx(mode, req.Tx, decodedTx) - if err != nil { - return responseCheckTxWithEvents(err, gInfo.GasWanted, gInfo.GasUsed, anteEvents, app.trace), nil - } - - return &abci.CheckTxResponse{ - GasWanted: int64(gInfo.GasWanted), - GasUsed: int64(gInfo.GasUsed), - Log: result.Log, - Data: result.Data, - Events: sdk.MarkEventsToIndex(result.Events, app.indexEvents), - }, nil -} +```go reference +https://github.com/cosmos/cosmos-sdk/blob/31c604762a434c7b676b6a89897ecbd7c4653a23/baseapp/abci.go#L350-L386 ``` ## CheckTx Handler diff --git a/types/abci.go b/types/abci.go index 8ca5a2618d8e..1485800ca509 100644 --- a/types/abci.go +++ b/types/abci.go @@ -24,9 +24,11 @@ type ProcessProposalHandler func(Context, *abci.ProcessProposalRequest) (*abci.P type PrepareProposalHandler func(Context, *abci.PrepareProposalRequest) (*abci.PrepareProposalResponse, error) // CheckTxHandler defines a function type alias for executing logic before transactions are executed. -type CheckTxHandler func(runTx, *abci.CheckTxRequest) (*abci.CheckTxResponse, error) +// `RunTx` is a function type alias for executing logic before transactions are executed. +type CheckTxHandler func(RunTx, *abci.CheckTxRequest) (*abci.CheckTxResponse, error) -type runTx func(mode uint8, txBytes []byte, tx Tx) (gInfo GasInfo, result *Result, anteEvents []abci.Event, err error) +// RunTx defines a function type alias for executing logic before transactions are executed. +type RunTx func(mode uint8, txBytes []byte, tx Tx) (gInfo GasInfo, result *Result, anteEvents []abci.Event, err error) // ExtendVoteHandler defines a function type alias for extending a pre-commit vote. type ExtendVoteHandler func(Context, *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error) From b09a0632452c11e71dceaffff45b260044154df9 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Mon, 30 Sep 2024 13:02:40 +0200 Subject: [PATCH 08/12] modiify runtx func --- baseapp/abci.go | 7 ++++++- types/abci.go | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/baseapp/abci.go b/baseapp/abci.go index e23ac46d7ff5..27118f0f3b10 100644 --- a/baseapp/abci.go +++ b/baseapp/abci.go @@ -382,7 +382,12 @@ func (app *BaseApp) CheckTx(req *abci.CheckTxRequest) (*abci.CheckTxResponse, er }, nil } - return app.checkTxHandler(app.runTx, req) + // Create wrapper to avoid users overriding the execution mode + runTx := func(txBytes []byte, tx sdk.Tx) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) { + return app.runTx(mode, txBytes, tx) + } + + return app.checkTxHandler(runTx, req) } // PrepareProposal implements the PrepareProposal ABCI method and returns a diff --git a/types/abci.go b/types/abci.go index 1485800ca509..aac87b0531f3 100644 --- a/types/abci.go +++ b/types/abci.go @@ -28,7 +28,7 @@ type PrepareProposalHandler func(Context, *abci.PrepareProposalRequest) (*abci.P type CheckTxHandler func(RunTx, *abci.CheckTxRequest) (*abci.CheckTxResponse, error) // RunTx defines a function type alias for executing logic before transactions are executed. -type RunTx func(mode uint8, txBytes []byte, tx Tx) (gInfo GasInfo, result *Result, anteEvents []abci.Event, err error) +type RunTx func(txBytes []byte, tx Tx) (gInfo GasInfo, result *Result, anteEvents []abci.Event, err error) // ExtendVoteHandler defines a function type alias for extending a pre-commit vote. type ExtendVoteHandler func(Context, *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error) From 20e9fc04a5d00daec4f730893aa99e8c3dc0ee65 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Mon, 30 Sep 2024 13:03:14 +0200 Subject: [PATCH 09/12] tt --- docs/build/abci/04-checktx.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build/abci/04-checktx.md b/docs/build/abci/04-checktx.md index 64d3f346bb1c..a2c5f2d707d6 100644 --- a/docs/build/abci/04-checktx.md +++ b/docs/build/abci/04-checktx.md @@ -15,7 +15,7 @@ graph TD ``` ```go reference -https://github.com/cosmos/cosmos-sdk/blob/31c604762a434c7b676b6a89897ecbd7c4653a23/baseapp/abci.go#L350-L386 +https://github.com/cosmos/cosmos-sdk/blob/31c604762a434c7b676b6a89897ecbd7c4653a23/baseapp/abci.go#L350-L390 ``` ## CheckTx Handler From 228cd9bb98aeeab612723b25ae6529b784ec369a Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Mon, 30 Sep 2024 13:21:21 +0200 Subject: [PATCH 10/12] address comments --- baseapp/baseapp.go | 3 ++- types/abci.go | 5 +---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index a44825d24307..88b85531db8b 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -37,7 +37,7 @@ import ( ) type ( - execMode = uint8 + execMode uint8 // StoreLoader defines a customizable function to control how we load the // CommitMultiStore from disk. This is useful for state migration, when @@ -822,6 +822,7 @@ type HasNestedMsgs interface { // Note, gas execution info is always returned. A reference to a Result is // returned if the tx does not run out of gas and if all the messages are valid // and execute successfully. An error is returned otherwise. +// both txbytes and the decoded tx are passed to runTx to avoid the state machine encoding the tx and decoding the transaction twice func (app *BaseApp) runTx(mode execMode, txBytes []byte, tx sdk.Tx) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) { // NOTE: GasWanted should be returned by the AnteHandler. GasUsed is // determined by the GasMeter. We need access to the context to get the gas diff --git a/types/abci.go b/types/abci.go index aac87b0531f3..60c975f35dd8 100644 --- a/types/abci.go +++ b/types/abci.go @@ -25,10 +25,7 @@ type PrepareProposalHandler func(Context, *abci.PrepareProposalRequest) (*abci.P // CheckTxHandler defines a function type alias for executing logic before transactions are executed. // `RunTx` is a function type alias for executing logic before transactions are executed. -type CheckTxHandler func(RunTx, *abci.CheckTxRequest) (*abci.CheckTxResponse, error) - -// RunTx defines a function type alias for executing logic before transactions are executed. -type RunTx func(txBytes []byte, tx Tx) (gInfo GasInfo, result *Result, anteEvents []abci.Event, err error) +type CheckTxHandler func(func(txBytes []byte, tx Tx) (gInfo GasInfo, result *Result, anteEvents []abci.Event, err error), *abci.CheckTxRequest) (*abci.CheckTxResponse, error) // ExtendVoteHandler defines a function type alias for extending a pre-commit vote. type ExtendVoteHandler func(Context, *abci.ExtendVoteRequest) (*abci.ExtendVoteResponse, error) From 0a50812644e700cb54ad3cac81a5b6b99bb6a61a Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Mon, 30 Sep 2024 15:24:42 +0200 Subject: [PATCH 11/12] add godoc for decoded tx being optiona; --- baseapp/baseapp.go | 1 + 1 file changed, 1 insertion(+) diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 88b85531db8b..b5d100d263a9 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -823,6 +823,7 @@ type HasNestedMsgs interface { // returned if the tx does not run out of gas and if all the messages are valid // and execute successfully. An error is returned otherwise. // both txbytes and the decoded tx are passed to runTx to avoid the state machine encoding the tx and decoding the transaction twice +// passing the decoded tx to runTX is optional, it will be decoded if the tx is nil func (app *BaseApp) runTx(mode execMode, txBytes []byte, tx sdk.Tx) (gInfo sdk.GasInfo, result *sdk.Result, anteEvents []abci.Event, err error) { // NOTE: GasWanted should be returned by the AnteHandler. GasUsed is // determined by the GasMeter. We need access to the context to get the gas From 76c5587f61530f2e662c0443473dc4c7556bdb35 Mon Sep 17 00:00:00 2001 From: marbar3778 Date: Tue, 1 Oct 2024 09:20:50 +0200 Subject: [PATCH 12/12] add go docs --- types/abci.go | 1 + 1 file changed, 1 insertion(+) diff --git a/types/abci.go b/types/abci.go index 60c975f35dd8..bcbc791388f3 100644 --- a/types/abci.go +++ b/types/abci.go @@ -25,6 +25,7 @@ type PrepareProposalHandler func(Context, *abci.PrepareProposalRequest) (*abci.P // CheckTxHandler defines a function type alias for executing logic before transactions are executed. // `RunTx` is a function type alias for executing logic before transactions are executed. +// The passed in runtx does not override antehandlers, the execution mode is not passed into runtx to avoid overriding the execution mode. type CheckTxHandler func(func(txBytes []byte, tx Tx) (gInfo GasInfo, result *Result, anteEvents []abci.Event, err error), *abci.CheckTxRequest) (*abci.CheckTxResponse, error) // ExtendVoteHandler defines a function type alias for extending a pre-commit vote.