From 355f4d7e422f111b6a61243872adc6d5661f4cad Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Wed, 28 Aug 2024 09:47:51 +0000 Subject: [PATCH] feat(x/auth/tx): extend app module + docs (#21409) --- x/auth/module.go | 2 +- x/auth/tx/README.md | 10 +++++++ x/auth/tx/config/depinject.go | 52 ++++++++++++--------------------- x/auth/tx/config/module.go | 54 +++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 35 deletions(-) create mode 100644 x/auth/tx/config/module.go diff --git a/x/auth/module.go b/x/auth/module.go index 3a8aed7b696a..49a358a1bf24 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -51,7 +51,7 @@ type AppModule struct { // IsAppModule implements the appmodule.AppModule interface. func (am AppModule) IsAppModule() {} -// NewAppModule creates a new AppModule object +// NewAppModule creates a new AppModule object. func NewAppModule( cdc codec.Codec, accountKeeper keeper.AccountKeeper, diff --git a/x/auth/tx/README.md b/x/auth/tx/README.md index 4fba6e3f7c3d..981f375dc0de 100644 --- a/x/auth/tx/README.md +++ b/x/auth/tx/README.md @@ -17,12 +17,15 @@ This document specifies the `x/auth/tx` package of the Cosmos SDK. This package represents the Cosmos SDK implementation of the `client.TxConfig`, `client.TxBuilder`, `client.TxEncoder` and `client.TxDecoder` interfaces. +It contains as well a depinject module and app module the registration of ante/post handler via `runtime` and tx validator via `runtime/v2`. + ## Contents * [Transactions](#transactions) * [`TxConfig`](#txconfig) * [`TxBuilder`](#txbuilder) * [`TxEncoder`/ `TxDecoder`](#txencoder-txdecoder) +* [Depinject \& App Module](#depinject--app-module) * [Client](#client) * [CLI](#cli) * [gRPC](#grpc) @@ -57,6 +60,13 @@ A `client.TxBuilder` can be accessed with `TxConfig.NewTxBuilder()`. More information about `TxEncoder` and `TxDecoder` can be found [here](https://docs.cosmos.network/main/core/encoding#transaction-encoding). +## Depinject & App Module + +The `x/auth/tx/config` contains a depinject module and app module. +The depinject module is there to setup ante/post handlers on an runtime app (via baseapp options) and the tx validator on the runtime/v2 app (via app module). It as well outputs the `TxConfig` and `TxConfigOptions` for the app. + +The app module is purely there for registering tx validators, due to the design of tx validators (tx validator belong to modules). + ## Client ### CLI diff --git a/x/auth/tx/config/depinject.go b/x/auth/tx/config/depinject.go index 09c49fd4e937..bb573f044f6a 100644 --- a/x/auth/tx/config/depinject.go +++ b/x/auth/tx/config/depinject.go @@ -14,8 +14,7 @@ import ( bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1" txconfigv1 "cosmossdk.io/api/cosmos/tx/config/v1" "cosmossdk.io/core/address" - "cosmossdk.io/core/appmodule" - appmodulev2 "cosmossdk.io/core/appmodule/v2" + "cosmossdk.io/core/appmodule/v2" "cosmossdk.io/core/transaction" "cosmossdk.io/depinject" "cosmossdk.io/depinject/appconfig" @@ -52,23 +51,24 @@ type ModuleInputs struct { ProtoFileResolver txsigning.ProtoFileResolver Environment appmodule.Environment // BankKeeper is the expected bank keeper to be passed to AnteHandlers - BankKeeper authtypes.BankKeeper `optional:"true"` - MetadataBankKeeper BankKeeper `optional:"true"` - AccountKeeper ante.AccountKeeper `optional:"true"` - FeeGrantKeeper ante.FeegrantKeeper `optional:"true"` - AccountAbstractionKeeper ante.AccountAbstractionKeeper `optional:"true"` - CustomSignModeHandlers func() []txsigning.SignModeHandler `optional:"true"` - CustomGetSigners []txsigning.CustomGetSigner `optional:"true"` - UnorderedTxManager *unorderedtx.Manager `optional:"true"` + BankKeeper authtypes.BankKeeper `optional:"true"` + MetadataBankKeeper BankKeeper `optional:"true"` + AccountKeeper ante.AccountKeeper `optional:"true"` + FeeGrantKeeper ante.FeegrantKeeper `optional:"true"` + AccountAbstractionKeeper ante.AccountAbstractionKeeper `optional:"true"` + CustomSignModeHandlers func() []txsigning.SignModeHandler `optional:"true"` + CustomGetSigners []txsigning.CustomGetSigner `optional:"true"` + UnorderedTxManager *unorderedtx.Manager `optional:"true"` + ExtraTxValidators []appmodule.TxValidator[transaction.Tx] `optional:"true"` } type ModuleOutputs struct { depinject.Out + Module appmodule.AppModule // This is only useful for chains using server/v2. It setup tx validators that don't belong to other modules. + BaseAppOption runtime.BaseAppOption // This is only useful for chains using baseapp. Server/v2 chains use TxValidator. TxConfig client.TxConfig TxConfigOptions tx.ConfigOptions - BaseAppOption runtime.BaseAppOption // This is only useful for chains using baseapp. Server/v2 chains use TxValidator. - Module appmodule.AppModule } func ProvideProtoRegistry() txsigning.ProtoFileResolver { @@ -152,9 +152,13 @@ func ProvideModule(in ModuleInputs) ModuleOutputs { ante.DefaultSigVerificationGasConsumer, in.AccountAbstractionKeeper, ) - appModule := AppModule{svd} - return ModuleOutputs{TxConfig: txConfig, TxConfigOptions: txConfigOptions, BaseAppOption: baseAppOption, Module: appModule} + return ModuleOutputs{ + Module: NewAppModule(svd, in.ExtraTxValidators...), + TxConfig: txConfig, + TxConfigOptions: txConfigOptions, + BaseAppOption: baseAppOption, + } } func newAnteHandler(txConfig client.TxConfig, in ModuleInputs) (sdk.AnteHandler, error) { @@ -235,23 +239,3 @@ func metadataExists(err error) error { return err } - -var ( - _ appmodulev2.AppModule = AppModule{} - _ appmodulev2.HasTxValidator[transaction.Tx] = AppModule{} -) - -type AppModule struct { - sigVerification ante.SigVerificationDecorator -} - -// TxValidator implements appmodule.HasTxValidator. -func (a AppModule) TxValidator(ctx context.Context, tx transaction.Tx) error { - return a.sigVerification.ValidateTx(ctx, tx) -} - -// IsAppModule implements appmodule.AppModule. -func (a AppModule) IsAppModule() {} - -// IsOnePerModuleType implements appmodule.AppModule. -func (a AppModule) IsOnePerModuleType() {} diff --git a/x/auth/tx/config/module.go b/x/auth/tx/config/module.go new file mode 100644 index 000000000000..6e94e0e8cfac --- /dev/null +++ b/x/auth/tx/config/module.go @@ -0,0 +1,54 @@ +package tx + +import ( + "context" + + appmodulev2 "cosmossdk.io/core/appmodule/v2" + "cosmossdk.io/core/transaction" + "cosmossdk.io/x/auth/ante" +) + +var ( + _ appmodulev2.AppModule = AppModule{} + _ appmodulev2.HasTxValidator[transaction.Tx] = AppModule{} +) + +// AppModule is a module that only implements tx validators. +// The goal of this module is to allow extensible registration of tx validators provided by chains without requiring a new modules. +// Additionally, it registers tx validators that do not really have a place in other modules. +// This module is only useful for chains using server/v2. Ante/Post handlers are setup via baseapp options in depinject. +type AppModule struct { + sigVerification ante.SigVerificationDecorator + // txValidators contains tx validator that can be injected into the module via depinject. + // tx validators should be module based, but it can happen that you do not want to create a new module + // and simply depinject-it. + txValidators []appmodulev2.TxValidator[transaction.Tx] +} + +// NewAppModule creates a new AppModule object. +func NewAppModule( + sigVerification ante.SigVerificationDecorator, + txValidators ...appmodulev2.TxValidator[transaction.Tx], +) AppModule { + return AppModule{ + sigVerification: sigVerification, + txValidators: txValidators, + } +} + +// IsAppModule implements appmodule.AppModule. +func (a AppModule) IsAppModule() {} + +// IsOnePerModuleType implements appmodule.AppModule. +func (a AppModule) IsOnePerModuleType() {} + +// TxValidator implements appmodule.HasTxValidator. +func (a AppModule) TxValidator(ctx context.Context, tx transaction.Tx) error { + for _, txValidator := range a.txValidators { + if err := txValidator.ValidateTx(ctx, tx); err != nil { + return err + } + } + + return a.sigVerification.ValidateTx(ctx, tx) +}