diff --git a/app/app.go b/app/app.go index c57adc2b0..059334407 100644 --- a/app/app.go +++ b/app/app.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "path/filepath" + "reflect" "strings" "github.com/CosmWasm/wasmd/x/wasm" @@ -195,7 +196,7 @@ type AxelarApp struct { appCodec codec.Codec interfaceRegistry types.InterfaceRegistry - // necessery keepers for export + // necessary keepers for export stakingKeeper stakingkeeper.Keeper crisisKeeper crisiskeeper.Keeper distrKeeper distrkeeper.Keeper @@ -226,16 +227,18 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) - paramsK := initParamsKeeper(appCodec, encodingConfig.Amino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey]) + keepers := newKeeperCache() + setKeeper(keepers, initParamsKeeper(appCodec, encodingConfig.Amino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])) + // set the BaseApp's parameter store - bApp.SetParamStore(getSubspace(paramsK, bam.Paramspace)) + bApp.SetParamStore(getSubspace(keepers, bam.Paramspace)) // add keepers - accountK := authkeeper.NewAccountKeeper( - appCodec, keys[authtypes.StoreKey], getSubspace(paramsK, authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms, - ) - bankK := bankkeeper.NewBaseKeeper( - appCodec, keys[banktypes.StoreKey], accountK, getSubspace(paramsK, banktypes.ModuleName), + setKeeper(keepers, authkeeper.NewAccountKeeper( + appCodec, keys[authtypes.StoreKey], getSubspace(keepers, authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms, + )) + setKeeper(keepers, bankkeeper.NewBaseKeeper( + appCodec, keys[banktypes.StoreKey], getKeeper[authkeeper.AccountKeeper](keepers), getSubspace(keepers, banktypes.ModuleName), maps.Filter(moduleAccountAddrs(), func(addr string, _ bool) bool { // we do not rely on internal balance tracking for invariance checks in the axelarnet module // (https://github.com/cosmos/cosmos-sdk/issues/12825 for more details on the purpose of the blocked list), @@ -243,70 +246,99 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest // so we exclude this address from the blocked list return addr != authtypes.NewModuleAddress(axelarnetTypes.ModuleName).String() }), - ) + )) + stakingK := stakingkeeper.NewKeeper( - appCodec, keys[stakingtypes.StoreKey], accountK, bankK, getSubspace(paramsK, stakingtypes.ModuleName), + appCodec, keys[stakingtypes.StoreKey], getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers), getSubspace(keepers, stakingtypes.ModuleName), ) - mintK := mintkeeper.NewKeeper( - appCodec, keys[minttypes.StoreKey], getSubspace(paramsK, minttypes.ModuleName), &stakingK, - accountK, bankK, authtypes.FeeCollectorName, - ) - distrK := distrkeeper.NewKeeper( - appCodec, keys[distrtypes.StoreKey], getSubspace(paramsK, distrtypes.ModuleName), accountK, bankK, + setKeeper(keepers, mintkeeper.NewKeeper( + appCodec, keys[minttypes.StoreKey], getSubspace(keepers, minttypes.ModuleName), &stakingK, + getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers), authtypes.FeeCollectorName, + )) + + setKeeper(keepers, distrkeeper.NewKeeper( + appCodec, keys[distrtypes.StoreKey], getSubspace(keepers, distrtypes.ModuleName), getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers), &stakingK, authtypes.FeeCollectorName, moduleAccountAddrs(), - ) - slashingK := slashingkeeper.NewKeeper( - appCodec, keys[slashingtypes.StoreKey], &stakingK, getSubspace(paramsK, slashingtypes.ModuleName), - ) - crisisK := crisiskeeper.NewKeeper( - getSubspace(paramsK, crisistypes.ModuleName), invCheckPeriod, bankK, authtypes.FeeCollectorName, - ) + )) + + setKeeper(keepers, slashingkeeper.NewKeeper( + appCodec, keys[slashingtypes.StoreKey], &stakingK, getSubspace(keepers, slashingtypes.ModuleName), + )) + + setKeeper(keepers, crisiskeeper.NewKeeper( + getSubspace(keepers, crisistypes.ModuleName), invCheckPeriod, getKeeper[bankkeeper.BaseKeeper](keepers), authtypes.FeeCollectorName, + )) + upgradeK := upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, bApp) + semverVersion := bApp.Version() + if !strings.HasPrefix(semverVersion, "v") { + semverVersion = fmt.Sprintf("v%s", semverVersion) + } + upgradeName := semver.MajorMinor(semverVersion) + if upgradeName == "" { + panic(fmt.Errorf("invalid app version %s", bApp.Version())) + } + // todo: change order of commands so this doesn't have to be defined before initialization + var configurator module.Configurator + var mm *module.Manager + upgradeK.SetUpgradeHandler( + upgradeName, + func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + return mm.RunMigrations(ctx, configurator, fromVM) + }, + ) + setKeeper(keepers, upgradeK) + // there is no point in this constructor returning a reference, so we deref it evidenceK := evidencekeeper.NewKeeper( - appCodec, keys[evidencetypes.StoreKey], &stakingK, slashingK, + appCodec, keys[evidencetypes.StoreKey], &stakingK, getKeeper[slashingkeeper.Keeper](keepers), ) + setKeeper(keepers, *evidenceK) - feegrantK := feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], accountK) + setKeeper(keepers, feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], getKeeper[authkeeper.AccountKeeper](keepers))) // register the staking hooks // NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks stakingK = *stakingK.SetHooks( - stakingtypes.NewMultiStakingHooks(distrK.Hooks(), slashingK.Hooks()), + stakingtypes.NewMultiStakingHooks(getKeeper[distrkeeper.Keeper](keepers).Hooks(), getKeeper[slashingkeeper.Keeper](keepers).Hooks()), ) + setKeeper(keepers, stakingK) // add capability keeper and ScopeToModule for ibc module capabilityK := capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey]) + setKeeper(keepers, *capabilityK) // grant capabilities for the ibc and ibc-transfer modules scopedIBCK := capabilityK.ScopeToModule(ibchost.ModuleName) scopedTransferK := capabilityK.ScopeToModule(ibctransfertypes.ModuleName) + capabilityK.Seal() // Create IBC Keeper - ibcKeeper := ibckeeper.NewKeeper( - appCodec, keys[ibchost.StoreKey], getSubspace(paramsK, ibchost.ModuleName), stakingK, upgradeK, scopedIBCK, - ) + setKeeper(keepers, ibckeeper.NewKeeper( + appCodec, keys[ibchost.StoreKey], getSubspace(keepers, ibchost.ModuleName), getKeeper[stakingkeeper.Keeper](keepers), getKeeper[upgradekeeper.Keeper](keepers), scopedIBCK, + )) // Custom axelarnet/evm/nexus keepers - axelarnetK := axelarnetKeeper.NewKeeper( - appCodec, keys[axelarnetTypes.StoreKey], getSubspace(paramsK, axelarnetTypes.ModuleName), ibcKeeper.ChannelKeeper, feegrantK, - ) + setKeeper(keepers, axelarnetKeeper.NewKeeper( + appCodec, keys[axelarnetTypes.StoreKey], getSubspace(keepers, axelarnetTypes.ModuleName), getKeeper[*ibckeeper.Keeper](keepers).ChannelKeeper, getKeeper[feegrantkeeper.Keeper](keepers), + )) - evmK := evmKeeper.NewKeeper( - appCodec, keys[evmTypes.StoreKey], paramsK, - ) + setKeeper(keepers, evmKeeper.NewKeeper( + appCodec, keys[evmTypes.StoreKey], getKeeper[paramskeeper.Keeper](keepers), + )) nexusK := nexusKeeper.NewKeeper( - appCodec, keys[nexusTypes.StoreKey], getSubspace(paramsK, nexusTypes.ModuleName), + appCodec, keys[nexusTypes.StoreKey], getSubspace(keepers, nexusTypes.ModuleName), ) // Setting Router will finalize all routes by sealing router // No more routes can be added nexusRouter := nexusTypes.NewRouter() nexusRouter.AddAddressValidator(evmTypes.ModuleName, evmKeeper.NewAddressValidator()). - AddAddressValidator(axelarnetTypes.ModuleName, axelarnetKeeper.NewAddressValidator(axelarnetK)) + AddAddressValidator(axelarnetTypes.ModuleName, axelarnetKeeper.NewAddressValidator(getKeeper[axelarnetKeeper.Keeper](keepers))) nexusK.SetRouter(nexusRouter) + setKeeper(keepers, nexusK) // IBC Transfer Stack: SendPacket // @@ -316,7 +348,7 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest // After this, the wasm keeper is required to be set on WasmHooks // Create IBC rate limiter - rateLimiter := axelarnet.NewRateLimiter(axelarnetK, ibcKeeper.ChannelKeeper, nexusK) + rateLimiter := axelarnet.NewRateLimiter(getKeeper[axelarnetKeeper.Keeper](keepers), getKeeper[*ibckeeper.Keeper](keepers).ChannelKeeper, getKeeper[nexusKeeper.Keeper](keepers)) var ibcHooksMiddleware ibchooks.ICS4Middleware var ics4Wrapper ibctransfertypes.ICS4Wrapper var wasmHooks ibchooks.WasmHooks @@ -338,25 +370,26 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest } // Create Transfer Keepers - transferKeeper := ibctransferkeeper.NewKeeper( - appCodec, keys[ibctransfertypes.StoreKey], getSubspace(paramsK, ibctransfertypes.ModuleName), + setKeeper(keepers, ibctransferkeeper.NewKeeper( + appCodec, keys[ibctransfertypes.StoreKey], getSubspace(keepers, ibctransfertypes.ModuleName), // Use the IBC middleware stack ics4Wrapper, - ibcKeeper.ChannelKeeper, &ibcKeeper.PortKeeper, - accountK, bankK, scopedTransferK, - ) + getKeeper[*ibckeeper.Keeper](keepers).ChannelKeeper, &getKeeper[*ibckeeper.Keeper](keepers).PortKeeper, + getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers), scopedTransferK, + )) // IBC Transfer Stack: RecvPacket // // Packet originates from core IBC and goes down to app, the flow is the other way // channel.RecvPacket -> axelarnet.OnRecvPacket (transfer, GMP, and rate limit handler) -> ibc_hooks.OnRecvPacket -> transfer.OnRecvPacket - var transferStack porttypes.IBCModule = transfer.NewIBCModule(transferKeeper) + var transferStack porttypes.IBCModule = transfer.NewIBCModule(getKeeper[ibctransferkeeper.Keeper](keepers)) if IsWasmEnabled() { transferStack = ibchooks.NewIBCMiddleware(transferStack, &ibcHooksMiddleware) } - ibcK := axelarnetKeeper.NewIBCKeeper(axelarnetK, transferKeeper, ibcKeeper.ChannelKeeper) - axelarnetModule := axelarnet.NewAppModule(axelarnetK, nexusK, axelarbankkeeper.NewBankKeeper(bankK), accountK, ibcK, transferStack, rateLimiter, logger) + setKeeper(keepers, axelarnetKeeper.NewIBCKeeper(getKeeper[axelarnetKeeper.Keeper](keepers), getKeeper[ibctransferkeeper.Keeper](keepers), getKeeper[*ibckeeper.Keeper](keepers).ChannelKeeper)) + + axelarnetModule := axelarnet.NewAppModule(getKeeper[axelarnetKeeper.Keeper](keepers), getKeeper[nexusKeeper.Keeper](keepers), axelarbankkeeper.NewBankKeeper(getKeeper[bankkeeper.BaseKeeper](keepers)), getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[axelarnetKeeper.IBCKeeper](keepers), transferStack, rateLimiter, logger) // Create static IBC router, add axelarnet module as the IBC transfer route, and seal it ibcRouter := porttypes.NewRouter() @@ -364,31 +397,40 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest // axelar custom keepers // axelarnet / evm / nexus keepers created above - rewardK := rewardKeeper.NewKeeper( - appCodec, keys[rewardTypes.StoreKey], getSubspace(paramsK, rewardTypes.ModuleName), axelarbankkeeper.NewBankKeeper(bankK), distrK, stakingK, - ) + setKeeper(keepers, rewardKeeper.NewKeeper( + appCodec, keys[rewardTypes.StoreKey], getSubspace(keepers, rewardTypes.ModuleName), axelarbankkeeper.NewBankKeeper(getKeeper[bankkeeper.BaseKeeper](keepers)), getKeeper[distrkeeper.Keeper](keepers), getKeeper[stakingkeeper.Keeper](keepers), + )) multisigK := multisigKeeper.NewKeeper( - appCodec, keys[multisigTypes.StoreKey], getSubspace(paramsK, multisigTypes.ModuleName), + appCodec, keys[multisigTypes.StoreKey], getSubspace(keepers, multisigTypes.ModuleName), ) multisigRouter := multisigTypes.NewSigRouter() - multisigRouter.AddHandler(evmTypes.ModuleName, evmKeeper.NewSigHandler(appCodec, evmK)) + multisigRouter.AddHandler(evmTypes.ModuleName, evmKeeper.NewSigHandler(appCodec, getKeeper[*evmKeeper.BaseKeeper](keepers))) multisigK.SetSigRouter(multisigRouter) + setKeeper(keepers, multisigK) - tssK := tssKeeper.NewKeeper( - appCodec, keys[tssTypes.StoreKey], getSubspace(paramsK, tssTypes.ModuleName), - ) - snapK := snapKeeper.NewKeeper( - appCodec, keys[snapTypes.StoreKey], getSubspace(paramsK, snapTypes.ModuleName), stakingK, axelarbankkeeper.NewBankKeeper(bankK), - slashingK, - ) - votingK := voteKeeper.NewKeeper( - appCodec, keys[voteTypes.StoreKey], getSubspace(paramsK, voteTypes.ModuleName), snapK, stakingK, rewardK, - ) - permissionK := permissionKeeper.NewKeeper( - appCodec, keys[permissionTypes.StoreKey], getSubspace(paramsK, permissionTypes.ModuleName), + setKeeper(keepers, tssKeeper.NewKeeper( + appCodec, keys[tssTypes.StoreKey], getSubspace(keepers, tssTypes.ModuleName), + )) + + setKeeper(keepers, snapKeeper.NewKeeper( + appCodec, keys[snapTypes.StoreKey], getSubspace(keepers, snapTypes.ModuleName), getKeeper[stakingkeeper.Keeper](keepers), axelarbankkeeper.NewBankKeeper(getKeeper[bankkeeper.BaseKeeper](keepers)), + getKeeper[slashingkeeper.Keeper](keepers), + )) + + voteK := voteKeeper.NewKeeper( + appCodec, keys[voteTypes.StoreKey], getSubspace(keepers, voteTypes.ModuleName), getKeeper[snapKeeper.Keeper](keepers), getKeeper[stakingkeeper.Keeper](keepers), getKeeper[rewardKeeper.Keeper](keepers), ) + voteRouter := voteTypes.NewRouter() + voteRouter.AddHandler(evmTypes.ModuleName, evmKeeper.NewVoteHandler(appCodec, getKeeper[*evmKeeper.BaseKeeper](keepers), getKeeper[nexusKeeper.Keeper](keepers), getKeeper[rewardKeeper.Keeper](keepers))) + (&voteK).SetVoteRouter(voteRouter) + setKeeper(keepers, voteK) + + setKeeper(keepers, permissionKeeper.NewKeeper( + appCodec, keys[permissionTypes.StoreKey], getSubspace(keepers, permissionTypes.ModuleName), + )) + var wasmK wasm.Keeper var wasmAnteDecorators []sdk.AnteDecorator @@ -403,21 +445,21 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest // The last arguments can contain custom message handlers, and custom query handlers, // if we want to allow any custom callbacks wasmOpts = append(wasmOpts, wasmkeeper.WithMessageHandlerDecorator(func(old wasmkeeper.Messenger) wasmkeeper.Messenger { - return wasmkeeper.NewMessageHandlerChain(old, nexusKeeper.NewMessenger(nexusK)) + return wasmkeeper.NewMessageHandlerChain(old, nexusKeeper.NewMessenger(getKeeper[nexusKeeper.Keeper](keepers))) })) wasmK = wasm.NewKeeper( appCodec, keys[wasm.StoreKey], - getSubspace(paramsK, wasm.ModuleName), - accountK, - bankK, - stakingK, - distrK, - ibcKeeper.ChannelKeeper, - ibcKeeper.ChannelKeeper, - &ibcKeeper.PortKeeper, + getSubspace(keepers, wasm.ModuleName), + getKeeper[authkeeper.AccountKeeper](keepers), + getKeeper[bankkeeper.BaseKeeper](keepers), + getKeeper[stakingkeeper.Keeper](keepers), + getKeeper[distrkeeper.Keeper](keepers), + getKeeper[*ibckeeper.Keeper](keepers).ChannelKeeper, + getKeeper[*ibckeeper.Keeper](keepers).ChannelKeeper, + &getKeeper[*ibckeeper.Keeper](keepers).PortKeeper, scopedWasmK, - transferKeeper, + getKeeper[ibctransferkeeper.Keeper](keepers), bApp.MsgServiceRouter(), bApp.GRPCQueryRouter(), wasmDir, @@ -432,61 +474,44 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest } // Create wasm ibc stack - var wasmStack porttypes.IBCModule = wasm.NewIBCHandler(wasmK, ibcKeeper.ChannelKeeper, ibcKeeper.ChannelKeeper) + var wasmStack porttypes.IBCModule = wasm.NewIBCHandler(wasmK, getKeeper[*ibckeeper.Keeper](keepers).ChannelKeeper, getKeeper[*ibckeeper.Keeper](keepers).ChannelKeeper) ibcRouter.AddRoute(wasm.ModuleName, wasmStack) // set the contract keeper for the Ics20WasmHooks wasmHooks.ContractKeeper = wasmkeeper.NewDefaultPermissionKeeper(wasmK) + + setKeeper(keepers, wasmK) } // Finalize the IBC router - ibcKeeper.SetRouter(ibcRouter) + getKeeper[*ibckeeper.Keeper](keepers).SetRouter(ibcRouter) // Add governance proposal hooks govRouter := govtypes.NewRouter() govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). - AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(paramsK)). - AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(distrK)). - AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(upgradeK)). - AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(ibcKeeper.ClientKeeper)). - AddRoute(axelarnetTypes.RouterKey, axelarnet.NewProposalHandler(axelarnetK, nexusK, accountK)) + AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(getKeeper[paramskeeper.Keeper](keepers))). + AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(getKeeper[distrkeeper.Keeper](keepers))). + AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(getKeeper[upgradekeeper.Keeper](keepers))). + AddRoute(ibcclienttypes.RouterKey, ibcclient.NewClientProposalHandler(getKeeper[*ibckeeper.Keeper](keepers).ClientKeeper)). + AddRoute(axelarnetTypes.RouterKey, axelarnet.NewProposalHandler(getKeeper[axelarnetKeeper.Keeper](keepers), getKeeper[nexusKeeper.Keeper](keepers), getKeeper[authkeeper.AccountKeeper](keepers))) if IsWasmEnabled() { - govRouter.AddRoute(wasm.RouterKey, wasm.NewWasmProposalHandler(wasmK, wasm.EnableAllProposals)) + govRouter.AddRoute(wasm.RouterKey, wasm.NewWasmProposalHandler(getKeeper[wasm.Keeper](keepers), wasm.EnableAllProposals)) } govK := govkeeper.NewKeeper( - appCodec, keys[govtypes.StoreKey], getSubspace(paramsK, govtypes.ModuleName), accountK, bankK, - &stakingK, govRouter, + appCodec, keys[govtypes.StoreKey], getSubspace(keepers, govtypes.ModuleName), getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers), + getKeeper[stakingkeeper.Keeper](keepers), govRouter, ) - govK.SetHooks(govtypes.NewMultiGovHooks(axelarnetK.Hooks(nexusK, govK))) + govK.SetHooks(govtypes.NewMultiGovHooks(getKeeper[axelarnetKeeper.Keeper](keepers).Hooks(getKeeper[nexusKeeper.Keeper](keepers), govK))) + setKeeper(keepers, govK) - semverVersion := bApp.Version() - if !strings.HasPrefix(semverVersion, "v") { - semverVersion = fmt.Sprintf("v%s", semverVersion) - } - - upgradeName := semver.MajorMinor(semverVersion) - if upgradeName == "" { - panic(fmt.Errorf("invalid app version %s", bApp.Version())) - } - - // todo: change order of commands so this doesn't have to be defined before initialization - var configurator module.Configurator - var mm *module.Manager - upgradeK.SetUpgradeHandler( - upgradeName, - func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { - return mm.RunMigrations(ctx, configurator, fromVM) - }, - ) - - upgradeInfo, err := upgradeK.ReadUpgradeInfoFromDisk() + upgradeInfo, err := getKeeper[upgradekeeper.Keeper](keepers).ReadUpgradeInfoFromDisk() if err != nil { panic(err) } - if upgradeInfo.Name == upgradeName && !upgradeK.IsSkipHeight(upgradeInfo.Height) { + if upgradeInfo.Name == upgradeName && !getKeeper[upgradekeeper.Keeper](keepers).IsSkipHeight(upgradeInfo.Height) { storeUpgrades := store.StoreUpgrades{} if IsWasmEnabled() { @@ -498,57 +523,55 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bApp.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &storeUpgrades)) } - voteRouter := voteTypes.NewRouter() - voteRouter.AddHandler(evmTypes.ModuleName, evmKeeper.NewVoteHandler(appCodec, evmK, nexusK, rewardK)) - votingK.SetVoteRouter(voteRouter) - /**** Module Options ****/ // NOTE: we may consider parsing `appOpts` inside module constructors. For the moment // we prefer to be more strict in what arguments the modules expect. var skipGenesisInvariants = cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants)) + crisisK := getKeeper[crisiskeeper.Keeper](keepers) appModules := []module.AppModule{ - genutil.NewAppModule(accountK, stakingK, bApp.DeliverTx, encodingConfig.TxConfig), - auth.NewAppModule(appCodec, accountK, nil), - vesting.NewAppModule(accountK, bankK), - bank.NewAppModule(appCodec, bankK, accountK), + genutil.NewAppModule(getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[stakingkeeper.Keeper](keepers), bApp.DeliverTx, encodingConfig.TxConfig), + auth.NewAppModule(appCodec, getKeeper[authkeeper.AccountKeeper](keepers), nil), + vesting.NewAppModule(getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers)), + bank.NewAppModule(appCodec, getKeeper[bankkeeper.BaseKeeper](keepers), getKeeper[authkeeper.AccountKeeper](keepers)), crisis.NewAppModule(&crisisK, skipGenesisInvariants), - gov.NewAppModule(appCodec, govK, accountK, bankK), - mint.NewAppModule(appCodec, mintK, accountK), - slashing.NewAppModule(appCodec, slashingK, accountK, bankK, stakingK), - distr.NewAppModule(appCodec, distrK, accountK, bankK, stakingK), - staking.NewAppModule(appCodec, stakingK, accountK, bankK), - upgrade.NewAppModule(upgradeK), - evidence.NewAppModule(*evidenceK), - params.NewAppModule(paramsK), + gov.NewAppModule(appCodec, getKeeper[govkeeper.Keeper](keepers), getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers)), + mint.NewAppModule(appCodec, getKeeper[mintkeeper.Keeper](keepers), getKeeper[authkeeper.AccountKeeper](keepers)), + slashing.NewAppModule(appCodec, getKeeper[slashingkeeper.Keeper](keepers), getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers), getKeeper[stakingkeeper.Keeper](keepers)), + distr.NewAppModule(appCodec, getKeeper[distrkeeper.Keeper](keepers), getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers), getKeeper[stakingkeeper.Keeper](keepers)), + staking.NewAppModule(appCodec, getKeeper[stakingkeeper.Keeper](keepers), getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers)), + upgrade.NewAppModule(getKeeper[upgradekeeper.Keeper](keepers)), + evidence.NewAppModule(getKeeper[evidencekeeper.Keeper](keepers)), + params.NewAppModule(getKeeper[paramskeeper.Keeper](keepers)), capability.NewAppModule(appCodec, *capabilityK), } // wasm module needs to be added in a specific order if IsWasmEnabled() { + wasmK := getKeeper[wasm.Keeper](keepers) appModules = append( appModules, - wasm.NewAppModule(appCodec, &wasmK, stakingK, accountK, bankK), - ibchooks.NewAppModule(accountK), + wasm.NewAppModule(appCodec, &wasmK, getKeeper[stakingkeeper.Keeper](keepers), getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers)), + ibchooks.NewAppModule(getKeeper[authkeeper.AccountKeeper](keepers)), ) } appModules = append(appModules, []module.AppModule{ - evidence.NewAppModule(*evidenceK), - ibc.NewAppModule(ibcKeeper), - transfer.NewAppModule(transferKeeper), - feegrantmodule.NewAppModule(appCodec, accountK, bankK, feegrantK, interfaceRegistry), - - snapshot.NewAppModule(snapK), - multisig.NewAppModule(multisigK, stakingK, slashingK, snapK, rewardK, nexusK), - tss.NewAppModule(tssK, snapK, nexusK, stakingK, multisigK), - vote.NewAppModule(votingK), - nexus.NewAppModule(nexusK, snapK, slashingK, stakingK, axelarnetK, rewardK), - evm.NewAppModule(evmK, votingK, nexusK, snapK, stakingK, slashingK, multisigK), + evidence.NewAppModule(getKeeper[evidencekeeper.Keeper](keepers)), + ibc.NewAppModule(getKeeper[*ibckeeper.Keeper](keepers)), + transfer.NewAppModule(getKeeper[ibctransferkeeper.Keeper](keepers)), + feegrantmodule.NewAppModule(appCodec, getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers), getKeeper[feegrantkeeper.Keeper](keepers), interfaceRegistry), + + snapshot.NewAppModule(getKeeper[snapKeeper.Keeper](keepers)), + multisig.NewAppModule(getKeeper[multisigKeeper.Keeper](keepers), getKeeper[stakingkeeper.Keeper](keepers), getKeeper[slashingkeeper.Keeper](keepers), getKeeper[snapKeeper.Keeper](keepers), getKeeper[rewardKeeper.Keeper](keepers), getKeeper[nexusKeeper.Keeper](keepers)), + tss.NewAppModule(getKeeper[tssKeeper.Keeper](keepers), getKeeper[snapKeeper.Keeper](keepers), getKeeper[nexusKeeper.Keeper](keepers), getKeeper[stakingkeeper.Keeper](keepers), getKeeper[multisigKeeper.Keeper](keepers)), + vote.NewAppModule(getKeeper[voteKeeper.Keeper](keepers)), + nexus.NewAppModule(getKeeper[nexusKeeper.Keeper](keepers), getKeeper[snapKeeper.Keeper](keepers), getKeeper[slashingkeeper.Keeper](keepers), getKeeper[stakingkeeper.Keeper](keepers), getKeeper[axelarnetKeeper.Keeper](keepers), getKeeper[rewardKeeper.Keeper](keepers)), + evm.NewAppModule(getKeeper[*evmKeeper.BaseKeeper](keepers), getKeeper[voteKeeper.Keeper](keepers), getKeeper[nexusKeeper.Keeper](keepers), getKeeper[snapKeeper.Keeper](keepers), getKeeper[stakingkeeper.Keeper](keepers), getKeeper[slashingkeeper.Keeper](keepers), getKeeper[multisigKeeper.Keeper](keepers)), axelarnetModule, - reward.NewAppModule(rewardK, nexusK, mintK, stakingK, slashingK, multisigK, snapK, bankK, bApp.MsgServiceRouter(), bApp.Router()), - permission.NewAppModule(permissionK), + reward.NewAppModule(getKeeper[rewardKeeper.Keeper](keepers), getKeeper[nexusKeeper.Keeper](keepers), getKeeper[mintkeeper.Keeper](keepers), getKeeper[stakingkeeper.Keeper](keepers), getKeeper[slashingkeeper.Keeper](keepers), getKeeper[multisigKeeper.Keeper](keepers), getKeeper[snapKeeper.Keeper](keepers), getKeeper[bankkeeper.BaseKeeper](keepers), bApp.MsgServiceRouter(), bApp.Router()), + permission.NewAppModule(getKeeper[permissionKeeper.Keeper](keepers)), }...) var app = &AxelarApp{ @@ -556,7 +579,7 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest appCodec: appCodec, interfaceRegistry: interfaceRegistry, keys: keys, - upgradeKeeper: upgradeK, + upgradeKeeper: getKeeper[upgradekeeper.Keeper](keepers), } mm = module.NewManager( @@ -589,10 +612,10 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest // The baseAnteHandler handles signature verification and transaction pre-processing baseAnteHandler, err := authAnte.NewAnteHandler( authAnte.HandlerOptions{ - AccountKeeper: accountK, - BankKeeper: bankK, + AccountKeeper: getKeeper[authkeeper.AccountKeeper](keepers), + BankKeeper: getKeeper[bankkeeper.BaseKeeper](keepers), SignModeHandler: encodingConfig.TxConfig.SignModeHandler(), - FeegrantKeeper: feegrantK, + FeegrantKeeper: getKeeper[feegrantkeeper.Keeper](keepers), SigGasConsumer: authAnte.DefaultSigVerificationGasConsumer, }, ) @@ -611,12 +634,12 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest anteDecorators = append(anteDecorators, ante.NewLogMsgDecorator(appCodec), - ante.NewCheckCommissionRate(stakingK), - ante.NewUndelegateDecorator(multisigK, nexusK, snapK), - ante.NewCheckRefundFeeDecorator(app.interfaceRegistry, accountK, stakingK, snapK, rewardK), - ante.NewCheckProxy(snapK), - ante.NewRestrictedTx(permissionK), - ibcante.NewAnteDecorator(ibcKeeper), + ante.NewCheckCommissionRate(getKeeper[stakingkeeper.Keeper](keepers)), + ante.NewUndelegateDecorator(getKeeper[multisigKeeper.Keeper](keepers), getKeeper[nexusKeeper.Keeper](keepers), getKeeper[snapKeeper.Keeper](keepers)), + ante.NewCheckRefundFeeDecorator(app.interfaceRegistry, getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[stakingkeeper.Keeper](keepers), getKeeper[snapKeeper.Keeper](keepers), getKeeper[rewardKeeper.Keeper](keepers)), + ante.NewCheckProxy(getKeeper[snapKeeper.Keeper](keepers)), + ante.NewRestrictedTx(getKeeper[permissionKeeper.Keeper](keepers)), + ibcante.NewAnteDecorator(getKeeper[*ibckeeper.Keeper](keepers)), ) anteHandler := sdk.ChainAnteDecorators( @@ -633,7 +656,7 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest ctx := app.BaseApp.NewUncachedContext(true, tmproto.Header{}) // Initialize pinned codes in wasmvm as they are not persisted there - if err := wasmK.InitializePinnedCodes(ctx); err != nil { + if err := getKeeper[wasm.Keeper](keepers).InitializePinnedCodes(ctx); err != nil { tmos.Exit(fmt.Sprintf("failed initialize pinned codes %s", err)) } } @@ -643,7 +666,7 @@ func NewAxelarApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest // we need to ensure that all chain subspaces are loaded at start-up to prevent unexpected consensus failures // when the params keeper is used outside the evm module's context - evmK.InitChains(app.NewContext(true, tmproto.Header{})) + getKeeper[*evmKeeper.BaseKeeper](keepers).InitChains(app.NewContext(true, tmproto.Header{})) return app } @@ -1037,11 +1060,50 @@ func GetModuleBasics() module.BasicManager { return ModuleBasics } -func getSubspace(keeper paramskeeper.Keeper, moduleName string) paramstypes.Subspace { - subspace, _ := keeper.GetSubspace(moduleName) +type keeperCache struct { + repository map[string]any +} + +func newKeeperCache() *keeperCache { + return &keeperCache{ + repository: make(map[string]any), + } +} + +func getSubspace(k *keeperCache, moduleName string) paramstypes.Subspace { + paramsK := getKeeper[paramskeeper.Keeper](k) + subspace, ok := paramsK.GetSubspace(moduleName) + if !ok { + panic(fmt.Sprintf("subspace %s not found", moduleName)) + } return subspace } +func getKeeper[T any](k *keeperCache) T { + key := fullTypeName[T]() + keeper, ok := k.repository[key].(T) + if !ok { + panic(fmt.Sprintf("keeper %s not found", key)) + } + return keeper +} + +func setKeeper[T any](k *keeperCache, keeper T) { + k.repository[fullTypeName[T]()] = keeper +} + +func fullTypeName[T any]() string { + keeperType := reflect.TypeOf(*new(T)) + + var prefix string + if keeperType.Kind() == reflect.Ptr { + prefix = "*" + keeperType = keeperType.Elem() + } + + return prefix + keeperType.PkgPath() + "." + keeperType.Name() +} + // IsWasmEnabled returns whether wasm is enabled func IsWasmEnabled() bool { return WasmEnabled != ""