## Description Ref: #9438 This PR performs the major work of swapping out the v1beta1 msg server and query server for the new one which can process a proposal as an array of messages. This PR still retains the legacy servers which simply wrap around the new ones, providing the same interface as before. In order to keep backwards compatibility, a new msg, `MsgExecLegacyContent` has been created which allows `Content` to become a `Msg` type and still be used as part of the new implementation. --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
625 lines
26 KiB
Go
625 lines
26 KiB
Go
package simapp
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/gorilla/mux"
|
|
"github.com/rakyll/statik/fs"
|
|
"github.com/spf13/cast"
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
"github.com/tendermint/tendermint/libs/log"
|
|
tmos "github.com/tendermint/tendermint/libs/os"
|
|
dbm "github.com/tendermint/tm-db"
|
|
|
|
"github.com/cosmos/cosmos-sdk/baseapp"
|
|
"github.com/cosmos/cosmos-sdk/client"
|
|
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
"github.com/cosmos/cosmos-sdk/codec/types"
|
|
"github.com/cosmos/cosmos-sdk/server"
|
|
"github.com/cosmos/cosmos-sdk/server/api"
|
|
"github.com/cosmos/cosmos-sdk/server/config"
|
|
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
|
simappparams "github.com/cosmos/cosmos-sdk/simapp/params"
|
|
"github.com/cosmos/cosmos-sdk/store/streaming"
|
|
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
|
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
"github.com/cosmos/cosmos-sdk/types/module"
|
|
"github.com/cosmos/cosmos-sdk/version"
|
|
"github.com/cosmos/cosmos-sdk/x/auth"
|
|
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
|
authmiddleware "github.com/cosmos/cosmos-sdk/x/auth/middleware"
|
|
authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation"
|
|
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
|
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
|
|
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
|
|
"github.com/cosmos/cosmos-sdk/x/authz"
|
|
authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
|
|
authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module"
|
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
|
bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
|
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
|
"github.com/cosmos/cosmos-sdk/x/capability"
|
|
capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
|
|
capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types"
|
|
"github.com/cosmos/cosmos-sdk/x/crisis"
|
|
crisiskeeper "github.com/cosmos/cosmos-sdk/x/crisis/keeper"
|
|
crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types"
|
|
distr "github.com/cosmos/cosmos-sdk/x/distribution"
|
|
distrclient "github.com/cosmos/cosmos-sdk/x/distribution/client"
|
|
distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper"
|
|
distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types"
|
|
"github.com/cosmos/cosmos-sdk/x/evidence"
|
|
evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper"
|
|
evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
|
|
"github.com/cosmos/cosmos-sdk/x/feegrant"
|
|
feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper"
|
|
feegrantmodule "github.com/cosmos/cosmos-sdk/x/feegrant/module"
|
|
"github.com/cosmos/cosmos-sdk/x/genutil"
|
|
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
|
"github.com/cosmos/cosmos-sdk/x/gov"
|
|
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
|
|
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
|
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
|
|
govv1beta2 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta2"
|
|
"github.com/cosmos/cosmos-sdk/x/group"
|
|
groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper"
|
|
groupmodule "github.com/cosmos/cosmos-sdk/x/group/module"
|
|
"github.com/cosmos/cosmos-sdk/x/mint"
|
|
mintkeeper "github.com/cosmos/cosmos-sdk/x/mint/keeper"
|
|
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
|
|
"github.com/cosmos/cosmos-sdk/x/nft"
|
|
nftkeeper "github.com/cosmos/cosmos-sdk/x/nft/keeper"
|
|
nftmodule "github.com/cosmos/cosmos-sdk/x/nft/module"
|
|
"github.com/cosmos/cosmos-sdk/x/params"
|
|
paramsclient "github.com/cosmos/cosmos-sdk/x/params/client"
|
|
paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper"
|
|
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
|
|
paramproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal"
|
|
"github.com/cosmos/cosmos-sdk/x/slashing"
|
|
slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
|
|
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
|
|
"github.com/cosmos/cosmos-sdk/x/staking"
|
|
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
|
"github.com/cosmos/cosmos-sdk/x/upgrade"
|
|
upgradeclient "github.com/cosmos/cosmos-sdk/x/upgrade/client"
|
|
upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
|
|
upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
|
|
|
// unnamed import of statik for swagger UI support
|
|
_ "github.com/cosmos/cosmos-sdk/client/docs/statik"
|
|
)
|
|
|
|
const appName = "SimApp"
|
|
|
|
var (
|
|
// DefaultNodeHome default home directories for the application daemon
|
|
DefaultNodeHome string
|
|
|
|
// ModuleBasics defines the module BasicManager is in charge of setting up basic,
|
|
// non-dependant module elements, such as codec registration
|
|
// and genesis verification.
|
|
ModuleBasics = module.NewBasicManager(
|
|
auth.AppModuleBasic{},
|
|
genutil.AppModuleBasic{},
|
|
bank.AppModuleBasic{},
|
|
capability.AppModuleBasic{},
|
|
staking.AppModuleBasic{},
|
|
mint.AppModuleBasic{},
|
|
distr.AppModuleBasic{},
|
|
gov.NewAppModuleBasic(
|
|
paramsclient.ProposalHandler, distrclient.ProposalHandler, upgradeclient.ProposalHandler, upgradeclient.CancelProposalHandler,
|
|
),
|
|
params.AppModuleBasic{},
|
|
crisis.AppModuleBasic{},
|
|
slashing.AppModuleBasic{},
|
|
feegrantmodule.AppModuleBasic{},
|
|
upgrade.AppModuleBasic{},
|
|
evidence.AppModuleBasic{},
|
|
authzmodule.AppModuleBasic{},
|
|
groupmodule.AppModuleBasic{},
|
|
vesting.AppModuleBasic{},
|
|
nftmodule.AppModuleBasic{},
|
|
)
|
|
|
|
// module account permissions
|
|
maccPerms = map[string][]string{
|
|
authtypes.FeeCollectorName: nil,
|
|
distrtypes.ModuleName: nil,
|
|
minttypes.ModuleName: {authtypes.Minter},
|
|
stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking},
|
|
stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking},
|
|
govtypes.ModuleName: {authtypes.Burner},
|
|
nft.ModuleName: nil,
|
|
}
|
|
)
|
|
|
|
var (
|
|
_ App = (*SimApp)(nil)
|
|
_ servertypes.Application = (*SimApp)(nil)
|
|
)
|
|
|
|
// SimApp 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.
|
|
type SimApp struct {
|
|
*baseapp.BaseApp
|
|
legacyAmino *codec.LegacyAmino
|
|
appCodec codec.Codec
|
|
interfaceRegistry types.InterfaceRegistry
|
|
msgSvcRouter *authmiddleware.MsgServiceRouter
|
|
legacyRouter sdk.Router
|
|
|
|
invCheckPeriod uint
|
|
|
|
// keys to access the substores
|
|
keys map[string]*storetypes.KVStoreKey
|
|
tkeys map[string]*storetypes.TransientStoreKey
|
|
memKeys map[string]*storetypes.MemoryStoreKey
|
|
|
|
// keepers
|
|
AccountKeeper authkeeper.AccountKeeper
|
|
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
|
|
AuthzKeeper authzkeeper.Keeper
|
|
EvidenceKeeper evidencekeeper.Keeper
|
|
FeeGrantKeeper feegrantkeeper.Keeper
|
|
GroupKeeper groupkeeper.Keeper
|
|
NFTKeeper nftkeeper.Keeper
|
|
|
|
// the module manager
|
|
mm *module.Manager
|
|
|
|
// simulation manager
|
|
sm *module.SimulationManager
|
|
|
|
// module configurator
|
|
configurator module.Configurator
|
|
}
|
|
|
|
func init() {
|
|
userHomeDir, err := os.UserHomeDir()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
DefaultNodeHome = filepath.Join(userHomeDir, ".simapp")
|
|
}
|
|
|
|
// NewSimApp returns a reference to an initialized SimApp.
|
|
func NewSimApp(
|
|
logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, skipUpgradeHeights map[int64]bool,
|
|
homePath string, invCheckPeriod uint, encodingConfig simappparams.EncodingConfig,
|
|
appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp),
|
|
) *SimApp {
|
|
|
|
appCodec := encodingConfig.Codec
|
|
legacyAmino := encodingConfig.Amino
|
|
interfaceRegistry := encodingConfig.InterfaceRegistry
|
|
|
|
bApp := baseapp.NewBaseApp(appName, logger, db, baseAppOptions...)
|
|
bApp.SetCommitMultiStoreTracer(traceStore)
|
|
bApp.SetVersion(version.Version)
|
|
bApp.SetInterfaceRegistry(interfaceRegistry)
|
|
|
|
keys := sdk.NewKVStoreKeys(
|
|
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey,
|
|
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
|
|
govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey,
|
|
evidencetypes.StoreKey, capabilitytypes.StoreKey,
|
|
authzkeeper.StoreKey, nftkeeper.StoreKey, group.StoreKey,
|
|
)
|
|
tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey)
|
|
// NOTE: The testingkey is just mounted for testing purposes. Actual applications should
|
|
// not include this key.
|
|
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey, "testingkey")
|
|
|
|
// configure state listening capabilities using AppOptions
|
|
// we are doing nothing with the returned streamingServices and waitGroup in this case
|
|
if _, _, err := streaming.LoadStreamingServices(bApp, appOpts, appCodec, keys); err != nil {
|
|
tmos.Exit(err.Error())
|
|
}
|
|
|
|
app := &SimApp{
|
|
BaseApp: bApp,
|
|
legacyAmino: legacyAmino,
|
|
appCodec: appCodec,
|
|
interfaceRegistry: interfaceRegistry,
|
|
legacyRouter: authmiddleware.NewLegacyRouter(),
|
|
msgSvcRouter: authmiddleware.NewMsgServiceRouter(interfaceRegistry),
|
|
invCheckPeriod: invCheckPeriod,
|
|
keys: keys,
|
|
tkeys: tkeys,
|
|
memKeys: memKeys,
|
|
}
|
|
|
|
app.ParamsKeeper = initParamsKeeper(appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
|
|
|
|
// set the BaseApp's parameter store
|
|
bApp.SetParamStore(app.ParamsKeeper.Subspace(baseapp.Paramspace).WithKeyTable(paramstypes.ConsensusParamsKeyTable()))
|
|
|
|
app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
|
|
// Applications that wish to enforce statically created ScopedKeepers should call `Seal` after creating
|
|
// their scoped modules in `NewApp` with `ScopeToModule`
|
|
app.CapabilityKeeper.Seal()
|
|
|
|
// add keepers
|
|
app.AccountKeeper = authkeeper.NewAccountKeeper(
|
|
appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms, sdk.Bech32MainPrefix,
|
|
)
|
|
app.BankKeeper = bankkeeper.NewBaseKeeper(
|
|
appCodec, keys[banktypes.StoreKey], app.AccountKeeper, app.GetSubspace(banktypes.ModuleName), app.ModuleAccountAddrs(),
|
|
)
|
|
stakingKeeper := stakingkeeper.NewKeeper(
|
|
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName),
|
|
)
|
|
app.MintKeeper = mintkeeper.NewKeeper(
|
|
appCodec, keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &stakingKeeper,
|
|
app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName,
|
|
)
|
|
app.DistrKeeper = distrkeeper.NewKeeper(
|
|
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
|
&stakingKeeper, authtypes.FeeCollectorName,
|
|
)
|
|
app.SlashingKeeper = slashingkeeper.NewKeeper(
|
|
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
|
|
)
|
|
app.CrisisKeeper = crisiskeeper.NewKeeper(
|
|
app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName,
|
|
)
|
|
|
|
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
|
|
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp)
|
|
|
|
// register the staking hooks
|
|
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
|
|
app.StakingKeeper = *stakingKeeper.SetHooks(
|
|
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
|
|
)
|
|
|
|
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.msgSvcRouter, app.AccountKeeper)
|
|
|
|
app.GroupKeeper = groupkeeper.NewKeeper(keys[group.StoreKey], appCodec, app.msgSvcRouter, app.AccountKeeper)
|
|
|
|
// register the proposal types
|
|
govRouter := govv1beta1.NewRouter()
|
|
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
|
|
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
|
|
AddRoute(distrtypes.RouterKey, distr.NewCommunityPoolSpendProposalHandler(app.DistrKeeper)).
|
|
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
|
|
govKeeper := govkeeper.NewKeeper(
|
|
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
|
|
&stakingKeeper, govRouter, app.msgSvcRouter,
|
|
)
|
|
|
|
app.GovKeeper = *govKeeper.SetHooks(
|
|
govtypes.NewMultiGovHooks(
|
|
// register the governance hooks
|
|
),
|
|
)
|
|
app.NFTKeeper = nftkeeper.NewKeeper(keys[nftkeeper.StoreKey], appCodec, app.AccountKeeper, app.BankKeeper)
|
|
|
|
// create evidence keeper with router
|
|
evidenceKeeper := evidencekeeper.NewKeeper(
|
|
appCodec, keys[evidencetypes.StoreKey], &app.StakingKeeper, app.SlashingKeeper,
|
|
)
|
|
// If evidence needs to be handled for the app, set routes in router here and seal
|
|
app.EvidenceKeeper = *evidenceKeeper
|
|
|
|
/**** 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))
|
|
|
|
// NOTE: Any module instantiated in the module manager that is later modified
|
|
// must be passed by reference here.
|
|
app.mm = module.NewManager(
|
|
genutil.NewAppModule(
|
|
app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx,
|
|
encodingConfig.TxConfig,
|
|
),
|
|
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
|
|
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
|
|
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
|
|
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
|
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
|
|
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
|
|
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
|
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
|
|
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
|
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
|
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
|
upgrade.NewAppModule(app.UpgradeKeeper),
|
|
evidence.NewAppModule(app.EvidenceKeeper),
|
|
params.NewAppModule(app.ParamsKeeper),
|
|
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
|
|
groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
|
|
nftmodule.NewAppModule(appCodec, app.NFTKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
|
|
)
|
|
|
|
// During begin block slashing happens after distr.BeginBlocker so that
|
|
// there is nothing left over in the validator fee pool, so as to keep the
|
|
// CanWithdrawInvariant invariant.
|
|
// NOTE: staking module is required if HistoricalEntries param > 0
|
|
// NOTE: capability module's beginblocker must come before any modules using capabilities (e.g. IBC)
|
|
app.mm.SetOrderBeginBlockers(
|
|
upgradetypes.ModuleName, capabilitytypes.ModuleName, minttypes.ModuleName, distrtypes.ModuleName, slashingtypes.ModuleName,
|
|
evidencetypes.ModuleName, stakingtypes.ModuleName,
|
|
authtypes.ModuleName, banktypes.ModuleName, govtypes.ModuleName, crisistypes.ModuleName, genutiltypes.ModuleName,
|
|
authz.ModuleName, feegrant.ModuleName, nft.ModuleName, group.ModuleName,
|
|
paramstypes.ModuleName, vestingtypes.ModuleName,
|
|
)
|
|
app.mm.SetOrderEndBlockers(
|
|
crisistypes.ModuleName, govtypes.ModuleName, stakingtypes.ModuleName,
|
|
capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName,
|
|
slashingtypes.ModuleName, minttypes.ModuleName,
|
|
genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName,
|
|
feegrant.ModuleName, nft.ModuleName, group.ModuleName,
|
|
paramstypes.ModuleName, upgradetypes.ModuleName, vestingtypes.ModuleName,
|
|
)
|
|
|
|
// NOTE: The genutils module must occur after staking so that pools are
|
|
// properly initialized with tokens from genesis accounts.
|
|
// NOTE: Capability module must occur first so that it can initialize any capabilities
|
|
// so that other modules that want to create or claim capabilities afterwards in InitChain
|
|
// can do so safely.
|
|
app.mm.SetOrderInitGenesis(
|
|
capabilitytypes.ModuleName, authtypes.ModuleName, banktypes.ModuleName, distrtypes.ModuleName, stakingtypes.ModuleName,
|
|
slashingtypes.ModuleName, govtypes.ModuleName, minttypes.ModuleName, crisistypes.ModuleName,
|
|
genutiltypes.ModuleName, evidencetypes.ModuleName, authz.ModuleName,
|
|
feegrant.ModuleName, nft.ModuleName, group.ModuleName,
|
|
paramstypes.ModuleName, upgradetypes.ModuleName, vestingtypes.ModuleName,
|
|
)
|
|
|
|
// Uncomment if you want to set a custom migration order here.
|
|
// app.mm.SetOrderMigrations(custom order)
|
|
|
|
app.mm.RegisterInvariants(&app.CrisisKeeper)
|
|
app.mm.RegisterRoutes(app.legacyRouter, app.QueryRouter(), encodingConfig.Amino)
|
|
app.configurator = module.NewConfigurator(app.appCodec, app.msgSvcRouter, app.GRPCQueryRouter())
|
|
app.mm.RegisterServices(app.configurator)
|
|
|
|
// add test gRPC service for testing gRPC queries in isolation
|
|
testdata.RegisterQueryServer(app.GRPCQueryRouter(), testdata.QueryImpl{})
|
|
|
|
// create the simulation manager and define the order of the modules for deterministic simulations
|
|
//
|
|
// NOTE: this is not required apps that don't use the simulator for fuzz testing
|
|
// transactions
|
|
app.sm = module.NewSimulationManager(
|
|
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
|
|
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
|
|
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
|
|
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
|
|
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
|
|
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
|
|
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
|
|
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
|
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
|
|
params.NewAppModule(app.ParamsKeeper),
|
|
evidence.NewAppModule(app.EvidenceKeeper),
|
|
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
|
|
groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
|
|
nftmodule.NewAppModule(appCodec, app.NFTKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
|
|
)
|
|
|
|
app.sm.RegisterStoreDecoders()
|
|
|
|
// initialize stores
|
|
app.MountKVStores(keys)
|
|
app.MountTransientStores(tkeys)
|
|
app.MountMemoryStores(memKeys)
|
|
|
|
// initialize BaseApp
|
|
app.SetInitChainer(app.InitChainer)
|
|
app.SetBeginBlocker(app.BeginBlocker)
|
|
app.SetEndBlocker(app.EndBlocker)
|
|
app.setTxHandler(encodingConfig.TxConfig, cast.ToStringSlice(appOpts.Get(server.FlagIndexEvents)))
|
|
|
|
if loadLatest {
|
|
if err := app.LoadLatestVersion(); err != nil {
|
|
tmos.Exit(err.Error())
|
|
}
|
|
}
|
|
|
|
return app
|
|
}
|
|
|
|
func (app *SimApp) setTxHandler(txConfig client.TxConfig, indexEventsStr []string) {
|
|
indexEvents := map[string]struct{}{}
|
|
for _, e := range indexEventsStr {
|
|
indexEvents[e] = struct{}{}
|
|
}
|
|
txHandler, err := authmiddleware.NewDefaultTxHandler(authmiddleware.TxHandlerOptions{
|
|
Debug: app.Trace(),
|
|
IndexEvents: indexEvents,
|
|
LegacyRouter: app.legacyRouter,
|
|
MsgServiceRouter: app.msgSvcRouter,
|
|
AccountKeeper: app.AccountKeeper,
|
|
BankKeeper: app.BankKeeper,
|
|
FeegrantKeeper: app.FeeGrantKeeper,
|
|
SignModeHandler: txConfig.SignModeHandler(),
|
|
SigGasConsumer: authmiddleware.DefaultSigVerificationGasConsumer,
|
|
TxDecoder: txConfig.TxDecoder(),
|
|
})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
app.SetTxHandler(txHandler)
|
|
}
|
|
|
|
// Name returns the name of the App
|
|
func (app *SimApp) Name() string { return app.BaseApp.Name() }
|
|
|
|
// BeginBlocker application updates every begin block
|
|
func (app *SimApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
|
return app.mm.BeginBlock(ctx, req)
|
|
}
|
|
|
|
// EndBlocker application updates every end block
|
|
func (app *SimApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
|
return app.mm.EndBlock(ctx, req)
|
|
}
|
|
|
|
// InitChainer application update at chain initialization
|
|
func (app *SimApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
|
var genesisState GenesisState
|
|
if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
|
|
panic(err)
|
|
}
|
|
app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap())
|
|
return app.mm.InitGenesis(ctx, app.appCodec, genesisState)
|
|
}
|
|
|
|
// LoadHeight loads a particular height
|
|
func (app *SimApp) LoadHeight(height int64) error {
|
|
return app.LoadVersion(height)
|
|
}
|
|
|
|
// ModuleAccountAddrs returns all the app's module account addresses.
|
|
func (app *SimApp) ModuleAccountAddrs() map[string]bool {
|
|
modAccAddrs := make(map[string]bool)
|
|
for acc := range maccPerms {
|
|
modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
|
|
}
|
|
|
|
return modAccAddrs
|
|
}
|
|
|
|
// LegacyAmino returns SimApp's amino codec.
|
|
//
|
|
// NOTE: This is solely to be used for testing purposes as it may be desirable
|
|
// for modules to register their own custom testing types.
|
|
func (app *SimApp) LegacyAmino() *codec.LegacyAmino {
|
|
return app.legacyAmino
|
|
}
|
|
|
|
// AppCodec returns SimApp's app codec.
|
|
//
|
|
// NOTE: This is solely to be used for testing purposes as it may be desirable
|
|
// for modules to register their own custom testing types.
|
|
func (app *SimApp) AppCodec() codec.Codec {
|
|
return app.appCodec
|
|
}
|
|
|
|
// InterfaceRegistry returns SimApp's InterfaceRegistry
|
|
func (app *SimApp) InterfaceRegistry() types.InterfaceRegistry {
|
|
return app.interfaceRegistry
|
|
}
|
|
|
|
// GetKey returns the KVStoreKey for the provided store key.
|
|
//
|
|
// NOTE: This is solely to be used for testing purposes.
|
|
func (app *SimApp) GetKey(storeKey string) *storetypes.KVStoreKey {
|
|
return app.keys[storeKey]
|
|
}
|
|
|
|
// GetTKey returns the TransientStoreKey for the provided store key.
|
|
//
|
|
// NOTE: This is solely to be used for testing purposes.
|
|
func (app *SimApp) GetTKey(storeKey string) *storetypes.TransientStoreKey {
|
|
return app.tkeys[storeKey]
|
|
}
|
|
|
|
// GetMemKey returns the MemStoreKey for the provided mem key.
|
|
//
|
|
// NOTE: This is solely used for testing purposes.
|
|
func (app *SimApp) GetMemKey(storeKey string) *storetypes.MemoryStoreKey {
|
|
return app.memKeys[storeKey]
|
|
}
|
|
|
|
// GetSubspace returns a param subspace for a given module name.
|
|
//
|
|
// NOTE: This is solely to be used for testing purposes.
|
|
func (app *SimApp) GetSubspace(moduleName string) paramstypes.Subspace {
|
|
subspace, _ := app.ParamsKeeper.GetSubspace(moduleName)
|
|
return subspace
|
|
}
|
|
|
|
// SimulationManager implements the SimulationApp interface
|
|
func (app *SimApp) SimulationManager() *module.SimulationManager {
|
|
return app.sm
|
|
}
|
|
|
|
// RegisterAPIRoutes registers all application module routes with the provided
|
|
// API server.
|
|
func (app *SimApp) RegisterAPIRoutes(apiSvr *api.Server, apiConfig config.APIConfig) {
|
|
clientCtx := apiSvr.ClientCtx
|
|
// Register new tx routes from grpc-gateway.
|
|
authtx.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
|
// Register new tendermint queries routes from grpc-gateway.
|
|
tmservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
|
|
|
// Register legacy and grpc-gateway routes for all modules.
|
|
ModuleBasics.RegisterRESTRoutes(clientCtx, apiSvr.Router)
|
|
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
|
|
|
|
// register swagger API from root so that other applications can override easily
|
|
if apiConfig.Swagger {
|
|
RegisterSwaggerAPI(clientCtx, apiSvr.Router)
|
|
}
|
|
}
|
|
|
|
// RegisterTxService implements the Application.RegisterTxService method.
|
|
func (app *SimApp) RegisterTxService(clientCtx client.Context) {
|
|
authtx.RegisterTxService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.BaseApp.Simulate, app.interfaceRegistry)
|
|
}
|
|
|
|
// RegisterTendermintService implements the Application.RegisterTendermintService method.
|
|
func (app *SimApp) RegisterTendermintService(clientCtx client.Context) {
|
|
tmservice.RegisterTendermintService(app.BaseApp.GRPCQueryRouter(), clientCtx, app.interfaceRegistry)
|
|
}
|
|
|
|
// RegisterSwaggerAPI registers swagger route with API Server
|
|
func RegisterSwaggerAPI(ctx client.Context, rtr *mux.Router) {
|
|
statikFS, err := fs.New()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
staticServer := http.FileServer(statikFS)
|
|
rtr.PathPrefix("/swagger/").Handler(http.StripPrefix("/swagger/", staticServer))
|
|
}
|
|
|
|
// GetMaccPerms returns a copy of the module account permissions
|
|
func GetMaccPerms() map[string][]string {
|
|
dupMaccPerms := make(map[string][]string)
|
|
for k, v := range maccPerms {
|
|
dupMaccPerms[k] = v
|
|
}
|
|
return dupMaccPerms
|
|
}
|
|
|
|
// initParamsKeeper init params keeper and its subspaces
|
|
func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey storetypes.StoreKey) paramskeeper.Keeper {
|
|
paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey)
|
|
|
|
paramsKeeper.Subspace(authtypes.ModuleName)
|
|
paramsKeeper.Subspace(banktypes.ModuleName)
|
|
paramsKeeper.Subspace(stakingtypes.ModuleName)
|
|
paramsKeeper.Subspace(minttypes.ModuleName)
|
|
paramsKeeper.Subspace(distrtypes.ModuleName)
|
|
paramsKeeper.Subspace(slashingtypes.ModuleName)
|
|
paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govv1beta2.ParamKeyTable())
|
|
paramsKeeper.Subspace(crisistypes.ModuleName)
|
|
|
|
return paramsKeeper
|
|
}
|