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

374 lines
12 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"
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"
2018-04-06 22:12:00 -07:00
"github.com/cosmos/cosmos-sdk/x/stake"
)
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
keyStake *sdk.KVStoreKey
tkeyStake *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
2018-05-25 20:29:40 -07:00
stakeKeeper stake.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.
2018-07-12 18:20:26 -07:00
func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, 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("main"),
keyAccount: sdk.NewKVStoreKey("acc"),
keyStake: sdk.NewKVStoreKey("stake"),
tkeyStake: sdk.NewTransientStoreKey("transient_stake"),
2018-10-19 11:36:00 -07:00
keyMint: sdk.NewKVStoreKey("mint"),
2018-09-17 20:02:15 -07:00
keyDistr: sdk.NewKVStoreKey("distr"),
tkeyDistr: sdk.NewTransientStoreKey("transient_distr"),
2018-06-29 06:37:14 -07:00
keySlashing: sdk.NewKVStoreKey("slashing"),
keyGov: sdk.NewKVStoreKey("gov"),
2018-07-02 21:08:00 -07:00
keyFeeCollection: sdk.NewKVStoreKey("fee"),
keyParams: sdk.NewKVStoreKey("params"),
tkeyParams: sdk.NewTransientStoreKey("transient_params"),
2018-04-06 22:12:00 -07:00
}
// define the accountKeeper
app.accountKeeper = auth.NewAccountKeeper(
2018-04-27 08:06:55 -07:00
app.cdc,
app.keyAccount, // target store
auth.ProtoBaseAccount, // prototype
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.feeCollectionKeeper = auth.NewFeeCollectionKeeper(
app.cdc,
app.keyFeeCollection,
)
2018-10-06 06:50:58 -07:00
app.paramsKeeper = params.NewKeeper(
app.cdc,
app.keyParams, app.tkeyParams,
)
stakeKeeper := stake.NewKeeper(
2018-10-06 06:50:58 -07:00
app.cdc,
app.keyStake, app.tkeyStake,
app.bankKeeper, app.paramsKeeper.Subspace(stake.DefaultParamspace),
2018-11-16 09:12:24 -08:00
stake.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),
&stakeKeeper, app.feeCollectionKeeper,
2018-10-19 11:36:00 -07:00
)
app.distrKeeper = distr.NewKeeper(
app.cdc,
app.keyDistr,
app.paramsKeeper.Subspace(distr.DefaultParamspace),
app.bankKeeper, &stakeKeeper, 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,
&stakeKeeper, 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,
app.paramsKeeper, app.paramsKeeper.Subspace(gov.DefaultParamspace), app.bankKeeper, &stakeKeeper,
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
// NOTE: The stakeKeeper above is passed by reference, so that it can be
// modified like below:
app.stakeKeeper = *stakeKeeper.SetHooks(
NewStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks()),
)
2018-09-18 14:54:28 -07:00
// register message routes
2018-04-06 22:12:00 -07:00
app.Router().
AddRoute("bank", bank.NewHandler(app.bankKeeper)).
AddRoute("stake", stake.NewHandler(app.stakeKeeper)).
2018-09-19 21:53:48 -07:00
AddRoute("distr", distr.NewHandler(app.distrKeeper)).
2018-06-21 17:19:14 -07:00
AddRoute("slashing", slashing.NewHandler(app.slashingKeeper)).
AddRoute("gov", gov.NewHandler(app.govKeeper))
2018-04-06 22:12:00 -07:00
2018-08-04 22:56:48 -07:00
app.QueryRouter().
Merge PR #2249: Staking Querier pt1 * Cherry picked commits from prev branch * Added new keepers for querier functionalities * Renaming * Fixed gov errors and messages * Added Querier to stake and app * Update delegation keepers * REST Queriers not working * Fix marshalling error * Querier tests working * Pool and params working * sdk.NewCoin for test handler * Refactor and renaming * Update LCD queries and added more tests for queriers * use sdk.NewCoin * Delegator summary query and tests * Added more tests for keeper * Update PENDING.md * Update stake rest query * Format and replaced panics for sdk.Error * Refactor and addressed comments from Sunny and Aleks * Fixed some of the errors produced by addr type change * Fixed remaining errors * Updated and fixed lite tests * JSON Header and consistency on errors * Increased cov for genesis * Added comment for maxRetrieve param in keepers * Comment on DelegationWithoutDec * Bech32Validator Keepers * Changed Bech validator * Updated remaining tests and bech32 validator * Addressed most of Rigel's comments * Updated tests and types * Make codec to be unexported from keeper * Moved logic to query_utils and updated tests * Fix linter err and PENDING * Fix err * Fix err * Fixed tests * Update PENDING description * Update UpdateBondedValidatorsFull * Update iterator * defer iterator.Close() * delete comment * Address some of Aleks comments, need to fix tests * export querier * Fixed tests * Address Rigel's comments * More tests * return error for GetDelegatorValidator * Fixed conflicts * Fix linter warnings * Address @rigelrozanski comments * Delete comments * wire ––> codec
2018-09-13 14:23:44 -07:00
AddRoute("gov", gov.NewQuerier(app.govKeeper)).
2018-12-14 11:09:39 -08:00
AddRoute(slashing.QuerierRoute, slashing.NewQuerier(app.slashingKeeper, app.cdc)).
Merge PR #2249: Staking Querier pt1 * Cherry picked commits from prev branch * Added new keepers for querier functionalities * Renaming * Fixed gov errors and messages * Added Querier to stake and app * Update delegation keepers * REST Queriers not working * Fix marshalling error * Querier tests working * Pool and params working * sdk.NewCoin for test handler * Refactor and renaming * Update LCD queries and added more tests for queriers * use sdk.NewCoin * Delegator summary query and tests * Added more tests for keeper * Update PENDING.md * Update stake rest query * Format and replaced panics for sdk.Error * Refactor and addressed comments from Sunny and Aleks * Fixed some of the errors produced by addr type change * Fixed remaining errors * Updated and fixed lite tests * JSON Header and consistency on errors * Increased cov for genesis * Added comment for maxRetrieve param in keepers * Comment on DelegationWithoutDec * Bech32Validator Keepers * Changed Bech validator * Updated remaining tests and bech32 validator * Addressed most of Rigel's comments * Updated tests and types * Make codec to be unexported from keeper * Moved logic to query_utils and updated tests * Fix linter err and PENDING * Fix err * Fix err * Fixed tests * Update PENDING description * Update UpdateBondedValidatorsFull * Update iterator * defer iterator.Close() * delete comment * Address some of Aleks comments, need to fix tests * export querier * Fixed tests * Address Rigel's comments * More tests * return error for GetDelegatorValidator * Fixed conflicts * Fix linter warnings * Address @rigelrozanski comments * Delete comments * wire ––> codec
2018-09-13 14:23:44 -07:00
AddRoute("stake", stake.NewQuerier(app.stakeKeeper, app.cdc))
2018-08-04 22:56:48 -07:00
2018-04-06 22:12:00 -07:00
// initialize BaseApp
app.MountStores(app.keyMain, app.keyAccount, app.keyStake, app.keyMint, app.keyDistr,
2018-10-19 11:36:00 -07:00
app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams)
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-09-20 17:10:26 -07:00
app.MountStoresTransient(app.tkeyParams, app.tkeyStake, app.tkeyDistr)
2018-10-04 17:20:43 -07:00
app.SetEndBlocker(app.EndBlocker)
2018-04-18 21:49:24 -07:00
err := app.LoadLatestVersion(app.keyMain)
2018-04-06 22:12:00 -07:00
if err != nil {
cmn.Exit(err.Error())
}
return app
}
// custom tx codec
func MakeCodec() *codec.Codec {
var cdc = codec.New()
bank.RegisterCodec(cdc)
stake.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-09-17 20:02:15 -07:00
2018-10-14 23:34:01 -07:00
tags := gov.EndBlocker(ctx, app.govKeeper)
validatorUpdates, endBlockerTags := stake.EndBlocker(ctx, app.stakeKeeper)
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 {
// sort by account number to maintain consistency
sort.Slice(genesisState.Accounts, func(i, j int) bool {
return genesisState.Accounts[i].AccountNumber < genesisState.Accounts[j].AccountNumber
})
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.AccountNumber = app.accountKeeper.GetNextAccountNumber(ctx)
app.accountKeeper.SetAccount(ctx, acc)
2018-04-06 22:12:00 -07:00
}
2018-04-06 22:50:46 -07:00
// load the initial stake information
validators, err := stake.InitGenesis(ctx, app.stakeKeeper, genesisState.StakeData)
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
auth.InitGenesis(ctx, app.feeCollectionKeeper, genesisState.AuthData)
slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakeData)
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-09-18 09:46:04 -07:00
distr.InitGenesis(ctx, app.distrKeeper, genesisState.DistrData)
2018-11-13 06:08:14 -08:00
// validate genesis state
err = GaiaValidateGenesisState(genesisState)
if 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)
}
}
validators = app.stakeKeeper.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
}
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) OnValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) {
h.dh.OnValidatorCreated(ctx, valAddr)
h.sh.OnValidatorCreated(ctx, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) OnValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) {
h.dh.OnValidatorModified(ctx, valAddr)
h.sh.OnValidatorModified(ctx, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) OnValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
h.dh.OnValidatorRemoved(ctx, consAddr, valAddr)
h.sh.OnValidatorRemoved(ctx, consAddr, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) OnValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
h.dh.OnValidatorBonded(ctx, consAddr, valAddr)
h.sh.OnValidatorBonded(ctx, consAddr, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) OnValidatorPowerDidChange(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
h.dh.OnValidatorPowerDidChange(ctx, consAddr, valAddr)
h.sh.OnValidatorPowerDidChange(ctx, consAddr, valAddr)
}
func (h StakingHooks) OnValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) {
h.dh.OnValidatorBeginUnbonding(ctx, consAddr, valAddr)
h.sh.OnValidatorBeginUnbonding(ctx, consAddr, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) OnDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
2018-09-18 09:46:04 -07:00
h.dh.OnDelegationCreated(ctx, delAddr, valAddr)
h.sh.OnDelegationCreated(ctx, delAddr, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) OnDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
2018-09-18 09:46:04 -07:00
h.dh.OnDelegationSharesModified(ctx, delAddr, valAddr)
h.sh.OnDelegationSharesModified(ctx, delAddr, valAddr)
2018-09-18 09:46:04 -07:00
}
func (h StakingHooks) OnDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) {
2018-09-18 09:46:04 -07:00
h.dh.OnDelegationRemoved(ctx, delAddr, valAddr)
h.sh.OnDelegationRemoved(ctx, delAddr, valAddr)
2018-09-18 09:46:04 -07:00
}