Synopsis
This document describes the core parts of a Cosmos SDK application, represented throughout the document as a placeholder application namedapp
.
Node Client
The Daemon, or Full-Node Client, is the core process of a Cosmos SDK-based blockchain. Participants in the network run this process to initialize their state-machine, connect with other full-nodes, and update their state-machine as new blocks come in.Copy
Ask AI
^ +-------------------------------+ ^
| | | |
| | State-machine = Application | |
| | | | Built with Cosmos SDK
| | ^ + | |
| +----------- | ABCI | ----------+ v
| | + v | ^
| | | |
Blockchain Node | | Consensus | |
| | | |
| +-------------------------------+ | CometBFT
| | | |
| | Networking | |
| | | |
v +-------------------------------+ v
-d
for “daemon” (e.g. appd
for app
or gaiad
for gaia
). This binary is built by running a simple main.go
function placed in ./cmd/appd/
. This operation usually happens through the Makefile.
Once the main binary is built, the node can be started by running the start
command. This command function primarily does three things:
- Create an instance of the state-machine defined in
app.go
. - Initialize the state-machine with the latest known state, extracted from the
db
stored in the~/.app/data
folder. At this point, the state-machine is at heightappBlockHeight
. - Create and start a new CometBFT instance. Among other things, the node performs a handshake with its peers. It gets the latest
blockHeight
from them and replays blocks to sync to this height if it is greater than the localappBlockHeight
. The node starts from genesis and CometBFT sends anInitChain
message via the ABCI to theapp
, which triggers theInitChainer
.
When starting a CometBFT instance, the genesis file is the
0
height and the
state within the genesis file is committed at block height 1
. When querying
the state of the node, querying block height 0 will return an error.Core Application File
In general, the core of the state-machine is defined in a file calledapp.go
. This file mainly contains the type definition of the application and functions to create and initialize it.
Type Definition of the Application
The first thing defined inapp.go
is the type
of the application. It is generally comprised of the following parts:
- A reference to
baseapp
. The custom application defined inapp.go
is an extension ofbaseapp
. When a transaction is relayed by CometBFT to the application,app
usesbaseapp
’s methods to route them to the appropriate module.baseapp
implements most of the core logic for the application, including all the ABCI methods and the routing logic. - A list of store keys. The store, which contains the entire state, is implemented as a
multistore
(i.e. a store of stores) in the Cosmos SDK. Each module uses one or multiple stores in the multistore to persist their part of the state. These stores can be accessed with specific keys that are declared in theapp
type. These keys, along with thekeepers
, are at the heart of the object-capabilities model of the Cosmos SDK. - A list of module’s
keeper
s. Each module defines an abstraction calledkeeper
, which handles reads and writes for this module’s store(s). Thekeeper
’s methods of one module can be called from other modules (if authorized), which is why they are declared in the application’s type and exported as interfaces to other modules so that the latter can only access the authorized functions. - A reference to an
appCodec
. The application’sappCodec
is used to serialize and deserialize data structures in order to store them, as stores can only persist[]bytes
. The default codec is Protocol Buffers. - A reference to a
legacyAmino
codec. Some parts of the Cosmos SDK have not been migrated to use theappCodec
above, and are still hardcoded to use Amino. Other parts explicitly use Amino for backwards compatibility. For these reasons, the application still holds a reference to the legacy Amino codec. Please note that the Amino codec will be removed from the SDK in the upcoming releases. - A reference to a module manager and a basic module manager. The module manager is an object that contains a list of the application’s modules. It facilitates operations related to these modules, like registering their
Msg
service and gRPCQuery
service, or setting the order of execution between modules for various functions likeInitChainer
,BeginBlocker
andEndBlocker
.
simapp
, the Cosmos SDK’s own app used for demo and testing purposes:
Copy
Ask AI
/go:build app_v1
package simapp
import (
"encoding/json"
"io"
"os"
"path/filepath"
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
"github.com/spf13/cast"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
simappparams "cosmossdk.io/simapp/params"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
"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/runtime"
runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
"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"
"github.com/cosmos/cosmos-sdk/std"
"github.com/cosmos/cosmos-sdk/store/streaming"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata_pulsar"
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"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/posthandler"
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"
consensus "github.com/cosmos/cosmos-sdk/x/consensus"
consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/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"
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"
govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
"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"
)
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.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),
bank.AppModuleBasic{
},
capability.AppModuleBasic{
},
staking.AppModuleBasic{
},
mint.AppModuleBasic{
},
distr.AppModuleBasic{
},
gov.NewAppModuleBasic(
[]govclient.ProposalHandler{
paramsclient.ProposalHandler,
upgradeclient.LegacyProposalHandler,
upgradeclient.LegacyCancelProposalHandler,
},
),
params.AppModuleBasic{
},
crisis.AppModuleBasic{
},
slashing.AppModuleBasic{
},
feegrantmodule.AppModuleBasic{
},
upgrade.AppModuleBasic{
},
evidence.AppModuleBasic{
},
authzmodule.AppModuleBasic{
},
groupmodule.AppModuleBasic{
},
vesting.AppModuleBasic{
},
nftmodule.AppModuleBasic{
},
consensus.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 (
_ runtime.AppI = (*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
txConfig client.TxConfig
interfaceRegistry types.InterfaceRegistry
/ 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
ConsensusParamsKeeper consensusparamkeeper.Keeper
/ the module manager
ModuleManager *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,
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
encodingConfig := makeEncodingConfig()
appCodec := encodingConfig.Codec
legacyAmino := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
txConfig := encodingConfig.TxConfig
/ Below we could construct and set an application specific mempool and ABCI 1.0 Prepare and Process Proposal
/ handlers. These defaults are already set in the SDK's BaseApp, this shows an example of how to override
/ them.
/
/ nonceMempool := mempool.NewSenderNonceMempool()
/ mempoolOpt := baseapp.SetMempool(nonceMempool)
/ prepareOpt := func(app *baseapp.BaseApp) {
/ app.SetPrepareProposal(app.DefaultPrepareProposal())
/
}
/ processOpt := func(app *baseapp.BaseApp) {
/ app.SetProcessProposal(app.DefaultProcessProposal())
/
}
/
/ Further down we'd set the options in the AppBuilder like below.
/ baseAppOptions = append(baseAppOptions, mempoolOpt, prepareOpt, processOpt)
bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseAppOptions...)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
bApp.SetInterfaceRegistry(interfaceRegistry)
bApp.SetTxEncoder(txConfig.TxEncoder())
keys := sdk.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, crisistypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, paramstypes.StoreKey, consensusparamtypes.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")
/ load state streaming if enabled
if _, _, err := streaming.LoadStreamingServices(bApp, appOpts, appCodec, logger, keys); err != nil {
logger.Error("failed to load state streaming", "err", err)
os.Exit(1)
}
app := &SimApp{
BaseApp: bApp,
legacyAmino: legacyAmino,
appCodec: appCodec,
txConfig: txConfig,
interfaceRegistry: interfaceRegistry,
keys: keys,
tkeys: tkeys,
memKeys: memKeys,
}
app.ParamsKeeper = initParamsKeeper(appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
/ set the BaseApp's parameter store
app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(appCodec, keys[upgradetypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String())
bApp.SetParamStore(&app.ConsensusParamsKeeper)
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], authtypes.ProtoBaseAccount, maccPerms, sdk.Bech32MainPrefix, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec,
keys[banktypes.StoreKey],
app.AccountKeeper,
BlockedAddresses(),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
app.StakingKeeper = stakingkeeper.NewKeeper(
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
app.MintKeeper = mintkeeper.NewKeeper(appCodec, keys[minttypes.StoreKey], app.StakingKeeper, app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.DistrKeeper = distrkeeper.NewKeeper(appCodec, keys[distrtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.StakingKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec, legacyAmino, keys[slashingtypes.StoreKey], app.StakingKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
invCheckPeriod := cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod))
app.CrisisKeeper = crisiskeeper.NewKeeper(appCodec, keys[crisistypes.StoreKey], invCheckPeriod,
app.BankKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
/ register the staking hooks
/ NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper.SetHooks(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper)
groupConfig := group.DefaultConfig()
/*
Example of setting group params:
groupConfig.MaxMetadataLen = 1000
*/
app.GroupKeeper = groupkeeper.NewKeeper(keys[group.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper, groupConfig)
/ get skipUpgradeHeights from the app options
skipUpgradeHeights := map[int64]bool{
}
for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) {
skipUpgradeHeights[int64(h)] = true
}
homePath := cast.ToString(appOpts.Get(flags.FlagHome))
/ set the governance module account as the authority for conducting upgrades
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp, authtypes.NewModuleAddress(govtypes.ModuleName).String())
/ Register the proposal types
/ Deprecated: Avoid adding new handlers, instead use the new proposal flow
/ by granting the governance module the right to execute the message.
/ See: https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/gov/spec/01_concepts.md#proposal-messages
govRouter := govv1beta1.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
govConfig := govtypes.DefaultConfig()
/*
Example of setting gov params:
govConfig.MaxMetadataLen = 10000
*/
govKeeper := govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.AccountKeeper, app.BankKeeper,
app.StakingKeeper, app.MsgServiceRouter(), govConfig, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
/ Set legacy router for backwards compatibility with gov v1beta1
govKeeper.SetLegacyRouter(govRouter)
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.
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.ModuleManager = module.NewManager(
genutil.NewAppModule(
app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx,
encodingConfig.TxConfig,
),
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)),
capability.NewAppModule(appCodec, *app.CapabilityKeeper, false),
crisis.NewAppModule(app.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, app.GetSubspace(minttypes.ModuleName)),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(slashingtypes.ModuleName)),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)),
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),
consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
)
/ 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.ModuleManager.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, consensusparamtypes.ModuleName,
)
app.ModuleManager.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, consensusparamtypes.ModuleName,
)
/ NOTE: The genutils module must occur after staking so that pools are
/ properly initialized with tokens from genesis accounts.
/ NOTE: The genutils module must also occur after auth so that it can access the params from auth.
/ 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.
genesisModuleOrder := []string{
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, consensusparamtypes.ModuleName,
}
app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)
app.ModuleManager.SetOrderExportGenesis(genesisModuleOrder...)
/ Uncomment if you want to set a custom migration order here.
/ app.ModuleManager.SetOrderMigrations(custom order)
app.ModuleManager.RegisterInvariants(app.CrisisKeeper)
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
app.ModuleManager.RegisterServices(app.configurator)
/ RegisterUpgradeHandlers is used for registering any on-chain upgrades.
/ Make sure it's called after `app.ModuleManager` and `app.configurator` are set.
app.RegisterUpgradeHandlers()
autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules))
reflectionSvc, err := runtimeservices.NewReflectionService()
if err != nil {
panic(err)
}
reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc)
/ add test gRPC service for testing gRPC queries in isolation
testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.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
overrideModules := map[string]module.AppModuleSimulation{
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
}
app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)
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.setAnteHandler(encodingConfig.TxConfig)
/ In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
/ antehandlers, but are run _after_ the `runMsgs` execution. They are also
/ defined as a chain, and have the same signature as antehandlers.
/
/ In baseapp, postHandlers are run in the same store branch as `runMsgs`,
/ meaning that both `runMsgs` and `postHandler` state will be committed if
/ both are successful, and both will be reverted if any of the two fails.
/
/ The SDK exposes a default postHandlers chain, which comprises of only
/ one decorator: the Transaction Tips decorator. However, some chains do
/ not need it by default, so feel free to comment the next line if you do
/ not need tips.
/ To read more about tips:
/ https://docs.cosmos.network/main/core/tips.html
/
/ Please note that changing any of the anteHandler or postHandler chain is
/ likely to be a state-machine breaking change, which needs a coordinated
/ upgrade.
app.setPostHandler()
if loadLatest {
if err := app.LoadLatestVersion(); err != nil {
logger.Error("error on loading last version", "err", err)
os.Exit(1)
}
}
return app
}
func (app *SimApp)
setAnteHandler(txConfig client.TxConfig) {
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: txConfig.SignModeHandler(),
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
if err != nil {
panic(err)
}
app.SetAnteHandler(anteHandler)
}
func (app *SimApp)
setPostHandler() {
postHandler, err := posthandler.NewPostHandler(
posthandler.HandlerOptions{
},
)
if err != nil {
panic(err)
}
app.SetPostHandler(postHandler)
}
/ 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.ModuleManager.BeginBlock(ctx, req)
}
/ EndBlocker application updates every end block
func (app *SimApp)
EndBlocker(ctx sdk.Context, req abci.RequestEndBlock)
abci.ResponseEndBlock {
return app.ModuleManager.EndBlock(ctx, req)
}
func (a *SimApp)
Configurator()
module.Configurator {
return a.configurator
}
/ 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.ModuleManager.GetVersionMap())
return app.ModuleManager.InitGenesis(ctx, app.appCodec, genesisState)
}
/ LoadHeight loads a particular height
func (app *SimApp)
LoadHeight(height int64)
error {
return app.LoadVersion(height)
}
/ 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
}
/ TxConfig returns SimApp's TxConfig
func (app *SimApp)
TxConfig()
client.TxConfig {
return app.txConfig
}
/ DefaultGenesis returns a default genesis from the registered AppModuleBasic's.
func (a *SimApp)
DefaultGenesis()
map[string]json.RawMessage {
return ModuleBasics.DefaultGenesis(a.appCodec)
}
/ 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 node gRPC service for grpc-gateway.
nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
/ Register grpc-gateway routes for all modules.
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
/ register swagger API from root so that other applications can override easily
if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
panic(err)
}
}
/ 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(
clientCtx,
app.BaseApp.GRPCQueryRouter(),
app.interfaceRegistry,
app.Query,
)
}
func (app *SimApp)
RegisterNodeService(clientCtx client.Context) {
nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter())
}
/ GetMaccPerms returns a copy of the module account permissions
/
/ NOTE: This is solely to be used for testing purposes.
func GetMaccPerms()
map[string][]string {
dupMaccPerms := make(map[string][]string)
for k, v := range maccPerms {
dupMaccPerms[k] = v
}
return dupMaccPerms
}
/ BlockedAddresses returns all the app's blocked account addresses.
func BlockedAddresses()
map[string]bool {
modAccAddrs := make(map[string]bool)
for acc := range GetMaccPerms() {
modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
}
/ allow the following addresses to receive funds
delete(modAccAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String())
return modAccAddrs
}
/ 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(govv1.ParamKeyTable())
paramsKeeper.Subspace(crisistypes.ModuleName)
return paramsKeeper
}
func makeEncodingConfig()
simappparams.EncodingConfig {
encodingConfig := simappparams.MakeTestEncodingConfig()
std.RegisterLegacyAminoCodec(encodingConfig.Amino)
std.RegisterInterfaces(encodingConfig.InterfaceRegistry)
ModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino)
ModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry)
return encodingConfig
}
Constructor Function
Also defined inapp.go
is the constructor function, which constructs a new application of the type defined in the preceding section. The function must fulfill the AppCreator
signature in order to be used in the start
command of the application’s daemon command.
Copy
Ask AI
package types
import (
"encoding/json"
"io"
"time"
"github.com/cosmos/gogoproto/grpc"
"github.com/spf13/cobra"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmtypes "github.com/tendermint/tendermint/types"
dbm "github.com/tendermint/tm-db"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/server/api"
"github.com/cosmos/cosmos-sdk/server/config"
sdk "github.com/cosmos/cosmos-sdk/types"
)
/ ServerStartTime defines the time duration that the server need to stay running after startup
/ for the startup be considered successful
const ServerStartTime = 5 * time.Second
type (
/ AppOptions defines an interface that is passed into an application
/ constructor, typically used to set BaseApp options that are either supplied
/ via config file or through CLI arguments/flags. The underlying implementation
/ is defined by the server package and is typically implemented via a Viper
/ literal defined on the server Context. Note, casting Get calls may not yield
/ the expected types and could result in type assertion errors. It is recommend
/ to either use the cast package or perform manual conversion for safety.
AppOptions interface {
Get(string)
interface{
}
}
/ Application defines an application interface that wraps abci.Application.
/ The interface defines the necessary contracts to be implemented in order
/ to fully bootstrap and start an application.
Application interface {
abci.Application
RegisterAPIRoutes(*api.Server, config.APIConfig)
/ RegisterGRPCServer registers gRPC services directly with the gRPC
/ server.
RegisterGRPCServer(grpc.Server)
/ RegisterTxService registers the gRPC Query service for tx (such as tx
/ simulation, fetching txs by hash...).
RegisterTxService(client.Context)
/ RegisterTendermintService registers the gRPC Query service for tendermint queries.
RegisterTendermintService(client.Context)
/ RegisterNodeService registers the node gRPC Query service.
RegisterNodeService(client.Context)
/ CommitMultiStore return the multistore instance
CommitMultiStore()
sdk.CommitMultiStore
}
/ AppCreator is a function that allows us to lazily initialize an
/ application using various configurations.
AppCreator func(log.Logger, dbm.DB, io.Writer, AppOptions)
Application
/ ModuleInitFlags takes a start command and adds modules specific init flags.
ModuleInitFlags func(startCmd *cobra.Command)
/ ExportedApp represents an exported app state, along with
/ validators, consensus params and latest app height.
ExportedApp struct {
/ AppState is the application state as JSON.
AppState json.RawMessage
/ Validators is the exported validator set.
Validators []tmtypes.GenesisValidator
/ Height is the app's latest block height.
Height int64
/ ConsensusParams are the exported consensus params for ABCI.
ConsensusParams *tmproto.ConsensusParams
}
/ AppExporter is a function that dumps all app state to
/ JSON-serializable structure and returns the current validator set.
AppExporter func(log.Logger, dbm.DB, io.Writer, int64, bool, []string, AppOptions, []string) (ExportedApp, error)
)
- Instantiate a new
codec
and initialize thecodec
of each of the application’s modules using the basic manager. - Instantiate a new application with a reference to a
baseapp
instance, a codec, and all the appropriate store keys. - Instantiate all the
keeper
objects defined in the application’stype
using theNewKeeper
function of each of the application’s modules. Note that keepers must be instantiated in the correct order, as theNewKeeper
of one module might require a reference to another module’skeeper
. - Instantiate the application’s module manager with the
AppModule
object of each of the application’s modules. - With the module manager, initialize the application’s
Msg
services, gRPCQuery
services, legacyMsg
routes, and legacy query routes. When a transaction is relayed to the application by CometBFT via the ABCI, it is routed to the appropriate module’sMsg
service using the routes defined here. Likewise, when a gRPC query request is received by the application, it is routed to the appropriate module’sgRPC query service
using the gRPC routes defined here. The Cosmos SDK still supports legacyMsg
s and legacy CometBFT queries, which are routed using the legacyMsg
routes and the legacy query routes, respectively. - With the module manager, register the application’s modules’ invariants. Invariants are variables (e.g. total supply of a token) that are evaluated at the end of each block. The process of checking invariants is done via a special module called the
InvariantsRegistry
. The value of the invariant should be equal to a predicted value defined in the module. Should the value be different than the predicted one, special logic defined in the invariant registry is triggered (usually the chain is halted). This is useful to make sure that no critical bug goes unnoticed, producing long-lasting effects that are hard to fix. - With the module manager, set the order of execution between the
InitGenesis
,BeginBlocker
, andEndBlocker
functions of each of the application’s modules. Note that not all modules implement these functions. - Set the remaining application parameters:
InitChainer
: used to initialize the application when it is first started.BeginBlocker
,EndBlocker
: called at the beginning and at the end of every block.anteHandler
: used to handle fees and signature verification.
- Mount the stores.
- Return the application.
~/.app/data
folder if the node is restarted, or generated from the genesis file if the node is started for the first time.
See an example of application constructor from simapp
:
Copy
Ask AI
/go:build app_v1
package simapp
import (
"encoding/json"
"io"
"os"
"path/filepath"
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
"github.com/spf13/cast"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
simappparams "cosmossdk.io/simapp/params"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
"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/runtime"
runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
"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"
"github.com/cosmos/cosmos-sdk/std"
"github.com/cosmos/cosmos-sdk/store/streaming"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata_pulsar"
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"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/posthandler"
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"
consensus "github.com/cosmos/cosmos-sdk/x/consensus"
consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/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"
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"
govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
"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"
)
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.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),
bank.AppModuleBasic{
},
capability.AppModuleBasic{
},
staking.AppModuleBasic{
},
mint.AppModuleBasic{
},
distr.AppModuleBasic{
},
gov.NewAppModuleBasic(
[]govclient.ProposalHandler{
paramsclient.ProposalHandler,
upgradeclient.LegacyProposalHandler,
upgradeclient.LegacyCancelProposalHandler,
},
),
params.AppModuleBasic{
},
crisis.AppModuleBasic{
},
slashing.AppModuleBasic{
},
feegrantmodule.AppModuleBasic{
},
upgrade.AppModuleBasic{
},
evidence.AppModuleBasic{
},
authzmodule.AppModuleBasic{
},
groupmodule.AppModuleBasic{
},
vesting.AppModuleBasic{
},
nftmodule.AppModuleBasic{
},
consensus.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 (
_ runtime.AppI = (*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
txConfig client.TxConfig
interfaceRegistry types.InterfaceRegistry
/ 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
ConsensusParamsKeeper consensusparamkeeper.Keeper
/ the module manager
ModuleManager *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,
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
encodingConfig := makeEncodingConfig()
appCodec := encodingConfig.Codec
legacyAmino := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
txConfig := encodingConfig.TxConfig
/ Below we could construct and set an application specific mempool and ABCI 1.0 Prepare and Process Proposal
/ handlers. These defaults are already set in the SDK's BaseApp, this shows an example of how to override
/ them.
/
/ nonceMempool := mempool.NewSenderNonceMempool()
/ mempoolOpt := baseapp.SetMempool(nonceMempool)
/ prepareOpt := func(app *baseapp.BaseApp) {
/ app.SetPrepareProposal(app.DefaultPrepareProposal())
/
}
/ processOpt := func(app *baseapp.BaseApp) {
/ app.SetProcessProposal(app.DefaultProcessProposal())
/
}
/
/ Further down we'd set the options in the AppBuilder like below.
/ baseAppOptions = append(baseAppOptions, mempoolOpt, prepareOpt, processOpt)
bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseAppOptions...)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
bApp.SetInterfaceRegistry(interfaceRegistry)
bApp.SetTxEncoder(txConfig.TxEncoder())
keys := sdk.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, crisistypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, paramstypes.StoreKey, consensusparamtypes.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")
/ load state streaming if enabled
if _, _, err := streaming.LoadStreamingServices(bApp, appOpts, appCodec, logger, keys); err != nil {
logger.Error("failed to load state streaming", "err", err)
os.Exit(1)
}
app := &SimApp{
BaseApp: bApp,
legacyAmino: legacyAmino,
appCodec: appCodec,
txConfig: txConfig,
interfaceRegistry: interfaceRegistry,
keys: keys,
tkeys: tkeys,
memKeys: memKeys,
}
app.ParamsKeeper = initParamsKeeper(appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
/ set the BaseApp's parameter store
app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(appCodec, keys[upgradetypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String())
bApp.SetParamStore(&app.ConsensusParamsKeeper)
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], authtypes.ProtoBaseAccount, maccPerms, sdk.Bech32MainPrefix, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec,
keys[banktypes.StoreKey],
app.AccountKeeper,
BlockedAddresses(),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
app.StakingKeeper = stakingkeeper.NewKeeper(
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
app.MintKeeper = mintkeeper.NewKeeper(appCodec, keys[minttypes.StoreKey], app.StakingKeeper, app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.DistrKeeper = distrkeeper.NewKeeper(appCodec, keys[distrtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.StakingKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec, legacyAmino, keys[slashingtypes.StoreKey], app.StakingKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
invCheckPeriod := cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod))
app.CrisisKeeper = crisiskeeper.NewKeeper(appCodec, keys[crisistypes.StoreKey], invCheckPeriod,
app.BankKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
/ register the staking hooks
/ NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper.SetHooks(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper)
groupConfig := group.DefaultConfig()
/*
Example of setting group params:
groupConfig.MaxMetadataLen = 1000
*/
app.GroupKeeper = groupkeeper.NewKeeper(keys[group.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper, groupConfig)
/ get skipUpgradeHeights from the app options
skipUpgradeHeights := map[int64]bool{
}
for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) {
skipUpgradeHeights[int64(h)] = true
}
homePath := cast.ToString(appOpts.Get(flags.FlagHome))
/ set the governance module account as the authority for conducting upgrades
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp, authtypes.NewModuleAddress(govtypes.ModuleName).String())
/ Register the proposal types
/ Deprecated: Avoid adding new handlers, instead use the new proposal flow
/ by granting the governance module the right to execute the message.
/ See: https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/gov/spec/01_concepts.md#proposal-messages
govRouter := govv1beta1.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
govConfig := govtypes.DefaultConfig()
/*
Example of setting gov params:
govConfig.MaxMetadataLen = 10000
*/
govKeeper := govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.AccountKeeper, app.BankKeeper,
app.StakingKeeper, app.MsgServiceRouter(), govConfig, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
/ Set legacy router for backwards compatibility with gov v1beta1
govKeeper.SetLegacyRouter(govRouter)
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.
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.ModuleManager = module.NewManager(
genutil.NewAppModule(
app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx,
encodingConfig.TxConfig,
),
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)),
capability.NewAppModule(appCodec, *app.CapabilityKeeper, false),
crisis.NewAppModule(app.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, app.GetSubspace(minttypes.ModuleName)),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(slashingtypes.ModuleName)),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)),
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),
consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
)
/ 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.ModuleManager.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, consensusparamtypes.ModuleName,
)
app.ModuleManager.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, consensusparamtypes.ModuleName,
)
/ NOTE: The genutils module must occur after staking so that pools are
/ properly initialized with tokens from genesis accounts.
/ NOTE: The genutils module must also occur after auth so that it can access the params from auth.
/ 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.
genesisModuleOrder := []string{
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, consensusparamtypes.ModuleName,
}
app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)
app.ModuleManager.SetOrderExportGenesis(genesisModuleOrder...)
/ Uncomment if you want to set a custom migration order here.
/ app.ModuleManager.SetOrderMigrations(custom order)
app.ModuleManager.RegisterInvariants(app.CrisisKeeper)
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
app.ModuleManager.RegisterServices(app.configurator)
/ RegisterUpgradeHandlers is used for registering any on-chain upgrades.
/ Make sure it's called after `app.ModuleManager` and `app.configurator` are set.
app.RegisterUpgradeHandlers()
autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules))
reflectionSvc, err := runtimeservices.NewReflectionService()
if err != nil {
panic(err)
}
reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc)
/ add test gRPC service for testing gRPC queries in isolation
testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.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
overrideModules := map[string]module.AppModuleSimulation{
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
}
app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)
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.setAnteHandler(encodingConfig.TxConfig)
/ In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
/ antehandlers, but are run _after_ the `runMsgs` execution. They are also
/ defined as a chain, and have the same signature as antehandlers.
/
/ In baseapp, postHandlers are run in the same store branch as `runMsgs`,
/ meaning that both `runMsgs` and `postHandler` state will be committed if
/ both are successful, and both will be reverted if any of the two fails.
/
/ The SDK exposes a default postHandlers chain, which comprises of only
/ one decorator: the Transaction Tips decorator. However, some chains do
/ not need it by default, so feel free to comment the next line if you do
/ not need tips.
/ To read more about tips:
/ https://docs.cosmos.network/main/core/tips.html
/
/ Please note that changing any of the anteHandler or postHandler chain is
/ likely to be a state-machine breaking change, which needs a coordinated
/ upgrade.
app.setPostHandler()
if loadLatest {
if err := app.LoadLatestVersion(); err != nil {
logger.Error("error on loading last version", "err", err)
os.Exit(1)
}
}
return app
}
func (app *SimApp)
setAnteHandler(txConfig client.TxConfig) {
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: txConfig.SignModeHandler(),
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
if err != nil {
panic(err)
}
app.SetAnteHandler(anteHandler)
}
func (app *SimApp)
setPostHandler() {
postHandler, err := posthandler.NewPostHandler(
posthandler.HandlerOptions{
},
)
if err != nil {
panic(err)
}
app.SetPostHandler(postHandler)
}
/ 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.ModuleManager.BeginBlock(ctx, req)
}
/ EndBlocker application updates every end block
func (app *SimApp)
EndBlocker(ctx sdk.Context, req abci.RequestEndBlock)
abci.ResponseEndBlock {
return app.ModuleManager.EndBlock(ctx, req)
}
func (a *SimApp)
Configurator()
module.Configurator {
return a.configurator
}
/ 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.ModuleManager.GetVersionMap())
return app.ModuleManager.InitGenesis(ctx, app.appCodec, genesisState)
}
/ LoadHeight loads a particular height
func (app *SimApp)
LoadHeight(height int64)
error {
return app.LoadVersion(height)
}
/ 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
}
/ TxConfig returns SimApp's TxConfig
func (app *SimApp)
TxConfig()
client.TxConfig {
return app.txConfig
}
/ DefaultGenesis returns a default genesis from the registered AppModuleBasic's.
func (a *SimApp)
DefaultGenesis()
map[string]json.RawMessage {
return ModuleBasics.DefaultGenesis(a.appCodec)
}
/ 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 node gRPC service for grpc-gateway.
nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
/ Register grpc-gateway routes for all modules.
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
/ register swagger API from root so that other applications can override easily
if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
panic(err)
}
}
/ 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(
clientCtx,
app.BaseApp.GRPCQueryRouter(),
app.interfaceRegistry,
app.Query,
)
}
func (app *SimApp)
RegisterNodeService(clientCtx client.Context) {
nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter())
}
/ GetMaccPerms returns a copy of the module account permissions
/
/ NOTE: This is solely to be used for testing purposes.
func GetMaccPerms()
map[string][]string {
dupMaccPerms := make(map[string][]string)
for k, v := range maccPerms {
dupMaccPerms[k] = v
}
return dupMaccPerms
}
/ BlockedAddresses returns all the app's blocked account addresses.
func BlockedAddresses()
map[string]bool {
modAccAddrs := make(map[string]bool)
for acc := range GetMaccPerms() {
modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
}
/ allow the following addresses to receive funds
delete(modAccAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String())
return modAccAddrs
}
/ 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(govv1.ParamKeyTable())
paramsKeeper.Subspace(crisistypes.ModuleName)
return paramsKeeper
}
func makeEncodingConfig()
simappparams.EncodingConfig {
encodingConfig := simappparams.MakeTestEncodingConfig()
std.RegisterLegacyAminoCodec(encodingConfig.Amino)
std.RegisterInterfaces(encodingConfig.InterfaceRegistry)
ModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino)
ModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry)
return encodingConfig
}
InitChainer
TheInitChainer
is a function that initializes the state of the application from a genesis file (i.e. token balances of genesis accounts). It is called when the application receives the InitChain
message from the CometBFT engine, which happens when the node is started at appBlockHeight == 0
(i.e. on genesis). The application must set the InitChainer
in its constructor via the SetInitChainer
method.
In general, the InitChainer
is mostly composed of the InitGenesis
function of each of the application’s modules. This is done by calling the InitGenesis
function of the module manager, which in turn calls the InitGenesis
function of each of the modules it contains. Note that the order in which the modules’ InitGenesis
functions must be called has to be set in the module manager using the module manager’s SetOrderInitGenesis
method. This is done in the application’s constructor, and the SetOrderInitGenesis
has to be called before the SetInitChainer
.
See an example of an InitChainer
from simapp
:
Copy
Ask AI
/go:build app_v1
package simapp
import (
"encoding/json"
"io"
"os"
"path/filepath"
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
"github.com/spf13/cast"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
simappparams "cosmossdk.io/simapp/params"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
"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/runtime"
runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
"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"
"github.com/cosmos/cosmos-sdk/std"
"github.com/cosmos/cosmos-sdk/store/streaming"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata_pulsar"
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"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/posthandler"
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"
consensus "github.com/cosmos/cosmos-sdk/x/consensus"
consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/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"
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"
govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
"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"
)
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.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),
bank.AppModuleBasic{
},
capability.AppModuleBasic{
},
staking.AppModuleBasic{
},
mint.AppModuleBasic{
},
distr.AppModuleBasic{
},
gov.NewAppModuleBasic(
[]govclient.ProposalHandler{
paramsclient.ProposalHandler,
upgradeclient.LegacyProposalHandler,
upgradeclient.LegacyCancelProposalHandler,
},
),
params.AppModuleBasic{
},
crisis.AppModuleBasic{
},
slashing.AppModuleBasic{
},
feegrantmodule.AppModuleBasic{
},
upgrade.AppModuleBasic{
},
evidence.AppModuleBasic{
},
authzmodule.AppModuleBasic{
},
groupmodule.AppModuleBasic{
},
vesting.AppModuleBasic{
},
nftmodule.AppModuleBasic{
},
consensus.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 (
_ runtime.AppI = (*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
txConfig client.TxConfig
interfaceRegistry types.InterfaceRegistry
/ 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
ConsensusParamsKeeper consensusparamkeeper.Keeper
/ the module manager
ModuleManager *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,
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
encodingConfig := makeEncodingConfig()
appCodec := encodingConfig.Codec
legacyAmino := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
txConfig := encodingConfig.TxConfig
/ Below we could construct and set an application specific mempool and ABCI 1.0 Prepare and Process Proposal
/ handlers. These defaults are already set in the SDK's BaseApp, this shows an example of how to override
/ them.
/
/ nonceMempool := mempool.NewSenderNonceMempool()
/ mempoolOpt := baseapp.SetMempool(nonceMempool)
/ prepareOpt := func(app *baseapp.BaseApp) {
/ app.SetPrepareProposal(app.DefaultPrepareProposal())
/
}
/ processOpt := func(app *baseapp.BaseApp) {
/ app.SetProcessProposal(app.DefaultProcessProposal())
/
}
/
/ Further down we'd set the options in the AppBuilder like below.
/ baseAppOptions = append(baseAppOptions, mempoolOpt, prepareOpt, processOpt)
bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseAppOptions...)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
bApp.SetInterfaceRegistry(interfaceRegistry)
bApp.SetTxEncoder(txConfig.TxEncoder())
keys := sdk.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, crisistypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, paramstypes.StoreKey, consensusparamtypes.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")
/ load state streaming if enabled
if _, _, err := streaming.LoadStreamingServices(bApp, appOpts, appCodec, logger, keys); err != nil {
logger.Error("failed to load state streaming", "err", err)
os.Exit(1)
}
app := &SimApp{
BaseApp: bApp,
legacyAmino: legacyAmino,
appCodec: appCodec,
txConfig: txConfig,
interfaceRegistry: interfaceRegistry,
keys: keys,
tkeys: tkeys,
memKeys: memKeys,
}
app.ParamsKeeper = initParamsKeeper(appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
/ set the BaseApp's parameter store
app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(appCodec, keys[upgradetypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String())
bApp.SetParamStore(&app.ConsensusParamsKeeper)
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], authtypes.ProtoBaseAccount, maccPerms, sdk.Bech32MainPrefix, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec,
keys[banktypes.StoreKey],
app.AccountKeeper,
BlockedAddresses(),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
app.StakingKeeper = stakingkeeper.NewKeeper(
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
app.MintKeeper = mintkeeper.NewKeeper(appCodec, keys[minttypes.StoreKey], app.StakingKeeper, app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.DistrKeeper = distrkeeper.NewKeeper(appCodec, keys[distrtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.StakingKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec, legacyAmino, keys[slashingtypes.StoreKey], app.StakingKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
invCheckPeriod := cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod))
app.CrisisKeeper = crisiskeeper.NewKeeper(appCodec, keys[crisistypes.StoreKey], invCheckPeriod,
app.BankKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
/ register the staking hooks
/ NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper.SetHooks(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper)
groupConfig := group.DefaultConfig()
/*
Example of setting group params:
groupConfig.MaxMetadataLen = 1000
*/
app.GroupKeeper = groupkeeper.NewKeeper(keys[group.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper, groupConfig)
/ get skipUpgradeHeights from the app options
skipUpgradeHeights := map[int64]bool{
}
for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) {
skipUpgradeHeights[int64(h)] = true
}
homePath := cast.ToString(appOpts.Get(flags.FlagHome))
/ set the governance module account as the authority for conducting upgrades
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp, authtypes.NewModuleAddress(govtypes.ModuleName).String())
/ Register the proposal types
/ Deprecated: Avoid adding new handlers, instead use the new proposal flow
/ by granting the governance module the right to execute the message.
/ See: https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/gov/spec/01_concepts.md#proposal-messages
govRouter := govv1beta1.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
govConfig := govtypes.DefaultConfig()
/*
Example of setting gov params:
govConfig.MaxMetadataLen = 10000
*/
govKeeper := govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.AccountKeeper, app.BankKeeper,
app.StakingKeeper, app.MsgServiceRouter(), govConfig, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
/ Set legacy router for backwards compatibility with gov v1beta1
govKeeper.SetLegacyRouter(govRouter)
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.
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.ModuleManager = module.NewManager(
genutil.NewAppModule(
app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx,
encodingConfig.TxConfig,
),
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)),
capability.NewAppModule(appCodec, *app.CapabilityKeeper, false),
crisis.NewAppModule(app.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, app.GetSubspace(minttypes.ModuleName)),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(slashingtypes.ModuleName)),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)),
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),
consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
)
/ 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.ModuleManager.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, consensusparamtypes.ModuleName,
)
app.ModuleManager.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, consensusparamtypes.ModuleName,
)
/ NOTE: The genutils module must occur after staking so that pools are
/ properly initialized with tokens from genesis accounts.
/ NOTE: The genutils module must also occur after auth so that it can access the params from auth.
/ 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.
genesisModuleOrder := []string{
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, consensusparamtypes.ModuleName,
}
app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)
app.ModuleManager.SetOrderExportGenesis(genesisModuleOrder...)
/ Uncomment if you want to set a custom migration order here.
/ app.ModuleManager.SetOrderMigrations(custom order)
app.ModuleManager.RegisterInvariants(app.CrisisKeeper)
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
app.ModuleManager.RegisterServices(app.configurator)
/ RegisterUpgradeHandlers is used for registering any on-chain upgrades.
/ Make sure it's called after `app.ModuleManager` and `app.configurator` are set.
app.RegisterUpgradeHandlers()
autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules))
reflectionSvc, err := runtimeservices.NewReflectionService()
if err != nil {
panic(err)
}
reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc)
/ add test gRPC service for testing gRPC queries in isolation
testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.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
overrideModules := map[string]module.AppModuleSimulation{
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
}
app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)
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.setAnteHandler(encodingConfig.TxConfig)
/ In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
/ antehandlers, but are run _after_ the `runMsgs` execution. They are also
/ defined as a chain, and have the same signature as antehandlers.
/
/ In baseapp, postHandlers are run in the same store branch as `runMsgs`,
/ meaning that both `runMsgs` and `postHandler` state will be committed if
/ both are successful, and both will be reverted if any of the two fails.
/
/ The SDK exposes a default postHandlers chain, which comprises of only
/ one decorator: the Transaction Tips decorator. However, some chains do
/ not need it by default, so feel free to comment the next line if you do
/ not need tips.
/ To read more about tips:
/ https://docs.cosmos.network/main/core/tips.html
/
/ Please note that changing any of the anteHandler or postHandler chain is
/ likely to be a state-machine breaking change, which needs a coordinated
/ upgrade.
app.setPostHandler()
if loadLatest {
if err := app.LoadLatestVersion(); err != nil {
logger.Error("error on loading last version", "err", err)
os.Exit(1)
}
}
return app
}
func (app *SimApp)
setAnteHandler(txConfig client.TxConfig) {
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: txConfig.SignModeHandler(),
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
if err != nil {
panic(err)
}
app.SetAnteHandler(anteHandler)
}
func (app *SimApp)
setPostHandler() {
postHandler, err := posthandler.NewPostHandler(
posthandler.HandlerOptions{
},
)
if err != nil {
panic(err)
}
app.SetPostHandler(postHandler)
}
/ 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.ModuleManager.BeginBlock(ctx, req)
}
/ EndBlocker application updates every end block
func (app *SimApp)
EndBlocker(ctx sdk.Context, req abci.RequestEndBlock)
abci.ResponseEndBlock {
return app.ModuleManager.EndBlock(ctx, req)
}
func (a *SimApp)
Configurator()
module.Configurator {
return a.configurator
}
/ 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.ModuleManager.GetVersionMap())
return app.ModuleManager.InitGenesis(ctx, app.appCodec, genesisState)
}
/ LoadHeight loads a particular height
func (app *SimApp)
LoadHeight(height int64)
error {
return app.LoadVersion(height)
}
/ 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
}
/ TxConfig returns SimApp's TxConfig
func (app *SimApp)
TxConfig()
client.TxConfig {
return app.txConfig
}
/ DefaultGenesis returns a default genesis from the registered AppModuleBasic's.
func (a *SimApp)
DefaultGenesis()
map[string]json.RawMessage {
return ModuleBasics.DefaultGenesis(a.appCodec)
}
/ 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 node gRPC service for grpc-gateway.
nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
/ Register grpc-gateway routes for all modules.
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
/ register swagger API from root so that other applications can override easily
if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
panic(err)
}
}
/ 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(
clientCtx,
app.BaseApp.GRPCQueryRouter(),
app.interfaceRegistry,
app.Query,
)
}
func (app *SimApp)
RegisterNodeService(clientCtx client.Context) {
nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter())
}
/ GetMaccPerms returns a copy of the module account permissions
/
/ NOTE: This is solely to be used for testing purposes.
func GetMaccPerms()
map[string][]string {
dupMaccPerms := make(map[string][]string)
for k, v := range maccPerms {
dupMaccPerms[k] = v
}
return dupMaccPerms
}
/ BlockedAddresses returns all the app's blocked account addresses.
func BlockedAddresses()
map[string]bool {
modAccAddrs := make(map[string]bool)
for acc := range GetMaccPerms() {
modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
}
/ allow the following addresses to receive funds
delete(modAccAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String())
return modAccAddrs
}
/ 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(govv1.ParamKeyTable())
paramsKeeper.Subspace(crisistypes.ModuleName)
return paramsKeeper
}
func makeEncodingConfig()
simappparams.EncodingConfig {
encodingConfig := simappparams.MakeTestEncodingConfig()
std.RegisterLegacyAminoCodec(encodingConfig.Amino)
std.RegisterInterfaces(encodingConfig.InterfaceRegistry)
ModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino)
ModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry)
return encodingConfig
}
BeginBlocker and EndBlocker
The Cosmos SDK offers developers the possibility to implement automatic execution of code as part of their application. This is implemented through two functions calledBeginBlocker
and EndBlocker
. They are called when the application receives the BeginBlock
and EndBlock
messages from the CometBFT engine, which happens respectively at the beginning and at the end of each block. The application must set the BeginBlocker
and EndBlocker
in its constructor via the SetBeginBlocker
and SetEndBlocker
methods.
In general, the BeginBlocker
and EndBlocker
functions are mostly composed of the BeginBlock
and EndBlock
functions of each of the application’s modules. This is done by calling the BeginBlock
and EndBlock
functions of the module manager, which in turn calls the BeginBlock
and EndBlock
functions of each of the modules it contains. Note that the order in which the modules’ BeginBlock
and EndBlock
functions must be called has to be set in the module manager using the SetOrderBeginBlockers
and SetOrderEndBlockers
methods, respectively. This is done via the module manager in the application’s constructor, and the SetOrderBeginBlockers
and SetOrderEndBlockers
methods have to be called before the SetBeginBlocker
and SetEndBlocker
functions.
As a sidenote, it is important to remember that application-specific blockchains are deterministic. Developers must be careful not to introduce non-determinism in BeginBlocker
or EndBlocker
, and must also be careful not to make them too computationally expensive, as gas does not constrain the cost of BeginBlocker
and EndBlocker
execution.
See an example of BeginBlocker
and EndBlocker
functions from simapp
Copy
Ask AI
/go:build app_v1
package simapp
import (
"encoding/json"
"io"
"os"
"path/filepath"
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
"github.com/spf13/cast"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
simappparams "cosmossdk.io/simapp/params"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
"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/runtime"
runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
"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"
"github.com/cosmos/cosmos-sdk/std"
"github.com/cosmos/cosmos-sdk/store/streaming"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata_pulsar"
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"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/posthandler"
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"
consensus "github.com/cosmos/cosmos-sdk/x/consensus"
consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/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"
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"
govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
"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"
)
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.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),
bank.AppModuleBasic{
},
capability.AppModuleBasic{
},
staking.AppModuleBasic{
},
mint.AppModuleBasic{
},
distr.AppModuleBasic{
},
gov.NewAppModuleBasic(
[]govclient.ProposalHandler{
paramsclient.ProposalHandler,
upgradeclient.LegacyProposalHandler,
upgradeclient.LegacyCancelProposalHandler,
},
),
params.AppModuleBasic{
},
crisis.AppModuleBasic{
},
slashing.AppModuleBasic{
},
feegrantmodule.AppModuleBasic{
},
upgrade.AppModuleBasic{
},
evidence.AppModuleBasic{
},
authzmodule.AppModuleBasic{
},
groupmodule.AppModuleBasic{
},
vesting.AppModuleBasic{
},
nftmodule.AppModuleBasic{
},
consensus.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 (
_ runtime.AppI = (*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
txConfig client.TxConfig
interfaceRegistry types.InterfaceRegistry
/ 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
ConsensusParamsKeeper consensusparamkeeper.Keeper
/ the module manager
ModuleManager *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,
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
encodingConfig := makeEncodingConfig()
appCodec := encodingConfig.Codec
legacyAmino := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
txConfig := encodingConfig.TxConfig
/ Below we could construct and set an application specific mempool and ABCI 1.0 Prepare and Process Proposal
/ handlers. These defaults are already set in the SDK's BaseApp, this shows an example of how to override
/ them.
/
/ nonceMempool := mempool.NewSenderNonceMempool()
/ mempoolOpt := baseapp.SetMempool(nonceMempool)
/ prepareOpt := func(app *baseapp.BaseApp) {
/ app.SetPrepareProposal(app.DefaultPrepareProposal())
/
}
/ processOpt := func(app *baseapp.BaseApp) {
/ app.SetProcessProposal(app.DefaultProcessProposal())
/
}
/
/ Further down we'd set the options in the AppBuilder like below.
/ baseAppOptions = append(baseAppOptions, mempoolOpt, prepareOpt, processOpt)
bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseAppOptions...)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
bApp.SetInterfaceRegistry(interfaceRegistry)
bApp.SetTxEncoder(txConfig.TxEncoder())
keys := sdk.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, crisistypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, paramstypes.StoreKey, consensusparamtypes.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")
/ load state streaming if enabled
if _, _, err := streaming.LoadStreamingServices(bApp, appOpts, appCodec, logger, keys); err != nil {
logger.Error("failed to load state streaming", "err", err)
os.Exit(1)
}
app := &SimApp{
BaseApp: bApp,
legacyAmino: legacyAmino,
appCodec: appCodec,
txConfig: txConfig,
interfaceRegistry: interfaceRegistry,
keys: keys,
tkeys: tkeys,
memKeys: memKeys,
}
app.ParamsKeeper = initParamsKeeper(appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
/ set the BaseApp's parameter store
app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(appCodec, keys[upgradetypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String())
bApp.SetParamStore(&app.ConsensusParamsKeeper)
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], authtypes.ProtoBaseAccount, maccPerms, sdk.Bech32MainPrefix, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec,
keys[banktypes.StoreKey],
app.AccountKeeper,
BlockedAddresses(),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
app.StakingKeeper = stakingkeeper.NewKeeper(
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
app.MintKeeper = mintkeeper.NewKeeper(appCodec, keys[minttypes.StoreKey], app.StakingKeeper, app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.DistrKeeper = distrkeeper.NewKeeper(appCodec, keys[distrtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.StakingKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec, legacyAmino, keys[slashingtypes.StoreKey], app.StakingKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
invCheckPeriod := cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod))
app.CrisisKeeper = crisiskeeper.NewKeeper(appCodec, keys[crisistypes.StoreKey], invCheckPeriod,
app.BankKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
/ register the staking hooks
/ NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper.SetHooks(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper)
groupConfig := group.DefaultConfig()
/*
Example of setting group params:
groupConfig.MaxMetadataLen = 1000
*/
app.GroupKeeper = groupkeeper.NewKeeper(keys[group.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper, groupConfig)
/ get skipUpgradeHeights from the app options
skipUpgradeHeights := map[int64]bool{
}
for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) {
skipUpgradeHeights[int64(h)] = true
}
homePath := cast.ToString(appOpts.Get(flags.FlagHome))
/ set the governance module account as the authority for conducting upgrades
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp, authtypes.NewModuleAddress(govtypes.ModuleName).String())
/ Register the proposal types
/ Deprecated: Avoid adding new handlers, instead use the new proposal flow
/ by granting the governance module the right to execute the message.
/ See: https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/gov/spec/01_concepts.md#proposal-messages
govRouter := govv1beta1.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
govConfig := govtypes.DefaultConfig()
/*
Example of setting gov params:
govConfig.MaxMetadataLen = 10000
*/
govKeeper := govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.AccountKeeper, app.BankKeeper,
app.StakingKeeper, app.MsgServiceRouter(), govConfig, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
/ Set legacy router for backwards compatibility with gov v1beta1
govKeeper.SetLegacyRouter(govRouter)
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.
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.ModuleManager = module.NewManager(
genutil.NewAppModule(
app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx,
encodingConfig.TxConfig,
),
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)),
capability.NewAppModule(appCodec, *app.CapabilityKeeper, false),
crisis.NewAppModule(app.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, app.GetSubspace(minttypes.ModuleName)),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(slashingtypes.ModuleName)),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)),
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),
consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
)
/ 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.ModuleManager.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, consensusparamtypes.ModuleName,
)
app.ModuleManager.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, consensusparamtypes.ModuleName,
)
/ NOTE: The genutils module must occur after staking so that pools are
/ properly initialized with tokens from genesis accounts.
/ NOTE: The genutils module must also occur after auth so that it can access the params from auth.
/ 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.
genesisModuleOrder := []string{
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, consensusparamtypes.ModuleName,
}
app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)
app.ModuleManager.SetOrderExportGenesis(genesisModuleOrder...)
/ Uncomment if you want to set a custom migration order here.
/ app.ModuleManager.SetOrderMigrations(custom order)
app.ModuleManager.RegisterInvariants(app.CrisisKeeper)
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
app.ModuleManager.RegisterServices(app.configurator)
/ RegisterUpgradeHandlers is used for registering any on-chain upgrades.
/ Make sure it's called after `app.ModuleManager` and `app.configurator` are set.
app.RegisterUpgradeHandlers()
autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules))
reflectionSvc, err := runtimeservices.NewReflectionService()
if err != nil {
panic(err)
}
reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc)
/ add test gRPC service for testing gRPC queries in isolation
testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.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
overrideModules := map[string]module.AppModuleSimulation{
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
}
app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)
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.setAnteHandler(encodingConfig.TxConfig)
/ In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
/ antehandlers, but are run _after_ the `runMsgs` execution. They are also
/ defined as a chain, and have the same signature as antehandlers.
/
/ In baseapp, postHandlers are run in the same store branch as `runMsgs`,
/ meaning that both `runMsgs` and `postHandler` state will be committed if
/ both are successful, and both will be reverted if any of the two fails.
/
/ The SDK exposes a default postHandlers chain, which comprises of only
/ one decorator: the Transaction Tips decorator. However, some chains do
/ not need it by default, so feel free to comment the next line if you do
/ not need tips.
/ To read more about tips:
/ https://docs.cosmos.network/main/core/tips.html
/
/ Please note that changing any of the anteHandler or postHandler chain is
/ likely to be a state-machine breaking change, which needs a coordinated
/ upgrade.
app.setPostHandler()
if loadLatest {
if err := app.LoadLatestVersion(); err != nil {
logger.Error("error on loading last version", "err", err)
os.Exit(1)
}
}
return app
}
func (app *SimApp)
setAnteHandler(txConfig client.TxConfig) {
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: txConfig.SignModeHandler(),
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
if err != nil {
panic(err)
}
app.SetAnteHandler(anteHandler)
}
func (app *SimApp)
setPostHandler() {
postHandler, err := posthandler.NewPostHandler(
posthandler.HandlerOptions{
},
)
if err != nil {
panic(err)
}
app.SetPostHandler(postHandler)
}
/ 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.ModuleManager.BeginBlock(ctx, req)
}
/ EndBlocker application updates every end block
func (app *SimApp)
EndBlocker(ctx sdk.Context, req abci.RequestEndBlock)
abci.ResponseEndBlock {
return app.ModuleManager.EndBlock(ctx, req)
}
func (a *SimApp)
Configurator()
module.Configurator {
return a.configurator
}
/ 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.ModuleManager.GetVersionMap())
return app.ModuleManager.InitGenesis(ctx, app.appCodec, genesisState)
}
/ LoadHeight loads a particular height
func (app *SimApp)
LoadHeight(height int64)
error {
return app.LoadVersion(height)
}
/ 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
}
/ TxConfig returns SimApp's TxConfig
func (app *SimApp)
TxConfig()
client.TxConfig {
return app.txConfig
}
/ DefaultGenesis returns a default genesis from the registered AppModuleBasic's.
func (a *SimApp)
DefaultGenesis()
map[string]json.RawMessage {
return ModuleBasics.DefaultGenesis(a.appCodec)
}
/ 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 node gRPC service for grpc-gateway.
nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
/ Register grpc-gateway routes for all modules.
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
/ register swagger API from root so that other applications can override easily
if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
panic(err)
}
}
/ 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(
clientCtx,
app.BaseApp.GRPCQueryRouter(),
app.interfaceRegistry,
app.Query,
)
}
func (app *SimApp)
RegisterNodeService(clientCtx client.Context) {
nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter())
}
/ GetMaccPerms returns a copy of the module account permissions
/
/ NOTE: This is solely to be used for testing purposes.
func GetMaccPerms()
map[string][]string {
dupMaccPerms := make(map[string][]string)
for k, v := range maccPerms {
dupMaccPerms[k] = v
}
return dupMaccPerms
}
/ BlockedAddresses returns all the app's blocked account addresses.
func BlockedAddresses()
map[string]bool {
modAccAddrs := make(map[string]bool)
for acc := range GetMaccPerms() {
modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
}
/ allow the following addresses to receive funds
delete(modAccAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String())
return modAccAddrs
}
/ 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(govv1.ParamKeyTable())
paramsKeeper.Subspace(crisistypes.ModuleName)
return paramsKeeper
}
func makeEncodingConfig()
simappparams.EncodingConfig {
encodingConfig := simappparams.MakeTestEncodingConfig()
std.RegisterLegacyAminoCodec(encodingConfig.Amino)
std.RegisterInterfaces(encodingConfig.InterfaceRegistry)
ModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino)
ModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry)
return encodingConfig
}
Register Codec
TheEncodingConfig
structure is the last important part of the app.go
file. The goal of this structure is to define the codecs that will be used throughout the app.
Copy
Ask AI
package params
import (
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/codec/types"
)
/ EncodingConfig specifies the concrete encoding types to use for a given app.
/ This is provided for compatibility between protobuf and amino implementations.
type EncodingConfig struct {
InterfaceRegistry types.InterfaceRegistry
Codec codec.Codec
TxConfig client.TxConfig
Amino *codec.LegacyAmino
}
InterfaceRegistry
: TheInterfaceRegistry
is used by the Protobuf codec to handle interfaces that are encoded and decoded (we also say “unpacked”) usinggoogle.protobuf.Any
.Any
could be thought as a struct that contains atype_url
(name of a concrete type implementing the interface) and avalue
(its encoded bytes).InterfaceRegistry
provides a mechanism for registering interfaces and implementations that can be safely unpacked fromAny
. Each application module implements theRegisterInterfaces
method that can be used to register the module’s own interfaces and implementations.- You can read more about
Any
in ADR-019. - To go more into details, the Cosmos SDK uses an implementation of the Protobuf specification called
gogoprotobuf
. By default, the gogo protobuf implementation ofAny
uses global type registration to decode values packed inAny
into concrete Go types. This introduces a vulnerability where any malicious module in the dependency tree could register a type with the global protobuf registry and cause it to be loaded and unmarshaled by a transaction that referenced it in thetype_url
field. For more information, please refer to ADR-019.
- You can read more about
Codec
: The default codec used throughout the Cosmos SDK. It is composed of aBinaryCodec
used to encode and decode state, and aJSONCodec
used to output data to the users (for example, in the CLI). By default, the SDK uses Protobuf asCodec
.TxConfig
:TxConfig
defines an interface a client can utilize to generate an application-defined concrete transaction type. Currently, the SDK handles two transaction types:SIGN_MODE_DIRECT
(which uses Protobuf binary as over-the-wire encoding) andSIGN_MODE_LEGACY_AMINO_JSON
(which depends on Amino). Read more about transactions here.Amino
: Some legacy parts of the Cosmos SDK still use Amino for backwards-compatibility. Each module exposes aRegisterLegacyAmino
method to register the module’s specific types within Amino. ThisAmino
codec should not be used by app developers anymore, and will be removed in future releases.
simappparams.EncodingConfig
from simapp
:
Copy
Ask AI
/go:build app_v1
package simapp
import (
"encoding/json"
"io"
"os"
"path/filepath"
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
"github.com/spf13/cast"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
simappparams "cosmossdk.io/simapp/params"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
nodeservice "github.com/cosmos/cosmos-sdk/client/grpc/node"
"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/runtime"
runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services"
"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"
"github.com/cosmos/cosmos-sdk/std"
"github.com/cosmos/cosmos-sdk/store/streaming"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/testutil/testdata_pulsar"
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"
"github.com/cosmos/cosmos-sdk/x/auth/ante"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
"github.com/cosmos/cosmos-sdk/x/auth/posthandler"
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"
consensus "github.com/cosmos/cosmos-sdk/x/consensus"
consensusparamkeeper "github.com/cosmos/cosmos-sdk/x/consensus/keeper"
consensusparamtypes "github.com/cosmos/cosmos-sdk/x/consensus/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"
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"
govclient "github.com/cosmos/cosmos-sdk/x/gov/client"
govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1"
govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1"
"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"
)
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.NewAppModuleBasic(genutiltypes.DefaultMessageValidator),
bank.AppModuleBasic{
},
capability.AppModuleBasic{
},
staking.AppModuleBasic{
},
mint.AppModuleBasic{
},
distr.AppModuleBasic{
},
gov.NewAppModuleBasic(
[]govclient.ProposalHandler{
paramsclient.ProposalHandler,
upgradeclient.LegacyProposalHandler,
upgradeclient.LegacyCancelProposalHandler,
},
),
params.AppModuleBasic{
},
crisis.AppModuleBasic{
},
slashing.AppModuleBasic{
},
feegrantmodule.AppModuleBasic{
},
upgrade.AppModuleBasic{
},
evidence.AppModuleBasic{
},
authzmodule.AppModuleBasic{
},
groupmodule.AppModuleBasic{
},
vesting.AppModuleBasic{
},
nftmodule.AppModuleBasic{
},
consensus.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 (
_ runtime.AppI = (*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
txConfig client.TxConfig
interfaceRegistry types.InterfaceRegistry
/ 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
ConsensusParamsKeeper consensusparamkeeper.Keeper
/ the module manager
ModuleManager *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,
appOpts servertypes.AppOptions,
baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
encodingConfig := makeEncodingConfig()
appCodec := encodingConfig.Codec
legacyAmino := encodingConfig.Amino
interfaceRegistry := encodingConfig.InterfaceRegistry
txConfig := encodingConfig.TxConfig
/ Below we could construct and set an application specific mempool and ABCI 1.0 Prepare and Process Proposal
/ handlers. These defaults are already set in the SDK's BaseApp, this shows an example of how to override
/ them.
/
/ nonceMempool := mempool.NewSenderNonceMempool()
/ mempoolOpt := baseapp.SetMempool(nonceMempool)
/ prepareOpt := func(app *baseapp.BaseApp) {
/ app.SetPrepareProposal(app.DefaultPrepareProposal())
/
}
/ processOpt := func(app *baseapp.BaseApp) {
/ app.SetProcessProposal(app.DefaultProcessProposal())
/
}
/
/ Further down we'd set the options in the AppBuilder like below.
/ baseAppOptions = append(baseAppOptions, mempoolOpt, prepareOpt, processOpt)
bApp := baseapp.NewBaseApp(appName, logger, db, txConfig.TxDecoder(), baseAppOptions...)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
bApp.SetInterfaceRegistry(interfaceRegistry)
bApp.SetTxEncoder(txConfig.TxEncoder())
keys := sdk.NewKVStoreKeys(
authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, crisistypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, paramstypes.StoreKey, consensusparamtypes.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")
/ load state streaming if enabled
if _, _, err := streaming.LoadStreamingServices(bApp, appOpts, appCodec, logger, keys); err != nil {
logger.Error("failed to load state streaming", "err", err)
os.Exit(1)
}
app := &SimApp{
BaseApp: bApp,
legacyAmino: legacyAmino,
appCodec: appCodec,
txConfig: txConfig,
interfaceRegistry: interfaceRegistry,
keys: keys,
tkeys: tkeys,
memKeys: memKeys,
}
app.ParamsKeeper = initParamsKeeper(appCodec, legacyAmino, keys[paramstypes.StoreKey], tkeys[paramstypes.TStoreKey])
/ set the BaseApp's parameter store
app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper(appCodec, keys[upgradetypes.StoreKey], authtypes.NewModuleAddress(govtypes.ModuleName).String())
bApp.SetParamStore(&app.ConsensusParamsKeeper)
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], authtypes.ProtoBaseAccount, maccPerms, sdk.Bech32MainPrefix, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.BankKeeper = bankkeeper.NewBaseKeeper(
appCodec,
keys[banktypes.StoreKey],
app.AccountKeeper,
BlockedAddresses(),
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
app.StakingKeeper = stakingkeeper.NewKeeper(
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
app.MintKeeper = mintkeeper.NewKeeper(appCodec, keys[minttypes.StoreKey], app.StakingKeeper, app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.DistrKeeper = distrkeeper.NewKeeper(appCodec, keys[distrtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.StakingKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec, legacyAmino, keys[slashingtypes.StoreKey], app.StakingKeeper, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
invCheckPeriod := cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod))
app.CrisisKeeper = crisiskeeper.NewKeeper(appCodec, keys[crisistypes.StoreKey], invCheckPeriod,
app.BankKeeper, authtypes.FeeCollectorName, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
/ register the staking hooks
/ NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper.SetHooks(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)
app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper)
groupConfig := group.DefaultConfig()
/*
Example of setting group params:
groupConfig.MaxMetadataLen = 1000
*/
app.GroupKeeper = groupkeeper.NewKeeper(keys[group.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper, groupConfig)
/ get skipUpgradeHeights from the app options
skipUpgradeHeights := map[int64]bool{
}
for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) {
skipUpgradeHeights[int64(h)] = true
}
homePath := cast.ToString(appOpts.Get(flags.FlagHome))
/ set the governance module account as the authority for conducting upgrades
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp, authtypes.NewModuleAddress(govtypes.ModuleName).String())
/ Register the proposal types
/ Deprecated: Avoid adding new handlers, instead use the new proposal flow
/ by granting the governance module the right to execute the message.
/ See: https://github.com/cosmos/cosmos-sdk/blob/release/v0.46.x/x/gov/spec/01_concepts.md#proposal-messages
govRouter := govv1beta1.NewRouter()
govRouter.AddRoute(govtypes.RouterKey, govv1beta1.ProposalHandler).
AddRoute(paramproposal.RouterKey, params.NewParamChangeProposalHandler(app.ParamsKeeper)).
AddRoute(upgradetypes.RouterKey, upgrade.NewSoftwareUpgradeProposalHandler(app.UpgradeKeeper))
govConfig := govtypes.DefaultConfig()
/*
Example of setting gov params:
govConfig.MaxMetadataLen = 10000
*/
govKeeper := govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.AccountKeeper, app.BankKeeper,
app.StakingKeeper, app.MsgServiceRouter(), govConfig, authtypes.NewModuleAddress(govtypes.ModuleName).String(),
)
/ Set legacy router for backwards compatibility with gov v1beta1
govKeeper.SetLegacyRouter(govRouter)
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.
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.ModuleManager = module.NewManager(
genutil.NewAppModule(
app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx,
encodingConfig.TxConfig,
),
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper, app.GetSubspace(banktypes.ModuleName)),
capability.NewAppModule(appCodec, *app.CapabilityKeeper, false),
crisis.NewAppModule(app.CrisisKeeper, skipGenesisInvariants, app.GetSubspace(crisistypes.ModuleName)),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, &app.GovKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(govtypes.ModuleName)),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil, app.GetSubspace(minttypes.ModuleName)),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(slashingtypes.ModuleName)),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper, app.GetSubspace(distrtypes.ModuleName)),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName)),
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),
consensus.NewAppModule(appCodec, app.ConsensusParamsKeeper),
)
/ 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.ModuleManager.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, consensusparamtypes.ModuleName,
)
app.ModuleManager.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, consensusparamtypes.ModuleName,
)
/ NOTE: The genutils module must occur after staking so that pools are
/ properly initialized with tokens from genesis accounts.
/ NOTE: The genutils module must also occur after auth so that it can access the params from auth.
/ 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.
genesisModuleOrder := []string{
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, consensusparamtypes.ModuleName,
}
app.ModuleManager.SetOrderInitGenesis(genesisModuleOrder...)
app.ModuleManager.SetOrderExportGenesis(genesisModuleOrder...)
/ Uncomment if you want to set a custom migration order here.
/ app.ModuleManager.SetOrderMigrations(custom order)
app.ModuleManager.RegisterInvariants(app.CrisisKeeper)
app.configurator = module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter())
app.ModuleManager.RegisterServices(app.configurator)
/ RegisterUpgradeHandlers is used for registering any on-chain upgrades.
/ Make sure it's called after `app.ModuleManager` and `app.configurator` are set.
app.RegisterUpgradeHandlers()
autocliv1.RegisterQueryServer(app.GRPCQueryRouter(), runtimeservices.NewAutoCLIQueryService(app.ModuleManager.Modules))
reflectionSvc, err := runtimeservices.NewReflectionService()
if err != nil {
panic(err)
}
reflectionv1.RegisterReflectionServiceServer(app.GRPCQueryRouter(), reflectionSvc)
/ add test gRPC service for testing gRPC queries in isolation
testdata_pulsar.RegisterQueryServer(app.GRPCQueryRouter(), testdata_pulsar.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
overrideModules := map[string]module.AppModuleSimulation{
authtypes.ModuleName: auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts, app.GetSubspace(authtypes.ModuleName)),
}
app.sm = module.NewSimulationManagerFromAppModules(app.ModuleManager.Modules, overrideModules)
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.setAnteHandler(encodingConfig.TxConfig)
/ In v0.46, the SDK introduces _postHandlers_. PostHandlers are like
/ antehandlers, but are run _after_ the `runMsgs` execution. They are also
/ defined as a chain, and have the same signature as antehandlers.
/
/ In baseapp, postHandlers are run in the same store branch as `runMsgs`,
/ meaning that both `runMsgs` and `postHandler` state will be committed if
/ both are successful, and both will be reverted if any of the two fails.
/
/ The SDK exposes a default postHandlers chain, which comprises of only
/ one decorator: the Transaction Tips decorator. However, some chains do
/ not need it by default, so feel free to comment the next line if you do
/ not need tips.
/ To read more about tips:
/ https://docs.cosmos.network/main/core/tips.html
/
/ Please note that changing any of the anteHandler or postHandler chain is
/ likely to be a state-machine breaking change, which needs a coordinated
/ upgrade.
app.setPostHandler()
if loadLatest {
if err := app.LoadLatestVersion(); err != nil {
logger.Error("error on loading last version", "err", err)
os.Exit(1)
}
}
return app
}
func (app *SimApp)
setAnteHandler(txConfig client.TxConfig) {
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: txConfig.SignModeHandler(),
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
if err != nil {
panic(err)
}
app.SetAnteHandler(anteHandler)
}
func (app *SimApp)
setPostHandler() {
postHandler, err := posthandler.NewPostHandler(
posthandler.HandlerOptions{
},
)
if err != nil {
panic(err)
}
app.SetPostHandler(postHandler)
}
/ 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.ModuleManager.BeginBlock(ctx, req)
}
/ EndBlocker application updates every end block
func (app *SimApp)
EndBlocker(ctx sdk.Context, req abci.RequestEndBlock)
abci.ResponseEndBlock {
return app.ModuleManager.EndBlock(ctx, req)
}
func (a *SimApp)
Configurator()
module.Configurator {
return a.configurator
}
/ 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.ModuleManager.GetVersionMap())
return app.ModuleManager.InitGenesis(ctx, app.appCodec, genesisState)
}
/ LoadHeight loads a particular height
func (app *SimApp)
LoadHeight(height int64)
error {
return app.LoadVersion(height)
}
/ 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
}
/ TxConfig returns SimApp's TxConfig
func (app *SimApp)
TxConfig()
client.TxConfig {
return app.txConfig
}
/ DefaultGenesis returns a default genesis from the registered AppModuleBasic's.
func (a *SimApp)
DefaultGenesis()
map[string]json.RawMessage {
return ModuleBasics.DefaultGenesis(a.appCodec)
}
/ 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 node gRPC service for grpc-gateway.
nodeservice.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
/ Register grpc-gateway routes for all modules.
ModuleBasics.RegisterGRPCGatewayRoutes(clientCtx, apiSvr.GRPCGatewayRouter)
/ register swagger API from root so that other applications can override easily
if err := server.RegisterSwaggerAPI(apiSvr.ClientCtx, apiSvr.Router, apiConfig.Swagger); err != nil {
panic(err)
}
}
/ 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(
clientCtx,
app.BaseApp.GRPCQueryRouter(),
app.interfaceRegistry,
app.Query,
)
}
func (app *SimApp)
RegisterNodeService(clientCtx client.Context) {
nodeservice.RegisterNodeService(clientCtx, app.GRPCQueryRouter())
}
/ GetMaccPerms returns a copy of the module account permissions
/
/ NOTE: This is solely to be used for testing purposes.
func GetMaccPerms()
map[string][]string {
dupMaccPerms := make(map[string][]string)
for k, v := range maccPerms {
dupMaccPerms[k] = v
}
return dupMaccPerms
}
/ BlockedAddresses returns all the app's blocked account addresses.
func BlockedAddresses()
map[string]bool {
modAccAddrs := make(map[string]bool)
for acc := range GetMaccPerms() {
modAccAddrs[authtypes.NewModuleAddress(acc).String()] = true
}
/ allow the following addresses to receive funds
delete(modAccAddrs, authtypes.NewModuleAddress(govtypes.ModuleName).String())
return modAccAddrs
}
/ 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(govv1.ParamKeyTable())
paramsKeeper.Subspace(crisistypes.ModuleName)
return paramsKeeper
}
func makeEncodingConfig()
simappparams.EncodingConfig {
encodingConfig := simappparams.MakeTestEncodingConfig()
std.RegisterLegacyAminoCodec(encodingConfig.Amino)
std.RegisterInterfaces(encodingConfig.InterfaceRegistry)
ModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino)
ModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry)
return encodingConfig
}
Modules
Modules are the heart and soul of Cosmos SDK applications. They can be considered as state-machines nested within the state-machine. When a transaction is relayed from the underlying CometBFT engine via the ABCI to the application, it is routed bybaseapp
to the appropriate module in order to be processed. This paradigm enables developers to easily build complex state-machines, as most of the modules they need often already exist. For developers, most of the work involved in building a Cosmos SDK application revolves around building custom modules required by their application that do not exist yet, and integrating them with modules that do already exist into one coherent application. In the application directory, the standard practice is to store modules in the x/
folder (not to be confused with the Cosmos SDK’s x/
folder, which contains already-built modules).
Application Module Interface
Modules must implement interfaces defined in the Cosmos SDK,AppModuleBasic
and AppModule
. The former implements basic non-dependent elements of the module, such as the codec
, while the latter handles the bulk of the module methods (including methods that require references to other modules’ keeper
s). Both the AppModule
and AppModuleBasic
types are, by convention, defined in a file called module.go
.
AppModule
exposes a collection of useful methods on the module that facilitates the composition of modules into a coherent application. These methods are called from the module manager
, which manages the application’s collection of modules.
Msg
Services
Each application module defines two Protobuf services: one Msg
service to handle messages, and one gRPC Query
service to handle queries. If we consider the module as a state-machine, then a Msg
service is a set of state transition RPC methods.
Each Protobuf Msg
service method is 1:1 related to a Protobuf request type, which must implement sdk.Msg
interface.
Note that sdk.Msg
s are bundled in transactions, and each transaction contains one or multiple messages.
When a valid block of transactions is received by the full-node, CometBFT relays each one to the application via DeliverTx
. Then, the application handles the transaction:
- Upon receiving the transaction, the application first unmarshalls it from
[]byte
. - Then, it verifies a few things about the transaction like fee payment and signatures before extracting the
Msg
(s) contained in the transaction. sdk.Msg
s are encoded using ProtobufAny
s. By analyzing eachAny
’stype_url
, baseapp’smsgServiceRouter
routes thesdk.Msg
to the corresponding module’sMsg
service.- If the message is successfully processed, the state is updated.
Msg
services when they build their own module. The general practice is to define the Msg
Protobuf service in a tx.proto
file. For example, the x/bank
module defines a service with two methods to transfer tokens:
Copy
Ask AI
// Msg defines the bank Msg service.
service Msg {
option (cosmos.msg.v1.service) = true;
// Send defines a method for sending coins from one account to another account.
rpc Send(MsgSend) returns (MsgSendResponse);
// MultiSend defines a method for sending coins from some accounts to other accounts.
rpc MultiSend(MsgMultiSend) returns (MsgMultiSendResponse);
// UpdateParams defines a governance operation for updating the x/bank module parameters.
// The authority is defined in the keeper.
//
// Since: cosmos-sdk 0.47
rpc UpdateParams(MsgUpdateParams) returns (MsgUpdateParamsResponse);
// SetSendEnabled is a governance operation for setting the SendEnabled flag
// on any number of Denoms. Only the entries to add or update should be
// included. Entries that already exist in the store, but that aren't
// included in this message, will be left unchanged.
//
// Since: cosmos-sdk 0.47
rpc SetSendEnabled(MsgSetSendEnabled) returns (MsgSetSendEnabledResponse);
}
keeper
in order to update the module state.
Each module should also implement the RegisterServices
method as part of the AppModule
interface. This method should call the RegisterMsgServer
function provided by the generated Protobuf code.
gRPC Query
Services
gRPC Query
services allow users to query the state using gRPC. They are enabled by default, and can be configured under the grpc.enable
and grpc.address
fields inside app.toml
.
gRPC Query
services are defined in the module’s Protobuf definition files, specifically inside query.proto
. The query.proto
definition file exposes a single Query
Protobuf service. Each gRPC query endpoint corresponds to a service method, starting with the rpc
keyword, inside the Query
service.
Protobuf generates a QueryServer
interface for each module, containing all the service methods. A module’s keeper
then needs to implement this QueryServer
interface, by providing the concrete implementation of each service method. This concrete implementation is the handler of the corresponding gRPC query endpoint.
Finally, each module should also implement the RegisterServices
method as part of the AppModule
interface. This method should call the RegisterQueryServer
function provided by the generated Protobuf code.
Keeper
Keepers
are the gatekeepers of their module’s store(s). To read or write in a module’s store, it is mandatory to go through one of its keeper
’s methods. This is ensured by the object-capabilities model of the Cosmos SDK. Only objects that hold the key to a store can access it, and only the module’s keeper
should hold the key(s) to the module’s store(s).
Keepers
are generally defined in a file called keeper.go
. It contains the keeper
’s type definition and methods.
The keeper
type definition generally consists of the following:
- Key(s) to the module’s store(s) in the multistore.
- Reference to other module’s
keepers
. Only needed if thekeeper
needs to access other module’s store(s) (either to read or write from them). - A reference to the application’s codec. The
keeper
needs it to marshal structs before storing them, or to unmarshal them when it retrieves them, because stores only accept[]bytes
as value.
keeper.go
file is the keeper
’s constructor function, NewKeeper
. This function instantiates a new keeper
of the type defined above with a codec
, stores keys
and potentially references other modules’ keeper
s as parameters. The NewKeeper
function is called from the application’s constructor. The rest of the file defines the keeper
’s methods, which are primarily getters and setters.
Command-Line, gRPC Services and REST Interfaces
Each module defines command-line commands, gRPC services, and REST routes to be exposed to the end-user via the application’s interfaces. This enables end-users to create messages of the types defined in the module, or to query the subset of the state managed by the module.CLI
Generally, the commands related to a module are defined in a folder calledclient/cli
in the module’s folder. The CLI divides commands into two categories, transactions and queries, defined in client/cli/tx.go
and client/cli/query.go
, respectively. Both commands are built on top of the Cobra Library:
- Transactions commands let users generate new transactions so that they can be included in a block and eventually update the state. One command should be created for each defined in the module. The command calls the constructor of the message with the parameters provided by the end-user, and wraps it into a transaction. The Cosmos SDK handles signing and the addition of other transaction metadata.
- Queries let users query the subset of the state defined by the module. Query commands forward queries to the application’s query router, which routes them to the appropriate the
queryRoute
parameter supplied.
gRPC
gRPC is a modern open-source high performance RPC framework that has support in multiple languages. It is the recommended way for external clients (such as wallets, browsers and other backend services) to interact with a node. Each module can expose gRPC endpoints called service methods, which are defined in the module’s Protobufquery.proto
file. A service method is defined by its name, input arguments, and output response. The module then needs to perform the following actions:
- Define a
RegisterGRPCGatewayRoutes
method onAppModuleBasic
to wire the client gRPC requests to the correct handler inside the module. - For each service method, define a corresponding handler. The handler implements the core logic necessary to serve the gRPC request, and is located in the
keeper/grpc_query.go
file.
gRPC-gateway REST Endpoints
Some external clients may not wish to use gRPC. In this case, the Cosmos SDK provides a gRPC gateway service, which exposes each gRPC service as a corresponding REST endpoint. Please refer to the grpc-gateway documentation to learn more. The REST endpoints are defined in the Protobuf files, along with the gRPC services, using Protobuf annotations. Modules that want to expose REST queries should addgoogle.api.http
annotations to their rpc
methods. By default, all REST endpoints defined in the SDK have a URL starting with the /cosmos/
prefix.
The Cosmos SDK also provides a development endpoint to generate Swagger definition files for these REST endpoints. This endpoint can be enabled inside the app.toml
config file, under the api.swagger
key.
Application Interface
Interfaces let end-users interact with full-node clients. This means querying data from the full-node or creating and sending new transactions to be relayed by the full-node and eventually included in a block. The main interface is the Command-Line Interface. The CLI of a Cosmos SDK application is built by aggregating CLI commands defined in each of the modules used by the application. The CLI of an application is the same as the daemon (e.g.appd
), and is defined in a file called appd/main.go
. The file contains the following:
- A
main()
function, which is executed to build theappd
interface client. This function prepares each command and adds them to therootCmd
before building them. At the root ofappd
, the function adds generic commands likestatus
,keys
, andconfig
, query commands, tx commands, andrest-server
. - Query commands, which are added by calling the
queryCmd
function. This function returns a Cobra command that contains the query commands defined in each of the application’s modules (passed as an array ofsdk.ModuleClients
from themain()
function), as well as some other lower level query commands such as block or validator queries. Query command are called by using the commandappd query [query]
of the CLI. - Transaction commands, which are added by calling the
txCmd
function. Similar toqueryCmd
, the function returns a Cobra command that contains the tx commands defined in each of the application’s modules, as well as lower level tx commands like transaction signing or broadcasting. Tx commands are called by using the commandappd tx [tx]
of the CLI.
Copy
Ask AI
package cmd
import (
"errors"
"io"
"os"
"path/filepath"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/config"
"github.com/cosmos/cosmos-sdk/client/debug"
"github.com/cosmos/cosmos-sdk/client/flags"
"github.com/cosmos/cosmos-sdk/client/keys"
"github.com/cosmos/cosmos-sdk/client/rpc"
"github.com/cosmos/cosmos-sdk/server"
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
servertypes "github.com/cosmos/cosmos-sdk/server/types"
"github.com/cosmos/cosmos-sdk/snapshots"
snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types"
"github.com/cosmos/cosmos-sdk/store"
sdk "github.com/cosmos/cosmos-sdk/types"
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
"github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/cosmos-sdk/x/crisis"
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
"github.com/spf13/cast"
"github.com/spf13/cobra"
tmcfg "github.com/tendermint/tendermint/config"
tmcli "github.com/tendermint/tendermint/libs/cli"
"github.com/tendermint/tendermint/libs/log"
dbm "github.com/tendermint/tm-db"
gaia "github.com/cosmos/gaia/v8/app"
"github.com/cosmos/gaia/v8/app/params"
)
/ NewRootCmd creates a new root command for simd. It is called once in the
/ main function.
func NewRootCmd() (*cobra.Command, params.EncodingConfig) {
encodingConfig := gaia.MakeTestEncodingConfig()
initClientCtx := client.Context{
}.
WithCodec(encodingConfig.Codec).
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
WithTxConfig(encodingConfig.TxConfig).
WithLegacyAmino(encodingConfig.Amino).
WithInput(os.Stdin).
WithAccountRetriever(types.AccountRetriever{
}).
WithHomeDir(gaia.DefaultNodeHome).
WithViper("")
rootCmd := &cobra.Command{
Use: "gaiad",
Short: "Stargate Cosmos Hub App",
PersistentPreRunE: func(cmd *cobra.Command, _ []string)
error {
initClientCtx, err := client.ReadPersistentCommandFlags(initClientCtx, cmd.Flags())
if err != nil {
return err
}
initClientCtx, err = config.ReadFromClientConfig(initClientCtx)
if err != nil {
return err
}
if err = client.SetCmdClientContextHandler(initClientCtx, cmd); err != nil {
return err
}
customTemplate, customGaiaConfig := initAppConfig()
customTMConfig := initTendermintConfig()
return server.InterceptConfigsPreRunHandler(cmd, customTemplate, customGaiaConfig, customTMConfig)
},
}
initRootCmd(rootCmd, encodingConfig)
return rootCmd, encodingConfig
}
/ initTendermintConfig helps to override default Tendermint Config values.
/ return tmcfg.DefaultConfig if no custom configuration is required for the application.
func initTendermintConfig() *tmcfg.Config {
cfg := tmcfg.DefaultConfig()
/ these values put a higher strain on node memory
/ cfg.P2P.MaxNumInboundPeers = 100
/ cfg.P2P.MaxNumOutboundPeers = 40
return cfg
}
func initAppConfig() (string, interface{
}) {
srvCfg := serverconfig.DefaultConfig()
srvCfg.StateSync.SnapshotInterval = 1000
srvCfg.StateSync.SnapshotKeepRecent = 10
return params.CustomConfigTemplate(), params.CustomAppConfig{
Config: *srvCfg,
BypassMinFeeMsgTypes: gaia.GetDefaultBypassFeeMessages(),
}
}
func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
cfg := sdk.GetConfig()
cfg.Seal()
rootCmd.AddCommand(
genutilcli.InitCmd(gaia.ModuleBasics, gaia.DefaultNodeHome),
genutilcli.CollectGenTxsCmd(banktypes.GenesisBalancesIterator{
}, gaia.DefaultNodeHome),
genutilcli.GenTxCmd(gaia.ModuleBasics, encodingConfig.TxConfig, banktypes.GenesisBalancesIterator{
}, gaia.DefaultNodeHome),
genutilcli.ValidateGenesisCmd(gaia.ModuleBasics),
AddGenesisAccountCmd(gaia.DefaultNodeHome),
tmcli.NewCompletionCmd(rootCmd, true),
testnetCmd(gaia.ModuleBasics, banktypes.GenesisBalancesIterator{
}),
debug.Cmd(),
config.Cmd(),
)
ac := appCreator{
encCfg: encodingConfig,
}
server.AddCommands(rootCmd, gaia.DefaultNodeHome, ac.newApp, ac.appExport, addModuleInitFlags)
/ add keybase, auxiliary RPC, query, and tx child commands
rootCmd.AddCommand(
rpc.StatusCommand(),
queryCommand(),
txCommand(),
keys.Commands(gaia.DefaultNodeHome),
)
rootCmd.AddCommand(server.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Codec))
}
func addModuleInitFlags(startCmd *cobra.Command) {
crisis.AddModuleInitFlags(startCmd)
}
func queryCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "query",
Aliases: []string{"q"
},
Short: "Querying subcommands",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
cmd.AddCommand(
authcmd.GetAccountCmd(),
rpc.ValidatorCommand(),
rpc.BlockCommand(),
authcmd.QueryTxsByEventsCmd(),
authcmd.QueryTxCmd(),
)
gaia.ModuleBasics.AddQueryCommands(cmd)
cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID")
return cmd
}
func txCommand() *cobra.Command {
cmd := &cobra.Command{
Use: "tx",
Short: "Transactions subcommands",
DisableFlagParsing: true,
SuggestionsMinimumDistance: 2,
RunE: client.ValidateCmd,
}
cmd.AddCommand(
authcmd.GetSignCommand(),
authcmd.GetSignBatchCommand(),
authcmd.GetMultiSignCommand(),
authcmd.GetMultiSignBatchCmd(),
authcmd.GetValidateSignaturesCommand(),
flags.LineBreak,
authcmd.GetBroadcastCommand(),
authcmd.GetEncodeCommand(),
authcmd.GetDecodeCommand(),
authcmd.GetAuxToFeeCommand(),
)
gaia.ModuleBasics.AddTxCommands(cmd)
cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID")
return cmd
}
type appCreator struct {
encCfg params.EncodingConfig
}
func (ac appCreator)
newApp(
logger log.Logger,
db dbm.DB,
traceStore io.Writer,
appOpts servertypes.AppOptions,
)
servertypes.Application {
var cache sdk.MultiStorePersistentCache
if cast.ToBool(appOpts.Get(server.FlagInterBlockCache)) {
cache = store.NewCommitKVStoreCacheManager()
}
skipUpgradeHeights := make(map[int64]bool)
for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) {
skipUpgradeHeights[int64(h)] = true
}
pruningOpts, err := server.GetPruningOptionsFromFlags(appOpts)
if err != nil {
panic(err)
}
snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots")
snapshotDB, err := dbm.NewDB("metadata", server.GetAppDBBackend(appOpts), snapshotDir)
if err != nil {
panic(err)
}
snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir)
if err != nil {
panic(err)
}
snapshotOptions := snapshottypes.NewSnapshotOptions(
cast.ToUint64(appOpts.Get(server.FlagStateSyncSnapshotInterval)),
cast.ToUint32(appOpts.Get(server.FlagStateSyncSnapshotKeepRecent)),
)
return gaia.NewGaiaApp(
logger, db, traceStore, true, skipUpgradeHeights,
cast.ToString(appOpts.Get(flags.FlagHome)),
cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)),
ac.encCfg,
appOpts,
baseapp.SetPruning(pruningOpts),
baseapp.SetMinGasPrices(cast.ToString(appOpts.Get(server.FlagMinGasPrices))),
baseapp.SetHaltHeight(cast.ToUint64(appOpts.Get(server.FlagHaltHeight))),
baseapp.SetHaltTime(cast.ToUint64(appOpts.Get(server.FlagHaltTime))),
baseapp.SetMinRetainBlocks(cast.ToUint64(appOpts.Get(server.FlagMinRetainBlocks))),
baseapp.SetInterBlockCache(cache),
baseapp.SetTrace(cast.ToBool(appOpts.Get(server.FlagTrace))),
baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(server.FlagIndexEvents))),
baseapp.SetSnapshot(snapshotStore, snapshotOptions),
)
}
func (ac appCreator)
appExport(
logger log.Logger,
db dbm.DB,
traceStore io.Writer,
height int64,
forZeroHeight bool,
jailAllowedAddrs []string,
appOpts servertypes.AppOptions,
) (servertypes.ExportedApp, error) {
homePath, ok := appOpts.Get(flags.FlagHome).(string)
if !ok || homePath == "" {
return servertypes.ExportedApp{
}, errors.New("application home is not set")
}
var loadLatest bool
if height == -1 {
loadLatest = true
}
gaiaApp := gaia.NewGaiaApp(
logger,
db,
traceStore,
loadLatest,
map[int64]bool{
},
homePath,
cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)),
ac.encCfg,
appOpts,
)
if height != -1 {
if err := gaiaApp.LoadHeight(height); err != nil {
return servertypes.ExportedApp{
}, err
}
}
return gaiaApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs)
}
Dependencies and Makefile
This section is optional, as developers are free to choose their dependency manager and project building method. That said, the current most used framework for versioning control isgo.mod
. It ensures each of the libraries used throughout the application are imported with the correct version.
The following is the go.mod
of the Cosmos Hub, provided as an example.
Copy
Ask AI
module github.com/cosmos/gaia/v8
go 1.18
require (
cosmossdk.io/math v1.0.0-beta.3
github.com/cosmos/cosmos-sdk v0.46.2
github.com/cosmos/go-bip39 v1.0.0 / indirect
github.com/cosmos/ibc-go/v5 v5.0.0
github.com/gogo/protobuf v1.3.3
github.com/golang/protobuf v1.5.2
github.com/golangci/golangci-lint v1.50.0
github.com/gorilla/mux v1.8.0
github.com/gravity-devs/liquidity/v2 v2.0.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/pkg/errors v0.9.1
github.com/rakyll/statik v0.1.7
github.com/spf13/cast v1.5.0
github.com/spf13/cobra v1.6.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.13.0
github.com/strangelove-ventures/packet-forward-middleware/v2 v2.1.4-0.20220802012200-5a62a55a7f1d
github.com/stretchr/testify v1.8.0
github.com/tendermint/tendermint v0.34.21
github.com/tendermint/tm-db v0.6.7
google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959
google.golang.org/grpc v1.50.0
)
require (
4d63.com/gochecknoglobals v0.1.0 / indirect
cloud.google.com/go v0.102.1 / indirect
cloud.google.com/go/compute v1.7.0 / indirect
cloud.google.com/go/iam v0.4.0 / indirect
cloud.google.com/go/storage v1.22.1 / indirect
cosmossdk.io/errors v1.0.0-beta.7 / indirect
filippo.io/edwards25519 v1.0.0-rc.1 / indirect
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 / indirect
github.com/99designs/keyring v1.2.1 / indirect
github.com/Abirdcfly/dupword v0.0.7 / indirect
github.com/Antonboom/errname v0.1.7 / indirect
github.com/Antonboom/nilnil v0.1.1 / indirect
github.com/BurntSushi/toml v1.2.0 / indirect
github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d / indirect
github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 / indirect
github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0 / indirect
github.com/Masterminds/semver v1.5.0 / indirect
github.com/OpenPeeDeeP/depguard v1.1.1 / indirect
github.com/Workiva/go-datastructures v1.0.53 / indirect
github.com/alexkohler/prealloc v1.0.0 / indirect
github.com/alingse/asasalint v0.0.11 / indirect
github.com/armon/go-metrics v0.4.0 / indirect
github.com/ashanbrown/forbidigo v1.3.0 / indirect
github.com/ashanbrown/makezero v1.1.1 / indirect
github.com/aws/aws-sdk-go v1.40.45 / indirect
github.com/beorn7/perks v1.0.1 / indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d / indirect
github.com/bgentry/speakeasy v0.1.0 / indirect
github.com/bkielbasa/cyclop v1.2.0 / indirect
github.com/blizzy78/varnamelen v0.8.0 / indirect
github.com/bombsimon/wsl/v3 v3.3.0 / indirect
github.com/breml/bidichk v0.2.3 / indirect
github.com/breml/errchkjson v0.3.0 / indirect
github.com/btcsuite/btcd v0.22.1 / indirect
github.com/butuzov/ireturn v0.1.1 / indirect
github.com/cenkalti/backoff/v4 v4.1.3 / indirect
github.com/cespare/xxhash v1.1.0 / indirect
github.com/cespare/xxhash/v2 v2.1.2 / indirect
github.com/charithe/durationcheck v0.0.9 / indirect
github.com/chavacava/garif v0.0.0-20220630083739-93517212f375 / indirect
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e / indirect
github.com/cockroachdb/apd/v2 v2.0.2 / indirect
github.com/coinbase/rosetta-sdk-go v0.7.9 / indirect
github.com/confio/ics23/go v0.7.0 / indirect
github.com/cosmos/btcutil v1.0.4 / indirect
github.com/cosmos/cosmos-proto v1.0.0-alpha7 / indirect
github.com/cosmos/gorocksdb v1.2.0 / indirect
github.com/cosmos/iavl v0.19.2-0.20220916140702-9b6be3095313 / indirect
github.com/cosmos/ledger-cosmos-go v0.11.1 / indirect
github.com/cosmos/ledger-go v0.9.3 / indirect
github.com/creachadair/taskgroup v0.3.2 / indirect
github.com/curioswitch/go-reassign v0.2.0 / indirect
github.com/daixiang0/gci v0.8.0 / indirect
github.com/danieljoos/wincred v1.1.2 / indirect
github.com/davecgh/go-spew v1.1.1 / indirect
github.com/denis-tingaikin/go-header v0.4.3 / indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f / indirect
github.com/dgraph-io/badger/v2 v2.2007.4 / indirect
github.com/dgraph-io/ristretto v0.1.0 / indirect
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 / indirect
github.com/dustin/go-humanize v1.0.0 / indirect
github.com/dvsekhvalnov/jose2go v1.5.0 / indirect
github.com/esimonov/ifshort v1.0.4 / indirect
github.com/ettle/strcase v0.1.1 / indirect
github.com/fatih/color v1.13.0 / indirect
github.com/fatih/structtag v1.2.0 / indirect
github.com/felixge/httpsnoop v1.0.1 / indirect
github.com/firefart/nonamedreturns v1.0.4 / indirect
github.com/fsnotify/fsnotify v1.5.4 / indirect
github.com/fzipp/gocyclo v0.6.0 / indirect
github.com/go-critic/go-critic v0.6.5 / indirect
github.com/go-kit/kit v0.12.0 / indirect
github.com/go-kit/log v0.2.1 / indirect
github.com/go-logfmt/logfmt v0.5.1 / indirect
github.com/go-playground/validator/v10 v10.4.1 / indirect
github.com/go-toolsmith/astcast v1.0.0 / indirect
github.com/go-toolsmith/astcopy v1.0.2 / indirect
github.com/go-toolsmith/astequal v1.0.3 / indirect
github.com/go-toolsmith/astfmt v1.0.0 / indirect
github.com/go-toolsmith/astp v1.0.0 / indirect
github.com/go-toolsmith/strparse v1.0.0 / indirect
github.com/go-toolsmith/typep v1.0.2 / indirect
github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b / indirect
github.com/gobwas/glob v0.2.3 / indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 / indirect
github.com/gofrs/flock v0.8.1 / indirect
github.com/gogo/gateway v1.1.0 / indirect
github.com/golang/glog v1.0.0 / indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da / indirect
github.com/golang/snappy v0.0.4 / indirect
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 / indirect
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a / indirect
github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe / indirect
github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2 / indirect
github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 / indirect
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca / indirect
github.com/golangci/misspell v0.3.5 / indirect
github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6 / indirect
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 / indirect
github.com/google/btree v1.0.1 / indirect
github.com/google/go-cmp v0.5.9 / indirect
github.com/google/orderedcode v0.0.1 / indirect
github.com/google/uuid v1.3.0 / indirect
github.com/googleapis/enterprise-certificate-proxy v0.1.0 / indirect
github.com/googleapis/gax-go/v2 v2.4.0 / indirect
github.com/googleapis/go-type-adapters v1.0.0 / indirect
github.com/gordonklaus/ineffassign v0.0.0-20210914165742-4cc7213b9bc8 / indirect
github.com/gorilla/handlers v1.5.1 / indirect
github.com/gorilla/websocket v1.5.0 / indirect
github.com/gostaticanalysis/analysisutil v0.7.1 / indirect
github.com/gostaticanalysis/comment v1.4.2 / indirect
github.com/gostaticanalysis/forcetypeassert v0.1.0 / indirect
github.com/gostaticanalysis/nilerr v0.1.1 / indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 / indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 / indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c / indirect
github.com/gtank/merlin v0.1.1 / indirect
github.com/gtank/ristretto255 v0.1.2 / indirect
github.com/hashicorp/errwrap v1.1.0 / indirect
github.com/hashicorp/go-cleanhttp v0.5.2 / indirect
github.com/hashicorp/go-getter v1.6.1 / indirect
github.com/hashicorp/go-immutable-radix v1.3.1 / indirect
github.com/hashicorp/go-multierror v1.1.1 / indirect
github.com/hashicorp/go-safetemp v1.0.0 / indirect
github.com/hashicorp/go-version v1.6.0 / indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d / indirect
github.com/hashicorp/hcl v1.0.0 / indirect
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 / indirect
github.com/hexops/gotextdiff v1.0.3 / indirect
github.com/improbable-eng/grpc-web v0.15.0 / indirect
github.com/inconshreveable/mousetrap v1.0.1 / indirect
github.com/jgautheron/goconst v1.5.1 / indirect
github.com/jingyugao/rowserrcheck v1.1.1 / indirect
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af / indirect
github.com/jmespath/go-jmespath v0.4.0 / indirect
github.com/jmhodges/levigo v1.0.0 / indirect
github.com/julz/importas v0.1.0 / indirect
github.com/kisielk/errcheck v1.6.2 / indirect
github.com/kisielk/gotool v1.0.0 / indirect
github.com/kkHAIKE/contextcheck v1.1.2 / indirect
github.com/klauspost/compress v1.15.9 / indirect
github.com/kulti/thelper v0.6.3 / indirect
github.com/kunwardeep/paralleltest v1.0.6 / indirect
github.com/kyoh86/exportloopref v0.1.8 / indirect
github.com/ldez/gomoddirectives v0.2.3 / indirect
github.com/ldez/tagliatelle v0.3.1 / indirect
github.com/leonklingele/grouper v1.1.0 / indirect
github.com/lib/pq v1.10.6 / indirect
github.com/libp2p/go-buffer-pool v0.1.0 / indirect
github.com/lufeee/execinquery v1.2.1 / indirect
github.com/magiconair/properties v1.8.6 / indirect
github.com/manifoldco/promptui v0.9.0 / indirect
github.com/maratori/testableexamples v1.0.0 / indirect
github.com/maratori/testpackage v1.1.0 / indirect
github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 / indirect
github.com/mattn/go-colorable v0.1.13 / indirect
github.com/mattn/go-isatty v0.0.16 / indirect
github.com/mattn/go-runewidth v0.0.9 / indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 / indirect
github.com/mbilski/exhaustivestruct v1.2.0 / indirect
github.com/mgechev/revive v1.2.4 / indirect
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 / indirect
github.com/minio/highwayhash v1.0.2 / indirect
github.com/mitchellh/go-homedir v1.1.0 / indirect
github.com/mitchellh/go-testing-interface v1.0.0 / indirect
github.com/mitchellh/mapstructure v1.5.0 / indirect
github.com/moricho/tparallel v0.2.1 / indirect
github.com/mtibben/percent v0.2.1 / indirect
github.com/nakabonne/nestif v0.3.1 / indirect
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 / indirect
github.com/nishanths/exhaustive v0.8.3 / indirect
github.com/nishanths/predeclared v0.2.2 / indirect
github.com/olekukonko/tablewriter v0.0.5 / indirect
github.com/pelletier/go-toml v1.9.5 / indirect
github.com/pelletier/go-toml/v2 v2.0.5 / indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 / indirect
github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d / indirect
github.com/pmezard/go-difflib v1.0.0 / indirect
github.com/polyfloyd/go-errorlint v1.0.5 / indirect
github.com/prometheus/client_golang v1.12.2 / indirect
github.com/prometheus/client_model v0.2.0 / indirect
github.com/prometheus/common v0.34.0 / indirect
github.com/prometheus/procfs v0.7.3 / indirect
github.com/quasilyte/go-ruleguard v0.3.18 / indirect
github.com/quasilyte/gogrep v0.0.0-20220828223005-86e4605de09f / indirect
github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 / indirect
github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 / indirect
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 / indirect
github.com/regen-network/cosmos-proto v0.3.1 / indirect
github.com/rs/cors v1.8.2 / indirect
github.com/rs/zerolog v1.27.0 / indirect
github.com/ryancurrah/gomodguard v1.2.4 / indirect
github.com/ryanrolds/sqlclosecheck v0.3.0 / indirect
github.com/sanposhiho/wastedassign/v2 v2.0.6 / indirect
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa / indirect
github.com/sashamelentyev/interfacebloat v1.1.0 / indirect
github.com/sashamelentyev/usestdlibvars v1.20.0 / indirect
github.com/securego/gosec/v2 v2.13.1 / indirect
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c / indirect
github.com/sirupsen/logrus v1.9.0 / indirect
github.com/sivchari/containedctx v1.0.2 / indirect
github.com/sivchari/nosnakecase v1.7.0 / indirect
github.com/sivchari/tenv v1.7.0 / indirect
github.com/sonatard/noctx v0.0.1 / indirect
github.com/sourcegraph/go-diff v0.6.1 / indirect
github.com/spf13/afero v1.8.2 / indirect
github.com/spf13/jwalterweatherman v1.1.0 / indirect
github.com/ssgreg/nlreturn/v2 v2.2.1 / indirect
github.com/stbenjam/no-sprintf-host-port v0.1.1 / indirect
github.com/stretchr/objx v0.4.0 / indirect
github.com/subosito/gotenv v1.4.1 / indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 / indirect
github.com/tdakkota/asciicheck v0.1.1 / indirect
github.com/tendermint/btcd v0.1.1 / indirect
github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 / indirect
github.com/tendermint/go-amino v0.16.0 / indirect
github.com/tetafro/godot v1.4.11 / indirect
github.com/timakin/bodyclose v0.0.0-20210704033933-f49887972144 / indirect
github.com/timonwong/loggercheck v0.9.3 / indirect
github.com/tomarrell/wrapcheck/v2 v2.6.2 / indirect
github.com/tommy-muehle/go-mnd/v2 v2.5.0 / indirect
github.com/ulikunitz/xz v0.5.8 / indirect
github.com/ultraware/funlen v0.0.3 / indirect
github.com/ultraware/whitespace v0.0.5 / indirect
github.com/uudashr/gocognit v1.0.6 / indirect
github.com/yagipy/maintidx v1.0.0 / indirect
github.com/yeya24/promlinter v0.2.0 / indirect
github.com/zondax/hid v0.9.1-0.20220302062450-5552068d2266 / indirect
gitlab.com/bosi/decorder v0.2.3 / indirect
go.etcd.io/bbolt v1.3.6 / indirect
go.opencensus.io v0.23.0 / indirect
go.uber.org/atomic v1.9.0 / indirect
go.uber.org/multierr v1.8.0 / indirect
go.uber.org/zap v1.21.0 / indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa / indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e / indirect
golang.org/x/exp/typeparams v0.0.0-20220827204233-334a2380cb91 / indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 / indirect
golang.org/x/net v0.0.0-20220726230323-06994584191e / indirect
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 / indirect
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde / indirect
golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 / indirect
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 / indirect
golang.org/x/text v0.3.7 / indirect
golang.org/x/tools v0.1.12 / indirect
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f / indirect
google.golang.org/api v0.93.0 / indirect
google.golang.org/appengine v1.6.7 / indirect
google.golang.org/protobuf v1.28.1 / indirect
gopkg.in/ini.v1 v1.67.0 / indirect
gopkg.in/yaml.v2 v2.4.0 / indirect
gopkg.in/yaml.v3 v3.0.1 / indirect
honnef.co/go/tools v0.3.3 / indirect
mvdan.cc/gofumpt v0.4.0 / indirect
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed / indirect
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b / indirect
mvdan.cc/unparam v0.0.0-20220706161116-678bad134442 / indirect
nhooyr.io/websocket v1.8.6 / indirect
sigs.k8s.io/yaml v1.3.0 / indirect
)
replace (
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
github.com/zondax/hid => github.com/zondax/hid v0.9.0
)
go.mod
is run before building the two entrypoints to the application, appd
and appd
.
Here is an example of the Cosmos Hub Makefile.