From b163790cb60c2221793742eed6fecc22d4254315 Mon Sep 17 00:00:00 2001 From: Arnaud Mimart <33665250+amimart@users.noreply.github.com> Date: Mon, 19 Sep 2022 19:10:41 +0200 Subject: [PATCH] feat(wasm): wire wasm module in app --- app/app.go | 240 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 196 insertions(+), 44 deletions(-) diff --git a/app/app.go b/app/app.go index d743af71..a70f06ed 100644 --- a/app/app.go +++ b/app/app.go @@ -6,7 +6,10 @@ import ( "net/http" "os" "path/filepath" + "strings" + "github.com/CosmWasm/wasmd/x/wasm" + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" @@ -80,6 +83,9 @@ import ( upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" ica "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts" + icacontroller "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller" + icacontrollerkeeper "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/keeper" + icacontrollertypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types" icahost "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/host" icahostkeeper "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/host/keeper" icahosttypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/host/types" @@ -94,16 +100,23 @@ import ( ibcporttypes "github.com/cosmos/ibc-go/v5/modules/core/05-port/types" ibchost "github.com/cosmos/ibc-go/v5/modules/core/24-host" ibckeeper "github.com/cosmos/ibc-go/v5/modules/core/keeper" + intertx "github.com/cosmos/interchain-accounts/x/inter-tx" + intertxkeeper "github.com/cosmos/interchain-accounts/x/inter-tx/keeper" + intertxtypes "github.com/cosmos/interchain-accounts/x/inter-tx/types" logicmodule "github.com/okp4/okp4d/x/logic" logicmodulekeeper "github.com/okp4/okp4d/x/logic/keeper" logicmoduletypes "github.com/okp4/okp4d/x/logic/types" + "github.com/prometheus/client_golang/prometheus" "github.com/spf13/cast" abci "github.com/tendermint/tendermint/abci/types" tmjson "github.com/tendermint/tendermint/libs/json" "github.com/tendermint/tendermint/libs/log" tmos "github.com/tendermint/tendermint/libs/os" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" dbm "github.com/tendermint/tm-db" + wasmclient "github.com/CosmWasm/wasmd/x/wasm/client" + "github.com/ignite/cli/ignite/pkg/cosmoscmd" "github.com/ignite/cli/ignite/pkg/openapiconsole" @@ -116,9 +129,7 @@ const ( ) func getGovProposalHandlers() []govclient.ProposalHandler { - var govProposalHandlers []govclient.ProposalHandler - - govProposalHandlers = append(govProposalHandlers, + return append(wasmclient.ProposalHandlers, paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.LegacyProposalHandler, @@ -126,8 +137,6 @@ func getGovProposalHandlers() []govclient.ProposalHandler { ibcclientclient.UpdateClientProposalHandler, ibcclientclient.UpgradeProposalHandler, ) - - return govProposalHandlers } var ( @@ -158,6 +167,9 @@ var ( transfer.AppModuleBasic{}, ica.AppModuleBasic{}, vesting.AppModuleBasic{}, + wasm.AppModuleBasic{}, + ica.AppModuleBasic{}, + intertx.AppModuleBasic{}, logicmodule.AppModuleBasic{}, ) @@ -171,7 +183,20 @@ var ( stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, govtypes.ModuleName: {authtypes.Burner}, ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + wasm.ModuleName: {authtypes.Burner}, } + + // WasmProposalsEnabled enables all x/wasm proposals when it's value is "true" + // and EnableSpecificWasmProposals is empty. Otherwise, all x/wasm proposals + // are disabled. + WasmProposalsEnabled = "true" + + // EnableSpecificWasmProposals if set, must be comma-separated list of values + // that are all a subset of "EnableAllProposals", which takes precedence over + // WasmProposalsEnabled. + // + // See: https://github.com/CosmWasm/wasmd/blob/02a54d33ff2c064f3539ae12d75d027d9c665f05/x/wasm/internal/types/proposal.go#L28-L34 + EnableSpecificWasmProposals = "" ) var ( @@ -189,6 +214,28 @@ func init() { DefaultNodeHome = filepath.Join(userHomeDir, "."+Name) } +// GetWasmEnabledProposals parses the WasmProposalsEnabled and +// EnableSpecificWasmProposals values to produce a list of enabled proposals to +// pass into the application. +func GetWasmEnabledProposals() []wasm.ProposalType { + if EnableSpecificWasmProposals == "" { + if WasmProposalsEnabled == "true" { + return wasm.EnableAllProposals + } + + return wasm.DisableAllProposals + } + + chunks := strings.Split(EnableSpecificWasmProposals, ",") + + proposals, err := wasm.ConvertToProposals(chunks) + if err != nil { + panic(err) + } + + return proposals +} + // App extends an ABCI application, but with most of its parameters exported. // They are exported for convenience in creating helper functions, as object // capabilities aren't needed for testing. @@ -207,30 +254,36 @@ type App struct { memKeys map[string]*storetypes.MemoryStoreKey // keepers - AccountKeeper authkeeper.AccountKeeper - AuthzKeeper authzkeeper.Keeper - BankKeeper bankkeeper.Keeper - CapabilityKeeper *capabilitykeeper.Keeper - StakingKeeper stakingkeeper.Keeper - SlashingKeeper slashingkeeper.Keeper - MintKeeper mintkeeper.Keeper - DistrKeeper distrkeeper.Keeper - GovKeeper govkeeper.Keeper - CrisisKeeper crisiskeeper.Keeper - UpgradeKeeper upgradekeeper.Keeper - ParamsKeeper paramskeeper.Keeper - IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly - EvidenceKeeper evidencekeeper.Keeper - TransferKeeper ibctransferkeeper.Keeper - ICAHostKeeper icahostkeeper.Keeper - FeeGrantKeeper feegrantkeeper.Keeper - GroupKeeper groupkeeper.Keeper - LogicKeeper logicmodulekeeper.Keeper + AccountKeeper authkeeper.AccountKeeper + AuthzKeeper authzkeeper.Keeper + BankKeeper bankkeeper.Keeper + CapabilityKeeper *capabilitykeeper.Keeper + StakingKeeper stakingkeeper.Keeper + SlashingKeeper slashingkeeper.Keeper + MintKeeper mintkeeper.Keeper + DistrKeeper distrkeeper.Keeper + GovKeeper govkeeper.Keeper + CrisisKeeper crisiskeeper.Keeper + UpgradeKeeper upgradekeeper.Keeper + ParamsKeeper paramskeeper.Keeper + IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly + EvidenceKeeper evidencekeeper.Keeper + TransferKeeper ibctransferkeeper.Keeper + ICAHostKeeper icahostkeeper.Keeper + FeeGrantKeeper feegrantkeeper.Keeper + GroupKeeper groupkeeper.Keeper + ICAControllerKeeper icacontrollerkeeper.Keeper + InterTxKeeper intertxkeeper.Keeper + WasmKeeper wasm.Keeper + LogicKeeper logicmodulekeeper.Keeper // make scoped keepers public for test purposes - ScopedIBCKeeper capabilitykeeper.ScopedKeeper - ScopedTransferKeeper capabilitykeeper.ScopedKeeper - ScopedICAHostKeeper capabilitykeeper.ScopedKeeper + ScopedIBCKeeper capabilitykeeper.ScopedKeeper + ScopedTransferKeeper capabilitykeeper.ScopedKeeper + ScopedICAHostKeeper capabilitykeeper.ScopedKeeper + ScopedICAControllerKeeper capabilitykeeper.ScopedKeeper + ScopedInterTxKeeper capabilitykeeper.ScopedKeeper + ScopedWasmKeeper capabilitykeeper.ScopedKeeper // mm is the module manager mm *module.Manager @@ -269,7 +322,7 @@ func New( minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, icahosttypes.StoreKey, capabilitytypes.StoreKey, group.StoreKey, - logicmoduletypes.StoreKey, + wasm.StoreKey, icacontrollertypes.StoreKey, intertxtypes.StoreKey, logicmoduletypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -306,6 +359,10 @@ func New( scopedIBCKeeper := app.CapabilityKeeper.ScopeToModule(ibchost.ModuleName) scopedTransferKeeper := app.CapabilityKeeper.ScopeToModule(ibctransfertypes.ModuleName) scopedICAHostKeeper := app.CapabilityKeeper.ScopeToModule(icahosttypes.SubModuleName) + scopedICAControllerKeeper := app.CapabilityKeeper.ScopeToModule(icacontrollertypes.SubModuleName) + scopedInterTxKeeper := app.CapabilityKeeper.ScopeToModule(intertxtypes.ModuleName) + scopedWasmKeeper := app.CapabilityKeeper.ScopeToModule(wasm.ModuleName) + app.CapabilityKeeper.Seal() // add keepers app.AccountKeeper = authkeeper.NewAccountKeeper( @@ -443,9 +500,28 @@ func New( scopedICAHostKeeper, app.MsgServiceRouter(), ) - icaModule := ica.NewAppModule(nil, &app.ICAHostKeeper) + app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper( + appCodec, + keys[icacontrollertypes.StoreKey], + app.GetSubspace(icacontrollertypes.SubModuleName), + app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee + app.IBCKeeper.ChannelKeeper, + &app.IBCKeeper.PortKeeper, + scopedICAControllerKeeper, + app.MsgServiceRouter(), + ) + icaModule := ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper) icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper) + // For wasmd we use the demo controller from https://github.com/cosmos/interchain-accounts but see notes below + app.InterTxKeeper = intertxkeeper.NewKeeper(appCodec, keys[intertxtypes.StoreKey], app.ICAControllerKeeper, scopedInterTxKeeper) + // Note: please do your research before using this in production app, this is a demo and not an officially + // supported IBC team implementation. Do your own research before using it. + interTxModule := intertx.NewAppModule(appCodec, app.InterTxKeeper) + interTxIBCModule := intertx.NewIBCModule(app.InterTxKeeper) + // You will likely want to swap out the interTxIBCModule with your own reviewed and maintained ica auth module + icaControllerIBCModule := icacontroller.NewIBCMiddleware(interTxIBCModule, app.ICAControllerKeeper) + // Create evidence Keeper for to register the IBC light client misbehaviour evidence route evidenceKeeper := evidencekeeper.NewKeeper( appCodec, @@ -456,6 +532,40 @@ func New( // If evidence needs to be handled for the app, set routes in router here and seal app.EvidenceKeeper = *evidenceKeeper + wasmDir := filepath.Join(homePath, "wasm") + wasmConfig, err := wasm.ReadWasmConfig(appOpts) + if err != nil { + panic(fmt.Sprintf("error while reading wasm config: %s", err)) + } + + var wasmOpts []wasm.Option + if cast.ToBool(appOpts.Get("telemetry.enabled")) { + wasmOpts = append(wasmOpts, wasmkeeper.WithVMCacheMetrics(prometheus.DefaultRegisterer)) + } + + // The last arguments can contain custom message handlers, and custom query handlers, + // if we want to allow any custom callbacks + availableCapabilities := "iterator,staking,stargate,cosmwasm_1_1" + app.WasmKeeper = wasm.NewKeeper( + appCodec, + keys[wasm.StoreKey], + app.GetSubspace(wasm.ModuleName), + app.AccountKeeper, + app.BankKeeper, + app.StakingKeeper, + app.DistrKeeper, + app.IBCKeeper.ChannelKeeper, + &app.IBCKeeper.PortKeeper, + scopedWasmKeeper, + app.TransferKeeper, + app.MsgServiceRouter(), + app.GRPCQueryRouter(), + wasmDir, + wasmConfig, + availableCapabilities, + wasmOpts..., + ) + govRouter := govv1beta1.NewRouter() govRouter. AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler). @@ -463,6 +573,13 @@ func New( AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)). AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper)). AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper)) + + // The gov proposal types can be individually enabled + enabledProposals := GetWasmEnabledProposals() + if len(enabledProposals) != 0 { + govRouter.AddRoute(wasm.RouterKey, wasm.NewWasmProposalHandler(app.WasmKeeper, enabledProposals)) + } + govConfig := govtypes.DefaultConfig() app.GovKeeper = govkeeper.NewKeeper( appCodec, @@ -487,7 +604,10 @@ func New( // Create static IBC router, add transfer route, then set and seal it ibcRouter := ibcporttypes.NewRouter() ibcRouter.AddRoute(icahosttypes.SubModuleName, icaHostIBCModule). - AddRoute(ibctransfertypes.ModuleName, transferIBCModule) + AddRoute(ibctransfertypes.ModuleName, transferIBCModule). + AddRoute(wasm.ModuleName, wasm.NewIBCHandler(app.WasmKeeper, app.IBCKeeper.ChannelKeeper)). + AddRoute(icacontrollertypes.SubModuleName, icaControllerIBCModule). + AddRoute(intertxtypes.ModuleName, icaControllerIBCModule) app.IBCKeeper.SetRouter(ibcRouter) /**** Module Options ****/ @@ -518,11 +638,13 @@ func New( distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), upgrade.NewAppModule(app.UpgradeKeeper), + wasm.NewAppModule(appCodec, &app.WasmKeeper, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), evidence.NewAppModule(app.EvidenceKeeper), ibc.NewAppModule(app.IBCKeeper), params.NewAppModule(app.ParamsKeeper), transferModule, icaModule, + interTxModule, logicModule, ) @@ -552,6 +674,8 @@ func New( group.ModuleName, paramstypes.ModuleName, vestingtypes.ModuleName, + intertxtypes.ModuleName, + wasm.ModuleName, logicmoduletypes.ModuleName, ) @@ -576,6 +700,8 @@ func New( paramstypes.ModuleName, upgradetypes.ModuleName, vestingtypes.ModuleName, + intertxtypes.ModuleName, + wasm.ModuleName, logicmoduletypes.ModuleName, ) @@ -605,6 +731,9 @@ func New( paramstypes.ModuleName, upgradetypes.ModuleName, vestingtypes.ModuleName, + intertxtypes.ModuleName, + // wasm after ibc transfer + wasm.ModuleName, logicmoduletypes.ModuleName, ) @@ -632,6 +761,7 @@ func New( params.NewAppModule(app.ParamsKeeper), groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), evidence.NewAppModule(app.EvidenceKeeper), + wasm.NewAppModule(appCodec, &app.WasmKeeper, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), ibc.NewAppModule(app.IBCKeeper), transferModule, logicModule, @@ -643,17 +773,18 @@ func New( app.MountTransientStores(tkeys) app.MountMemoryStores(memKeys) - // initialize BaseApp - app.SetInitChainer(app.InitChainer) - app.SetBeginBlocker(app.BeginBlocker) - - anteHandler, err := ante.NewAnteHandler( - ante.HandlerOptions{ - AccountKeeper: app.AccountKeeper, - BankKeeper: app.BankKeeper, - SignModeHandler: encodingConfig.TxConfig.SignModeHandler(), - FeegrantKeeper: app.FeeGrantKeeper, - SigGasConsumer: ante.DefaultSigVerificationGasConsumer, + anteHandler, err := NewAnteHandler( + HandlerOptions{ + HandlerOptions: ante.HandlerOptions{ + AccountKeeper: app.AccountKeeper, + BankKeeper: app.BankKeeper, + FeegrantKeeper: app.FeeGrantKeeper, + SignModeHandler: encodingConfig.TxConfig.SignModeHandler(), + SigGasConsumer: ante.DefaultSigVerificationGasConsumer, + }, + IBCKeeper: app.IBCKeeper, + WasmConfig: &wasmConfig, + TXCounterStoreKey: keys[wasm.StoreKey], }, ) if err != nil { @@ -665,14 +796,33 @@ func New( app.SetBeginBlocker(app.BeginBlocker) app.SetEndBlocker(app.EndBlocker) - if loadLatest { - if err := app.LoadLatestVersion(); err != nil { - tmos.Exit(err.Error()) + if manager := app.SnapshotManager(); manager != nil { + err := manager.RegisterExtensions( + wasmkeeper.NewWasmSnapshotter(app.CommitMultiStore(), &app.WasmKeeper), + ) + if err != nil { + panic(fmt.Errorf("failed to register snapshot extension: %w", err)) } } app.ScopedIBCKeeper = scopedIBCKeeper app.ScopedTransferKeeper = scopedTransferKeeper + app.ScopedWasmKeeper = scopedWasmKeeper + app.ScopedICAHostKeeper = scopedICAHostKeeper + app.ScopedICAControllerKeeper = scopedICAControllerKeeper + app.ScopedInterTxKeeper = scopedInterTxKeeper + + if loadLatest { + if err := app.LoadLatestVersion(); err != nil { + tmos.Exit(err.Error()) + } + ctx := app.BaseApp.NewUncachedContext(true, tmproto.Header{}) + + // Initialize pinned codes in wasmvm as they are not persisted there + if err := app.WasmKeeper.InitializePinnedCodes(ctx); err != nil { + tmos.Exit(fmt.Errorf("failed initialize pinned codes %w", err).Error()) + } + } return app } @@ -833,6 +983,8 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino paramsKeeper.Subspace(ibctransfertypes.ModuleName) paramsKeeper.Subspace(ibchost.ModuleName) paramsKeeper.Subspace(icahosttypes.SubModuleName) + paramsKeeper.Subspace(icacontrollertypes.SubModuleName) + paramsKeeper.Subspace(wasm.ModuleName) paramsKeeper.Subspace(logicmoduletypes.ModuleName) return paramsKeeper