cosmos-sdk/cmd/gaia/app/app.go

389 lines
13 KiB
Go
Raw Normal View History

2018-04-06 22:12:00 -07:00
package app
import (
"fmt"
2018-10-22 11:59:00 -07:00
"io"
"os"
"sort"
2018-12-10 06:27:25 -08:00
abci "github.com/tendermint/tendermint/abci/types"
cmn "github.com/tendermint/tendermint/libs/common"
dbm "github.com/tendermint/tendermint/libs/db"
"github.com/tendermint/tendermint/libs/log"
// TODO: Remove once transfers are enabled.
gaiabank "github.com/cosmos/cosmos-sdk/cmd/gaia/app/x/bank"
2018-04-06 22:12:00 -07:00
bam "github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
2018-04-06 22:12:00 -07:00
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/auth"
"github.com/cosmos/cosmos-sdk/x/bank"
2018-09-17 20:02:15 -07:00
distr "github.com/cosmos/cosmos-sdk/x/distribution"
2018-06-21 17:19:14 -07:00
"github.com/cosmos/cosmos-sdk/x/gov"
2018-10-19 11:36:00 -07:00
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/cosmos/cosmos-sdk/x/params"
2018-05-23 13:25:56 -07:00
"github.com/cosmos/cosmos-sdk/x/slashing"
2019-01-11 12:08:01 -08:00
"github.com/cosmos/cosmos-sdk/x/staking"
2018-04-06 22:12:00 -07:00
)
const (
appName = "GaiaApp"
// DefaultKeyPass contains the default key password for genesis transactions
DefaultKeyPass = "12345678"
2018-04-06 22:12:00 -07:00
)
2018-04-25 21:27:40 -07:00
// default home directories for expected binaries
var (
DefaultCLIHome = os.ExpandEnv("$HOME/.gaiacli")
DefaultNodeHome = os.ExpandEnv("$HOME/.gaiad")
)
2018-04-06 22:12:00 -07:00
// Extended ABCI application
type GaiaApp struct {
*bam.BaseApp
cdc *codec.Codec
2018-04-06 22:12:00 -07:00
// keys to access the substores
2018-06-29 06:37:14 -07:00
keyMain *sdk.KVStoreKey
keyAccount *sdk.KVStoreKey
keyStaking *sdk.KVStoreKey
tkeyStaking *sdk.TransientStoreKey
2018-06-29 06:37:14 -07:00
keySlashing *sdk.KVStoreKey
2018-10-19 11:36:00 -07:00
keyMint *sdk.KVStoreKey
2018-09-17 20:02:15 -07:00
keyDistr *sdk.KVStoreKey
tkeyDistr *sdk.TransientStoreKey
2018-06-29 06:37:14 -07:00
keyGov *sdk.KVStoreKey
keyFeeCollection *sdk.KVStoreKey
keyParams *sdk.KVStoreKey
2018-07-26 18:24:18 -07:00
tkeyParams *sdk.TransientStoreKey
2018-04-06 22:12:00 -07:00
// Manage getting and setting accounts
accountKeeper auth.AccountKeeper
2018-05-25 20:29:40 -07:00
feeCollectionKeeper auth.FeeCollectionKeeper
bankKeeper bank.Keeper
stakingKeeper staking.Keeper
2018-05-23 13:25:56 -07:00
slashingKeeper slashing.Keeper
2018-10-19 11:36:00 -07:00
mintKeeper mint.Keeper
2018-09-17 20:02:15 -07:00
distrKeeper distr.Keeper
2018-06-21 17:19:14 -07:00
govKeeper gov.Keeper
paramsKeeper params.Keeper
2018-04-06 22:12:00 -07:00
}
// NewGaiaApp returns a reference to an initialized GaiaApp.
func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, baseAppOptions ...func(*bam.BaseApp)) *GaiaApp {
cdc := MakeCodec()
2018-07-18 16:24:16 -07:00
bApp := bam.NewBaseApp(appName, logger, db, auth.DefaultTxDecoder(cdc), baseAppOptions...)
bApp.SetCommitMultiStoreTracer(traceStore)
2018-04-06 22:12:00 -07:00
var app = &GaiaApp{
BaseApp: bApp,
2018-06-29 06:37:14 -07:00
cdc: cdc,
keyMain: sdk.NewKVStoreKey(bam.MainStoreKey),
keyAccount: sdk.NewKVStoreKey(auth.StoreKey),
keyStaking: sdk.NewKVStoreKey(staking.StoreKey),
tkeyStaking: sdk.NewTransientStoreKey(staking.TStoreKey),
keyMint: sdk.NewKVStoreKey(mint.StoreKey),
keyDistr: sdk.NewKVStoreKey(distr.StoreKey),
tkeyDistr: sdk.NewTransientStoreKey(distr.TStoreKey),
keySlashing: sdk.NewKVStoreKey(slashing.StoreKey),
keyGov: sdk.NewKVStoreKey(gov.StoreKey),
keyFeeCollection: sdk.NewKVStoreKey(auth.FeeStoreKey),
keyParams: sdk.NewKVStoreKey(params.StoreKey),
tkeyParams: sdk.NewTransientStoreKey(params.TStoreKey),
2018-04-06 22:12:00 -07:00
}
2018-12-20 11:09:43 -08:00
app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams, app.tkeyParams)
// define the accountKeeper
app.accountKeeper = auth.NewAccountKeeper(
2018-04-27 08:06:55 -07:00
app.cdc,
2018-12-20 11:09:43 -08:00
app.keyAccount,
app.paramsKeeper.Subspace(auth.DefaultParamspace),
auth.ProtoBaseAccount,
2018-04-27 08:06:55 -07:00
)
2018-09-18 14:54:28 -07:00
// add handlers
app.bankKeeper = bank.NewBaseKeeper(
app.accountKeeper,
app.paramsKeeper.Subspace(bank.DefaultParamspace),
bank.DefaultCodespace,
)
app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(
app.cdc,
app.keyFeeCollection,
)
2019-01-11 12:08:01 -08:00
stakingKeeper := staking.NewKeeper(
2018-10-06 06:50:58 -07:00
app.cdc,
2019-01-11 12:08:01 -08:00
app.keyStaking, app.tkeyStaking,
app.bankKeeper, app.paramsKeeper.Subspace(staking.DefaultParamspace),
staking.DefaultCodespace,
2018-10-06 06:50:58 -07:00
)
2018-10-19 11:36:00 -07:00
app.mintKeeper = mint.NewKeeper(app.cdc, app.keyMint,
app.paramsKeeper.Subspace(mint.DefaultParamspace),
2019-01-11 12:08:01 -08:00
&stakingKeeper, app.feeCollectionKeeper,
2018-10-19 11:36:00 -07:00
)
app.distrKeeper = distr.NewKeeper(
app.cdc,
app.keyDistr,
app.paramsKeeper.Subspace(distr.DefaultParamspace),
2019-01-11 12:08:01 -08:00
app.bankKeeper, &stakingKeeper, app.feeCollectionKeeper,
2018-11-16 09:12:24 -08:00
distr.DefaultCodespace,
)
2018-10-06 06:50:58 -07:00
app.slashingKeeper = slashing.NewKeeper(
app.cdc,
app.keySlashing,
2019-01-11 12:08:01 -08:00
&stakingKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamspace),
2018-11-16 09:12:24 -08:00
slashing.DefaultCodespace,
2018-10-06 06:50:58 -07:00
)
app.govKeeper = gov.NewKeeper(
app.cdc,
app.keyGov,
2019-01-11 12:08:01 -08:00
app.paramsKeeper, app.paramsKeeper.Subspace(gov.DefaultParamspace), app.bankKeeper, &stakingKeeper,
2018-11-16 09:12:24 -08:00
gov.DefaultCodespace,
2018-10-06 06:50:58 -07:00
)
2018-04-18 09:36:55 -07:00
2018-09-18 14:54:28 -07:00
// register the staking hooks
2019-01-11 12:08:01 -08:00
// NOTE: The stakingKeeper above is passed by reference, so that it can be
// modified like below:
2019-01-11 12:08:01 -08:00
app.stakingKeeper = *stakingKeeper.SetHooks(
NewStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks()),
)
2018-09-18 14:54:28 -07:00
// register message routes
//
// TODO: Use standard bank router once transfers are enabled.
2018-04-06 22:12:00 -07:00
app.Router().
AddRoute(bank.RouterKey, gaiabank.NewHandler(app.bankKeeper)).
2019-01-11 12:08:01 -08:00
AddRoute(staking.RouterKey, staking.NewHandler(app.stakingKeeper)).
AddRoute(distr.RouterKey, distr.NewHandler(app.distrKeeper)).
AddRoute(slashing.RouterKey, slashing.NewHandler(app.slashingKeeper)).
AddRoute(gov.RouterKey, gov.NewHandler(app.govKeeper))
2018-04-06 22:12:00 -07:00
2018-08-04 22:56:48 -07:00
app.QueryRouter().
2019-02-28 11:42:12 -08:00
AddRoute(auth.QuerierRoute, auth.NewQuerier(app.accountKeeper)).
AddRoute(distr.QuerierRoute, distr.NewQuerier(app.distrKeeper)).
AddRoute(gov.QuerierRoute, gov.NewQuerier(app.govKeeper)).
AddRoute(slashing.QuerierRoute, slashing.NewQuerier(app.slashingKeeper, app.cdc)).
2019-01-11 12:08:01 -08:00
AddRoute(staking.QuerierRoute, staking.NewQuerier(app.stakingKeeper, app.cdc))
2018-08-04 22:56:48 -07:00
2018-04-06 22:12:00 -07:00
// initialize BaseApp
2019-01-11 12:08:01 -08:00
app.MountStores(app.keyMain, app.keyAccount, app.keyStaking, app.keyMint, app.keyDistr,
2019-02-07 17:52:24 -08:00
app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams,
app.tkeyParams, app.tkeyStaking, app.tkeyDistr,
)
2018-04-06 22:12:00 -07:00
app.SetInitChainer(app.initChainer)
app.SetBeginBlocker(app.BeginBlocker)
app.SetAnteHandler(auth.NewAnteHandler(app.accountKeeper, app.feeCollectionKeeper))
2018-10-04 17:20:43 -07:00
app.SetEndBlocker(app.EndBlocker)
if loadLatest {
err := app.LoadLatestVersion(app.keyMain)
if err != nil {
cmn.Exit(err.Error())
}
2018-04-06 22:12:00 -07:00
}
return app
}
// custom tx codec
func MakeCodec() *codec.Codec {
var cdc = codec.New()
bank.RegisterCodec(cdc)
2019-01-11 12:08:01 -08:00
staking.RegisterCodec(cdc)
2018-09-17 20:02:15 -07:00
distr.RegisterCodec(cdc)
slashing.RegisterCodec(cdc)
gov.RegisterCodec(cdc)
auth.RegisterCodec(cdc)
sdk.RegisterCodec(cdc)
codec.RegisterCrypto(cdc)
2018-04-06 22:12:00 -07:00
return cdc
}
// application updates every end block
func (app *GaiaApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
// mint new tokens for the previous block
2018-10-19 11:36:00 -07:00
mint.BeginBlocker(ctx, app.mintKeeper)
// distribute rewards for the previous block
distr.BeginBlocker(ctx, req, app.distrKeeper)
// slash anyone who double signed.
// NOTE: This should happen after distr.BeginBlocker so that
// there is nothing left over in the validator fee pool,
// so as to keep the CanWithdrawInvariant invariant.
// TODO: This should really happen at EndBlocker.
tags := slashing.BeginBlocker(ctx, req, app.slashingKeeper)
return abci.ResponseBeginBlock{
Tags: tags.ToKVPairs(),
}
}
// application updates every end block
// nolint: unparam
func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
2018-10-14 23:34:01 -07:00
tags := gov.EndBlocker(ctx, app.govKeeper)
2019-01-11 12:08:01 -08:00
validatorUpdates, endBlockerTags := staking.EndBlocker(ctx, app.stakingKeeper)
tags = append(tags, endBlockerTags...)
2018-10-14 23:34:01 -07:00
app.assertRuntimeInvariants()
return abci.ResponseEndBlock{
ValidatorUpdates: validatorUpdates,
2018-06-21 17:19:14 -07:00
Tags: tags,
}
}
// initialize store from a genesis state
func (app *GaiaApp) initFromGenesisState(ctx sdk.Context, genesisState GenesisState) []abci.ValidatorUpdate {
genesisState.Sanitize()
2018-04-06 22:50:46 -07:00
// load the accounts
2018-04-06 22:12:00 -07:00
for _, gacc := range genesisState.Accounts {
acc := gacc.ToAccount()
acc = app.accountKeeper.NewAccount(ctx, acc) // set account number
app.accountKeeper.SetAccount(ctx, acc)
2018-04-06 22:12:00 -07:00
}
2018-04-06 22:50:46 -07:00
2019-01-16 13:38:05 -08:00
// initialize distribution (must happen before staking)
distr.InitGenesis(ctx, app.distrKeeper, genesisState.DistrData)
2019-01-11 12:08:01 -08:00
// load the initial staking information
validators, err := staking.InitGenesis(ctx, app.stakingKeeper, genesisState.StakingData)
2018-07-09 19:51:13 -07:00
if err != nil {
2018-10-05 17:32:06 -07:00
panic(err) // TODO find a way to do this w/o panics
2018-07-09 19:51:13 -07:00
}
2018-04-06 22:50:46 -07:00
// initialize module-specific stores
2018-12-20 11:09:43 -08:00
auth.InitGenesis(ctx, app.accountKeeper, app.feeCollectionKeeper, genesisState.AuthData)
bank.InitGenesis(ctx, app.bankKeeper, genesisState.BankData)
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakingData.Validators.ToSDKValidators())
2018-08-20 03:47:04 -07:00
gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData)
2018-10-19 11:36:00 -07:00
mint.InitGenesis(ctx, app.mintKeeper, genesisState.MintData)
2018-11-13 06:08:14 -08:00
// validate genesis state
if err := GaiaValidateGenesisState(genesisState); err != nil {
2018-10-05 17:32:06 -07:00
panic(err) // TODO find a way to do this w/o panics
}
2018-06-21 17:19:14 -07:00
if len(genesisState.GenTxs) > 0 {
for _, genTx := range genesisState.GenTxs {
var tx auth.StdTx
err = app.cdc.UnmarshalJSON(genTx, &tx)
if err != nil {
panic(err)
}
bz := app.cdc.MustMarshalBinaryLengthPrefixed(tx)
res := app.BaseApp.DeliverTx(bz)
if !res.IsOK() {
panic(res.Log)
}
}
2019-01-11 12:08:01 -08:00
validators = app.stakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx)
}
return validators
}
// custom logic for gaia initialization
func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
stateJSON := req.AppStateBytes
// TODO is this now the whole genesis file?
var genesisState GenesisState
err := app.cdc.UnmarshalJSON(stateJSON, &genesisState)
if err != nil {
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
// return sdk.ErrGenesisParse("").TraceCause(err, "")
}
validators := app.initFromGenesisState(ctx, genesisState)
// sanity check
if len(req.Validators) > 0 {
if len(req.Validators) != len(validators) {
panic(fmt.Errorf("len(RequestInitChain.Validators) != len(validators) (%d != %d)",
len(req.Validators), len(validators)))
}
sort.Sort(abci.ValidatorUpdates(req.Validators))
sort.Sort(abci.ValidatorUpdates(validators))
for i, val := range validators {
if !val.Equal(req.Validators[i]) {
panic(fmt.Errorf("validators[%d] != req.Validators[%d] ", i, i))
}
}
}
// assert runtime invariants
app.assertRuntimeInvariants()
return abci.ResponseInitChain{
Validators: validators,
}
2018-04-06 22:12:00 -07:00
}
2018-04-24 06:46:39 -07:00
2018-11-13 07:14:09 -08:00
// load a particular height
2018-11-13 07:17:40 -08:00
func (app *GaiaApp) LoadHeight(height int64) error {
return app.LoadVersion(height, app.keyMain)
2018-11-13 07:14:09 -08:00
}
2019-02-28 11:42:12 -08:00
// ______________________________________________________________________________________________
2018-09-18 09:46:04 -07:00
var _ sdk.StakingHooks = StakingHooks{}
// StakingHooks contains combined distribution and slashing hooks needed for the
// staking module.
type StakingHooks struct {
2018-09-18 09:46:04 -07:00
dh distr.Hooks
2018-09-19 20:01:55 -07:00
sh slashing.Hooks
2018-09-18 14:54:28 -07:00
}
func NewStakingHooks(dh distr.Hooks, sh slashing.Hooks) StakingHooks {
return StakingHooks{dh, sh}
2018-09-18 09:46:04 -07:00
}
// nolint
func (h StakingHooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
h.dh.AfterValidatorCreated(ctx, valAddr)
h.sh.AfterValidatorCreated(ctx, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
h.dh.BeforeValidatorModified(ctx, valAddr)
h.sh.BeforeValidatorModified(ctx, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
h.dh.AfterValidatorRemoved(ctx, consAddr, valAddr)
h.sh.AfterValidatorRemoved(ctx, consAddr, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
h.dh.AfterValidatorBonded(ctx, consAddr, valAddr)
h.sh.AfterValidatorBonded(ctx, consAddr, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
h.dh.AfterValidatorBeginUnbonding(ctx, consAddr, valAddr)
h.sh.AfterValidatorBeginUnbonding(ctx, consAddr, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
h.dh.BeforeDelegationCreated(ctx, delAddr, valAddr)
h.sh.BeforeDelegationCreated(ctx, delAddr, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
h.dh.BeforeDelegationSharesModified(ctx, delAddr, valAddr)
h.sh.BeforeDelegationSharesModified(ctx, delAddr, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
h.dh.BeforeDelegationRemoved(ctx, delAddr, valAddr)
h.sh.BeforeDelegationRemoved(ctx, delAddr, valAddr)
2018-09-18 09:46:04 -07:00
}
2019-01-16 13:38:05 -08:00
func (h StakingHooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
h.dh.AfterDelegationModified(ctx, delAddr, valAddr)
h.sh.AfterDelegationModified(ctx, delAddr, valAddr)
}
func (h StakingHooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) {
h.dh.BeforeValidatorSlashed(ctx, valAddr, fraction)
h.sh.BeforeValidatorSlashed(ctx, valAddr, fraction)
}