diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index 87cd86b0cdba..74562bfa16ed 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -6,6 +6,7 @@ import ( "os" "reflect" "runtime/debug" + "sort" "strings" "errors" @@ -48,8 +49,8 @@ type BaseApp struct { name string // application name from abci.Info db dbm.DB // common DB backend cms sdk.CommitMultiStore // Main (uncached) state - router Router // handle any kind of message - queryRouter QueryRouter // router for redirecting query calls + router sdk.Router // handle any kind of message + queryRouter sdk.QueryRouter // router for redirecting query calls txDecoder sdk.TxDecoder // unmarshal []byte into sdk.Tx // set upon LoadVersion or LoadLatestVersion. @@ -239,7 +240,7 @@ func (app *BaseApp) setHaltHeight(height uint64) { } // Router returns the router of the BaseApp. -func (app *BaseApp) Router() Router { +func (app *BaseApp) Router() sdk.Router { if app.sealed { // We cannot return a router when the app is sealed because we can't have // any routes modified which would cause unexpected routing behavior. @@ -249,7 +250,7 @@ func (app *BaseApp) Router() Router { } // QueryRouter returns the QueryRouter of a BaseApp. -func (app *BaseApp) QueryRouter() QueryRouter { return app.queryRouter } +func (app *BaseApp) QueryRouter() sdk.QueryRouter { return app.queryRouter } // Seal seals a BaseApp. It prohibits any further modifications to a BaseApp. func (app *BaseApp) Seal() { app.sealed = true } @@ -361,6 +362,22 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC res = app.initChainer(app.deliverState.ctx, req) + // sanity check + if len(req.Validators) > 0 { + if len(req.Validators) != len(res.Validators) { + panic(fmt.Errorf( + "len(RequestInitChain.Validators) != len(validators) (%d != %d)", + len(req.Validators), len(res.Validators))) + } + sort.Sort(abci.ValidatorUpdates(req.Validators)) + sort.Sort(abci.ValidatorUpdates(res.Validators)) + for i, val := range res.Validators { + if !val.Equal(req.Validators[i]) { + panic(fmt.Errorf("validators[%d] != req.Validators[%d] ", i, i)) + } + } + } + // NOTE: We don't commit, but BeginBlock for block 1 starts from this // deliverState. return diff --git a/baseapp/queryrouter.go b/baseapp/queryrouter.go index 178646b7ebb5..9e38674def6d 100644 --- a/baseapp/queryrouter.go +++ b/baseapp/queryrouter.go @@ -6,16 +6,12 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// QueryRouter provides queryables for each query path. -type QueryRouter interface { - AddRoute(r string, h sdk.Querier) (rtr QueryRouter) - Route(path string) (h sdk.Querier) -} - type queryRouter struct { routes map[string]sdk.Querier } +var _ sdk.QueryRouter = NewQueryRouter() + // NewQueryRouter returns a reference to a new queryRouter. // // TODO: Either make the function private or make return type (queryRouter) public. @@ -27,7 +23,7 @@ func NewQueryRouter() *queryRouter { // nolint: golint // AddRoute adds a query path to the router with a given Querier. It will panic // if a duplicate route is given. The route must be alphanumeric. -func (qrt *queryRouter) AddRoute(path string, q sdk.Querier) QueryRouter { +func (qrt *queryRouter) AddRoute(path string, q sdk.Querier) sdk.QueryRouter { if !isAlphaNumeric(path) { panic("route expressions can only contain alphanumeric characters") } diff --git a/baseapp/router.go b/baseapp/router.go index 5e829d73cfa6..9eebce23941c 100644 --- a/baseapp/router.go +++ b/baseapp/router.go @@ -6,16 +6,12 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// Router provides handlers for each transaction type. -type Router interface { - AddRoute(r string, h sdk.Handler) (rtr Router) - Route(path string) (h sdk.Handler) -} - type router struct { routes map[string]sdk.Handler } +var _ sdk.Router = NewRouter() + // NewRouter returns a reference to a new router. // // TODO: Either make the function private or make return type (router) public. @@ -27,7 +23,7 @@ func NewRouter() *router { // nolint: golint // AddRoute adds a route path to the router with a given handler. The route must // be alphanumeric. -func (rtr *router) AddRoute(path string, h sdk.Handler) Router { +func (rtr *router) AddRoute(path string, h sdk.Handler) sdk.Router { if !isAlphaNumeric(path) { panic("route expressions can only contain alphanumeric characters") } diff --git a/client/lcd/lcd_test.go b/client/lcd/lcd_test.go index 69c5281b38f3..1e69a7fd19d9 100644 --- a/client/lcd/lcd_test.go +++ b/client/lcd/lcd_test.go @@ -233,7 +233,7 @@ func TestCoinMultiSendGenerateOnly(t *testing.T) { var stdTx auth.StdTx require.Nil(t, cdc.UnmarshalJSON([]byte(body), &stdTx)) require.Equal(t, len(stdTx.Msgs), 1) - require.Equal(t, stdTx.GetMsgs()[0].Route(), "bank") + require.Equal(t, stdTx.GetMsgs()[0].Route(), bank.RouterKey) require.Equal(t, stdTx.GetMsgs()[0].GetSigners(), []sdk.AccAddress{addr}) require.Equal(t, 0, len(stdTx.Signatures)) require.Equal(t, memo, stdTx.Memo) @@ -269,7 +269,7 @@ func TestCoinSendGenerateSignAndBroadcast(t *testing.T) { var tx auth.StdTx require.Nil(t, cdc.UnmarshalJSON([]byte(body), &tx)) require.Equal(t, len(tx.Msgs), 1) - require.Equal(t, tx.Msgs[0].Route(), "bank") + require.Equal(t, tx.Msgs[0].Route(), bank.RouterKey) require.Equal(t, tx.Msgs[0].GetSigners(), []sdk.AccAddress{addr}) require.Equal(t, 0, len(tx.Signatures)) require.Equal(t, memo, tx.Memo) @@ -389,8 +389,8 @@ func TestPoolParamsQuery(t *testing.T) { tokens := sdk.TokensFromTendermintPower(100) freeTokens := sdk.TokensFromTendermintPower(50) initialPool.NotBondedTokens = initialPool.NotBondedTokens.Add(tokens) - initialPool.BondedTokens = initialPool.BondedTokens.Add(tokens) // Delegate tx on GaiaAppGenState - initialPool.NotBondedTokens = initialPool.NotBondedTokens.Add(freeTokens) // freeTokensPerAcc = 50 on GaiaAppGenState + initialPool.BondedTokens = initialPool.BondedTokens.Add(tokens) // Delegate tx on GaiaAppGenState + initialPool.NotBondedTokens = initialPool.NotBondedTokens.Add(freeTokens) require.Equal(t, initialPool.BondedTokens, pool.BondedTokens) diff --git a/cmd/gaia/app/app.go b/cmd/gaia/app/app.go index 26d920d5ea8e..5eda75765db3 100644 --- a/cmd/gaia/app/app.go +++ b/cmd/gaia/app/app.go @@ -1,10 +1,9 @@ package app import ( - "fmt" + "encoding/json" "io" "os" - "sort" abci "github.com/tendermint/tendermint/abci/types" cmn "github.com/tendermint/tendermint/libs/common" @@ -56,7 +55,7 @@ type GaiaApp struct { keyParams *sdk.KVStoreKey tkeyParams *sdk.TransientStoreKey - // Manage getting and setting accounts + // keepers accountKeeper auth.AccountKeeper feeCollectionKeeper auth.FeeCollectionKeeper bankKeeper bank.Keeper @@ -67,6 +66,24 @@ type GaiaApp struct { govKeeper gov.Keeper crisisKeeper crisis.Keeper paramsKeeper params.Keeper + + // the module manager + mm *sdk.ModuleManager +} + +// custom tx codec +func MakeCodec() *codec.Codec { + var cdc = codec.New() + bank.RegisterCodec(cdc) + staking.RegisterCodec(cdc) + distr.RegisterCodec(cdc) + slashing.RegisterCodec(cdc) + gov.RegisterCodec(cdc) + auth.RegisterCodec(cdc) + crisis.RegisterCodec(cdc) + sdk.RegisterCodec(cdc) + codec.RegisterCrypto(cdc) + return cdc } // NewGaiaApp returns a reference to an initialized GaiaApp. @@ -97,96 +114,64 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b tkeyParams: sdk.NewTransientStoreKey(params.TStoreKey), } + // init params keeper and subspaces app.paramsKeeper = params.NewKeeper(app.cdc, app.keyParams, app.tkeyParams) - - // define the accountKeeper - app.accountKeeper = auth.NewAccountKeeper( - app.cdc, - app.keyAccount, - app.paramsKeeper.Subspace(auth.DefaultParamspace), - auth.ProtoBaseAccount, - ) - - // add handlers - app.bankKeeper = bank.NewBaseKeeper( - app.accountKeeper, - app.paramsKeeper.Subspace(bank.DefaultParamspace), - bank.DefaultCodespace, - ) - app.feeCollectionKeeper = auth.NewFeeCollectionKeeper( - app.cdc, - app.keyFeeCollection, - ) - stakingKeeper := staking.NewKeeper( - app.cdc, - app.keyStaking, app.tkeyStaking, - app.bankKeeper, app.paramsKeeper.Subspace(staking.DefaultParamspace), - staking.DefaultCodespace, - ) - app.mintKeeper = mint.NewKeeper(app.cdc, app.keyMint, - app.paramsKeeper.Subspace(mint.DefaultParamspace), - &stakingKeeper, app.feeCollectionKeeper, - ) - app.distrKeeper = distr.NewKeeper( - app.cdc, - app.keyDistr, - app.paramsKeeper.Subspace(distr.DefaultParamspace), - app.bankKeeper, &stakingKeeper, app.feeCollectionKeeper, - distr.DefaultCodespace, - ) - app.slashingKeeper = slashing.NewKeeper( - app.cdc, - app.keySlashing, - &stakingKeeper, app.paramsKeeper.Subspace(slashing.DefaultParamspace), - slashing.DefaultCodespace, - ) - app.govKeeper = gov.NewKeeper( - app.cdc, - app.keyGov, - app.paramsKeeper, app.paramsKeeper.Subspace(gov.DefaultParamspace), app.bankKeeper, &stakingKeeper, - gov.DefaultCodespace, - ) - app.crisisKeeper = crisis.NewKeeper( - app.paramsKeeper.Subspace(crisis.DefaultParamspace), - app.distrKeeper, - app.bankKeeper, - app.feeCollectionKeeper, - ) + authSubspace := app.paramsKeeper.Subspace(auth.DefaultParamspace) + bankSubspace := app.paramsKeeper.Subspace(bank.DefaultParamspace) + stakingSubspace := app.paramsKeeper.Subspace(staking.DefaultParamspace) + mintSubspace := app.paramsKeeper.Subspace(mint.DefaultParamspace) + distrSubspace := app.paramsKeeper.Subspace(distr.DefaultParamspace) + slashingSubspace := app.paramsKeeper.Subspace(slashing.DefaultParamspace) + govSubspace := app.paramsKeeper.Subspace(gov.DefaultParamspace) + crisisSubspace := app.paramsKeeper.Subspace(crisis.DefaultParamspace) + + // add keepers + app.accountKeeper = auth.NewAccountKeeper(app.cdc, app.keyAccount, authSubspace, auth.ProtoBaseAccount) + app.bankKeeper = bank.NewBaseKeeper(app.accountKeeper, bankSubspace, bank.DefaultCodespace) + app.feeCollectionKeeper = auth.NewFeeCollectionKeeper(app.cdc, app.keyFeeCollection) + stakingKeeper := staking.NewKeeper(app.cdc, app.keyStaking, app.tkeyStaking, app.bankKeeper, + stakingSubspace, staking.DefaultCodespace) + app.mintKeeper = mint.NewKeeper(app.cdc, app.keyMint, mintSubspace, &stakingKeeper, app.feeCollectionKeeper) + app.distrKeeper = distr.NewKeeper(app.cdc, app.keyDistr, distrSubspace, app.bankKeeper, &stakingKeeper, + app.feeCollectionKeeper, distr.DefaultCodespace) + app.slashingKeeper = slashing.NewKeeper(app.cdc, app.keySlashing, &stakingKeeper, + slashingSubspace, slashing.DefaultCodespace) + app.govKeeper = gov.NewKeeper(app.cdc, app.keyGov, app.paramsKeeper, govSubspace, + app.bankKeeper, &stakingKeeper, gov.DefaultCodespace) + app.crisisKeeper = crisis.NewKeeper(crisisSubspace, invCheckPeriod, app.distrKeeper, + app.bankKeeper, app.feeCollectionKeeper) // register the staking hooks // NOTE: The stakingKeeper above is passed by reference, so that it can be // modified like below: app.stakingKeeper = *stakingKeeper.SetHooks( - NewStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks()), + staking.NewMultiStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks())) + + app.mm = sdk.NewModuleManager( + auth.NewAppModule(app.accountKeeper), + bank.NewAppModule(app.bankKeeper, app.accountKeeper), + crisis.NewAppModule(app.crisisKeeper, app.Logger()), + distr.NewAppModule(app.distrKeeper), + gov.NewAppModule(app.govKeeper), + mint.NewAppModule(app.mintKeeper), + slashing.NewAppModule(app.slashingKeeper), + staking.NewAppModule(app.stakingKeeper, app.feeCollectionKeeper, app.distrKeeper, app.accountKeeper), ) - // register the crisis routes - bank.RegisterInvariants(&app.crisisKeeper, app.accountKeeper) - distr.RegisterInvariants(&app.crisisKeeper, app.distrKeeper, app.stakingKeeper) - staking.RegisterInvariants(&app.crisisKeeper, app.stakingKeeper, app.feeCollectionKeeper, app.distrKeeper, app.accountKeeper) - - // register message routes - app.Router(). - AddRoute(bank.RouterKey, bank.NewHandler(app.bankKeeper)). - 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)). - AddRoute(crisis.RouterKey, crisis.NewHandler(app.crisisKeeper)) - - app.QueryRouter(). - 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)). - AddRoute(staking.QuerierRoute, staking.NewQuerier(app.stakingKeeper, app.cdc)). - AddRoute(mint.QuerierRoute, mint.NewQuerier(app.mintKeeper)) + // NOTE: 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. + // TODO: slashing should really happen at EndBlocker. + app.mm.SetOrderBeginBlockers(mint.ModuleName, distr.ModuleName, slashing.ModuleName) + app.mm.SetOrderEndBlockers(gov.ModuleName, staking.ModuleName) + app.mm.SetOrderInitGenesis(crisis.ModuleName) // XXX this only is for invariant checks right now + app.mm.RegisterInvariants(&app.crisisKeeper) + app.mm.RegisterRoutes(app.Router(), app.QueryRouter()) // initialize BaseApp - app.MountStores(app.keyMain, app.keyAccount, app.keyStaking, app.keyMint, app.keyDistr, - app.keySlashing, app.keyGov, app.keyFeeCollection, app.keyParams, - app.tkeyParams, app.tkeyStaking, app.tkeyDistr, - ) + app.MountStores(app.keyMain, app.keyAccount, app.keyStaking, app.keyMint, + app.keyDistr, app.keySlashing, app.keyGov, app.keyFeeCollection, + app.keyParams, app.tkeyParams, app.tkeyStaking, app.tkeyDistr) app.SetInitChainer(app.initChainer) app.SetBeginBlocker(app.BeginBlocker) app.SetAnteHandler(auth.NewAnteHandler(app.accountKeeper, app.feeCollectionKeeper)) @@ -202,56 +187,14 @@ func NewGaiaApp(logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest b return app } -// custom tx codec -func MakeCodec() *codec.Codec { - var cdc = codec.New() - bank.RegisterCodec(cdc) - staking.RegisterCodec(cdc) - distr.RegisterCodec(cdc) - slashing.RegisterCodec(cdc) - gov.RegisterCodec(cdc) - auth.RegisterCodec(cdc) - crisis.RegisterCodec(cdc) - sdk.RegisterCodec(cdc) - codec.RegisterCrypto(cdc) - 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 - 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(), - } + return app.mm.BeginBlock(ctx, req) } // application updates every end block -// nolint: unparam func (app *GaiaApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock { - tags := gov.EndBlocker(ctx, app.govKeeper) - validatorUpdates, endBlockerTags := staking.EndBlocker(ctx, app.stakingKeeper) - tags = append(tags, endBlockerTags...) - - if app.invCheckPeriod != 0 && ctx.BlockHeight()%int64(app.invCheckPeriod) == 0 { - app.assertRuntimeInvariants() - } - - return abci.ResponseEndBlock{ - ValidatorUpdates: validatorUpdates, - Tags: tags, - } + return app.mm.EndBlock(ctx, req) } // initialize store from a genesis state @@ -271,7 +214,7 @@ func (app *GaiaApp) initFromGenesisState(ctx sdk.Context, genesisState GenesisSt // load the initial staking information validators, err := staking.InitGenesis(ctx, app.stakingKeeper, genesisState.StakingData) if err != nil { - panic(err) // TODO find a way to do this w/o panics + panic(err) } // initialize module-specific stores @@ -279,65 +222,53 @@ func (app *GaiaApp) initFromGenesisState(ctx sdk.Context, genesisState GenesisSt bank.InitGenesis(ctx, app.bankKeeper, genesisState.BankData) slashing.InitGenesis(ctx, app.slashingKeeper, genesisState.SlashingData, genesisState.StakingData.Validators.ToSDKValidators()) gov.InitGenesis(ctx, app.govKeeper, genesisState.GovData) - crisis.InitGenesis(ctx, app.crisisKeeper, genesisState.CrisisData) mint.InitGenesis(ctx, app.mintKeeper, genesisState.MintData) + crisis.InitGenesis(ctx, app.crisisKeeper, genesisState.CrisisData) // validate genesis state if err := GaiaValidateGenesisState(genesisState); err != nil { - panic(err) // TODO find a way to do this w/o panics + panic(err) } 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.stakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) + validators = app.deliverGenTxs(ctx, genesisState.GenTxs, app.BaseApp.DeliverTx) } + return validators } +type deliverTxFn func([]byte) abci.ResponseDeliverTx + +// TODO move this genTx functionality to staking +func (app *GaiaApp) deliverGenTxs(ctx sdk.Context, genTxs []json.RawMessage, deliverTx deliverTxFn) []abci.ValidatorUpdate { + for _, genTx := range genTxs { + var tx auth.StdTx + app.cdc.MustUnmarshalJSON(genTx, &tx) + bz := app.cdc.MustMarshalBinaryLengthPrefixed(tx) + res := deliverTx(bz) + if !res.IsOK() { + panic(res.Log) + } + } + return app.stakingKeeper.ApplyAndReturnValidatorSetUpdates(ctx) +} + // 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, "") - } - + app.cdc.MustUnmarshalJSON(req.AppStateBytes, &genesisState) 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)) - } - } + // XXX this is a temporary partial init-genesis implementation to allow for + // an invariance check for the crisis module + ctx = app.NewContext(false, abci.Header{Height: app.LastBlockHeight() + 1}) + dummyGenesisData := make(map[string]json.RawMessage) + _, err := app.mm.InitGenesis(ctx, dummyGenesisData) + if err != nil { + panic(err) } - // assert runtime invariants - app.assertRuntimeInvariants() - return abci.ResponseInitChain{ Validators: validators, } @@ -347,60 +278,3 @@ func (app *GaiaApp) initChainer(ctx sdk.Context, req abci.RequestInitChain) abci func (app *GaiaApp) LoadHeight(height int64) error { return app.LoadVersion(height, app.keyMain) } - -// ______________________________________________________________________________________________ - -var _ sdk.StakingHooks = StakingHooks{} - -// StakingHooks contains combined distribution and slashing hooks needed for the -// staking module. -type StakingHooks struct { - dh distr.Hooks - sh slashing.Hooks -} - -func NewStakingHooks(dh distr.Hooks, sh slashing.Hooks) StakingHooks { - return StakingHooks{dh, sh} -} - -// nolint -func (h StakingHooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) { - h.dh.AfterValidatorCreated(ctx, valAddr) - h.sh.AfterValidatorCreated(ctx, valAddr) -} -func (h StakingHooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) { - h.dh.BeforeValidatorModified(ctx, valAddr) - h.sh.BeforeValidatorModified(ctx, valAddr) -} -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) -} -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) -} -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) -} -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) -} -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) -} -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) -} -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) -} diff --git a/cmd/gaia/app/export.go b/cmd/gaia/app/export.go index 2cb110bf8926..66acaaedf882 100644 --- a/cmd/gaia/app/export.go +++ b/cmd/gaia/app/export.go @@ -59,6 +59,8 @@ func (app *GaiaApp) ExportAppStateAndValidators(forZeroHeight bool, jailWhiteLis } // prepare for fresh start at zero height +// NOTE zero height genesis is a temporary feature which will be deprecated +// in favour of export at a block height func (app *GaiaApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []string) { applyWhiteList := false @@ -78,7 +80,7 @@ func (app *GaiaApp) prepForZeroHeightGenesis(ctx sdk.Context, jailWhiteList []st } /* Just to be safe, assert the invariants on current state. */ - app.assertRuntimeInvariantsOnContext(ctx) + app.crisisKeeper.AssertInvariants(ctx, app.Logger()) /* Handle fee distribution state. */ diff --git a/cmd/gaia/app/genesis.go b/cmd/gaia/app/genesis.go index 997cd131c751..fbeb8378dd69 100644 --- a/cmd/gaia/app/genesis.go +++ b/cmd/gaia/app/genesis.go @@ -25,11 +25,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/staking" ) -var ( - // bonded tokens given to genesis validators/accounts - freeTokensPerAcc = sdk.TokensFromTendermintPower(150) - defaultBondDenom = sdk.DefaultBondDenom -) +// XXX should use map for all module data // State to Unmarshal type GenesisState struct { @@ -46,8 +42,7 @@ type GenesisState struct { } func NewGenesisState(accounts []GenesisAccount, authData auth.GenesisState, - bankData bank.GenesisState, - stakingData staking.GenesisState, mintData mint.GenesisState, + bankData bank.GenesisState, stakingData staking.GenesisState, mintData mint.GenesisState, distrData distr.GenesisState, govData gov.GenesisState, crisisData crisis.GenesisState, slashingData slashing.GenesisState) GenesisState { @@ -121,32 +116,22 @@ func NewGenesisAccountI(acc auth.Account) GenesisAccount { // convert GenesisAccount to auth.BaseAccount func (ga *GenesisAccount) ToAccount() auth.Account { - bacc := &auth.BaseAccount{ - Address: ga.Address, - Coins: ga.Coins.Sort(), - AccountNumber: ga.AccountNumber, - Sequence: ga.Sequence, - } + + bacc := auth.NewBaseAccount(ga.Address, ga.Coins.Sort(), + nil, ga.AccountNumber, ga.Sequence) if !ga.OriginalVesting.IsZero() { - baseVestingAcc := &auth.BaseVestingAccount{ - BaseAccount: bacc, - OriginalVesting: ga.OriginalVesting, - DelegatedFree: ga.DelegatedFree, - DelegatedVesting: ga.DelegatedVesting, - EndTime: ga.EndTime, - } - if ga.StartTime != 0 && ga.EndTime != 0 { - return &auth.ContinuousVestingAccount{ - BaseVestingAccount: baseVestingAcc, - StartTime: ga.StartTime, - } - } else if ga.EndTime != 0 { - return &auth.DelayedVestingAccount{ - BaseVestingAccount: baseVestingAcc, - } - } else { + baseVestingAcc := auth.NewBaseVestingAccount( + bacc, ga.OriginalVesting, ga.DelegatedFree, + ga.DelegatedVesting, ga.EndTime) + + switch { + case ga.StartTime != 0 && ga.EndTime != 0: + return auth.NewContinuousVestingAccountRaw(baseVestingAcc, ga.StartTime) + case ga.EndTime != 0: + return auth.NewDelayedVestingAccountRaw(baseVestingAcc) + default: panic(fmt.Sprintf("invalid genesis vesting account: %+v", ga)) } } @@ -154,6 +139,8 @@ func (ga *GenesisAccount) ToAccount() auth.Account { return bacc } +// XXX move to init unused besides there and in testing + // Create the core parameters for genesis initialization for gaia // note that the pubkey input is this machines pubkey func GaiaAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) ( @@ -202,6 +189,18 @@ func GaiaAppGenState(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []js return genesisState, nil } +// GaiaAppGenState but with JSON +func GaiaAppGenStateJSON(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) ( + appState json.RawMessage, err error) { + + // create the final app state + genesisState, err := GaiaAppGenState(cdc, genDoc, appGenTxs) + if err != nil { + return nil, err + } + return codec.MarshalJSONIndent(cdc, genesisState) +} + // NewDefaultGenesisState generates the default state for gaia. func NewDefaultGenesisState() GenesisState { return GenesisState{ @@ -219,8 +218,6 @@ func NewDefaultGenesisState() GenesisState { } // GaiaValidateGenesisState ensures that the genesis state obeys the expected invariants -// TODO: No validators are both bonded and jailed (#2088) -// TODO: Error if there is a duplicate validator (#1708) // TODO: Ensure all state machine parameters are in genesis (#1704) func GaiaValidateGenesisState(genesisState GenesisState) error { if err := validateGenesisStateAccounts(genesisState.Accounts); err != nil { @@ -292,17 +289,6 @@ func validateGenesisStateAccounts(accs []GenesisAccount) error { return nil } -// GaiaAppGenState but with JSON -func GaiaAppGenStateJSON(cdc *codec.Codec, genDoc tmtypes.GenesisDoc, appGenTxs []json.RawMessage) ( - appState json.RawMessage, err error) { - // create the final app state - genesisState, err := GaiaAppGenState(cdc, genDoc, appGenTxs) - if err != nil { - return nil, err - } - return codec.MarshalJSONIndent(cdc, genesisState) -} - // CollectStdTxs processes and validates application's genesis StdTxs and returns // the list of appGenTxs, and persistent peers required to generate genesis.json. func CollectStdTxs(cdc *codec.Codec, moniker string, genTxsDir string, genDoc tmtypes.GenesisDoc) ( @@ -402,16 +388,3 @@ func CollectStdTxs(cdc *codec.Codec, moniker string, genTxsDir string, genDoc tm return appGenTxs, persistentPeers, nil } - -func NewDefaultGenesisAccount(addr sdk.AccAddress) GenesisAccount { - accAuth := auth.NewBaseAccountWithAddress(addr) - coins := sdk.Coins{ - sdk.NewCoin("footoken", sdk.NewInt(1000)), - sdk.NewCoin(defaultBondDenom, freeTokensPerAcc), - } - - coins.Sort() - - accAuth.Coins = coins - return NewGenesisAccount(&accAuth) -} diff --git a/cmd/gaia/app/genesis_test.go b/cmd/gaia/app/genesis_test.go index 300f4afcdec6..062186113ab4 100644 --- a/cmd/gaia/app/genesis_test.go +++ b/cmd/gaia/app/genesis_test.go @@ -9,7 +9,6 @@ import ( "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/ed25519" - "github.com/tendermint/tendermint/crypto/secp256k1" tmtypes "github.com/tendermint/tendermint/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -25,8 +24,9 @@ var ( addr2 = sdk.ValAddress(pk2.Address()) addr3 = sdk.ValAddress(pk3.Address()) - emptyAddr sdk.ValAddress - emptyPubkey crypto.PubKey + emptyAddr sdk.ValAddress + emptyPubkey crypto.PubKey + testBondDenom = sdk.DefaultBondDenom ) func makeGenesisState(t *testing.T, genTxs []auth.StdTx) GenesisState { @@ -41,7 +41,7 @@ func makeGenesisState(t *testing.T, genTxs []auth.StdTx) GenesisState { msg := msgs[0].(staking.MsgCreateValidator) acc := auth.NewBaseAccountWithAddress(sdk.AccAddress(msg.ValidatorAddress)) - acc.Coins = sdk.NewCoins(sdk.NewInt64Coin(defaultBondDenom, 150)) + acc.Coins = sdk.NewCoins(sdk.NewInt64Coin(testBondDenom, 150)) genAccs[i] = NewGenesisAccount(&acc) stakingData.Pool.NotBondedTokens = stakingData.Pool.NotBondedTokens.Add(sdk.NewInt(150)) // increase the supply } @@ -55,7 +55,7 @@ func TestToAccount(t *testing.T) { priv := ed25519.GenPrivKey() addr := sdk.AccAddress(priv.PubKey().Address()) authAcc := auth.NewBaseAccountWithAddress(addr) - authAcc.SetCoins(sdk.NewCoins(sdk.NewInt64Coin(defaultBondDenom, 150))) + authAcc.SetCoins(sdk.NewCoins(sdk.NewInt64Coin(testBondDenom, 150))) genAcc := NewGenesisAccount(&authAcc) acc := genAcc.ToAccount() require.IsType(t, &auth.BaseAccount{}, acc) @@ -104,7 +104,7 @@ func TestGaiaAppGenState(t *testing.T) { func makeMsg(name string, pk crypto.PubKey) auth.StdTx { desc := staking.NewDescription(name, "", "", "") comm := staking.CommissionMsg{} - msg := staking.NewMsgCreateValidator(sdk.ValAddress(pk.Address()), pk, sdk.NewInt64Coin(defaultBondDenom, + msg := staking.NewMsgCreateValidator(sdk.ValAddress(pk.Address()), pk, sdk.NewInt64Coin(testBondDenom, 50), desc, comm, sdk.OneInt()) return auth.NewStdTx([]sdk.Msg{msg}, auth.StdFee{}, nil, "") } @@ -147,13 +147,6 @@ func TestGaiaGenesisValidation(t *testing.T) { require.Error(t, err) } -func TestNewDefaultGenesisAccount(t *testing.T) { - addr := secp256k1.GenPrivKeySecp256k1([]byte("")).PubKey().Address() - acc := NewDefaultGenesisAccount(sdk.AccAddress(addr)) - require.Equal(t, sdk.NewInt(1000), acc.Coins.AmountOf("footoken")) - require.Equal(t, sdk.TokensFromTendermintPower(150), acc.Coins.AmountOf(defaultBondDenom)) -} - func TestGenesisStateSanitize(t *testing.T) { genesisState := makeGenesisState(t, nil) require.Nil(t, GaiaValidateGenesisState(genesisState)) diff --git a/cmd/gaia/app/invariants.go b/cmd/gaia/app/invariants.go deleted file mode 100644 index 899d6bdbac22..000000000000 --- a/cmd/gaia/app/invariants.go +++ /dev/null @@ -1,31 +0,0 @@ -package app - -import ( - "fmt" - "time" - - abci "github.com/tendermint/tendermint/abci/types" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func (app *GaiaApp) assertRuntimeInvariants() { - ctx := app.NewContext(false, abci.Header{Height: app.LastBlockHeight() + 1}) - app.assertRuntimeInvariantsOnContext(ctx) -} - -func (app *GaiaApp) assertRuntimeInvariantsOnContext(ctx sdk.Context) { - start := time.Now() - invarRoutes := app.crisisKeeper.Routes() - for _, ir := range invarRoutes { - if err := ir.Invar(ctx); err != nil { - panic(fmt.Errorf("invariant broken: %s\n"+ - "\tCRITICAL please submit the following transaction:\n"+ - "\t\t gaiacli tx crisis invariant-broken %v %v", err, ir.ModuleName, ir.Route)) - } - } - end := time.Now() - diff := end.Sub(start) - app.BaseApp.Logger().With("module", "invariants").Info( - "Asserted all invariants", "duration", diff, "height", app.LastBlockHeight()) -} diff --git a/cmd/gaia/cmd/gaiacli/main.go b/cmd/gaia/cmd/gaiacli/main.go index 4fd6d1c3ad75..0b67a57a21b1 100644 --- a/cmd/gaia/cmd/gaiacli/main.go +++ b/cmd/gaia/cmd/gaiacli/main.go @@ -69,7 +69,7 @@ func main() { // Module clients hold cli commnads (tx,query) and lcd routes // TODO: Make the lcd command take a list of ModuleClient - mc := []sdk.ModuleClients{ + mc := []sdk.ModuleClient{ govClient.NewModuleClient(gv.StoreKey, cdc), distClient.NewModuleClient(distcmd.StoreKey, cdc), stakingclient.NewModuleClient(st.StoreKey, cdc), @@ -114,7 +114,7 @@ func main() { } } -func queryCmd(cdc *amino.Codec, mc []sdk.ModuleClients) *cobra.Command { +func queryCmd(cdc *amino.Codec, mc []sdk.ModuleClient) *cobra.Command { queryCmd := &cobra.Command{ Use: "query", Aliases: []string{"q"}, @@ -140,7 +140,7 @@ func queryCmd(cdc *amino.Codec, mc []sdk.ModuleClients) *cobra.Command { return queryCmd } -func txCmd(cdc *amino.Codec, mc []sdk.ModuleClients) *cobra.Command { +func txCmd(cdc *amino.Codec, mc []sdk.ModuleClient) *cobra.Command { txCmd := &cobra.Command{ Use: "tx", Short: "Transactions subcommands", diff --git a/cmd/gaia/testnets/README.md b/cmd/gaia/testnets/README.md deleted file mode 100644 index e64db9f7dd7e..000000000000 --- a/cmd/gaia/testnets/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# DEPRECATED - -The content of this file was moved to the `/docs` folder and is hosted on the -[website](https://cosmos.network/docs/getting-started/full-node.html#run-a-full-node). - -The rest of this folder was moved to the [testnets -repo](https://github.com/cosmos/testnets). diff --git a/cmd/gaia/testnets/STATUS.md b/cmd/gaia/testnets/STATUS.md deleted file mode 100644 index 4db4297845d6..000000000000 --- a/cmd/gaia/testnets/STATUS.md +++ /dev/null @@ -1,132 +0,0 @@ -# DEPRECATED - -See [testnets repo](https://github.com/cosmos/testnets). - -## *July 22, 2018, 5:30 EST* - Gaia-7001 Consensus Failure - -- [Consensus Failure at Block 24570](https://github.com/cosmos/cosmos-sdk/issues/1787) - - -## *July 17, 2018, 4:00 EST* - New Testnet Gaia-7001 - -- New testnet with fixes for the genesis file -- Increased max validators to 128 - -## *July 17, 2018, 3:00 EST* - Gaia-7000 consensus failure - -- Misconfiguration in the genesis file led to a consensus failure -- New genesis file for gaia-7001 will be up soon - -## *July 17, 2018, 2:40 EST* - Gaia-7000 is making blocks! - -- Gaia-7000 is live and making blocks! - -## *July 16, 2018, 17:00 EST* - New Testnet Gaia-7000 - -- Gaia-7000 is up! -- 108 validators in the genesis.json file. - -## *July 2, 2018, 1:00 EST* - Gaia-6002 slashing failure - -- Gaia-6002 has been halted due to a slashing issue. -- The team is taking its time to look into this Gaia-7000 will be introduced this week. - -## *June 13, 2018, 17:00 EST* - Gaia-6002 is making blocks! - -- Gaia-6002 is live and making blocks -- Absent validators have been slashed and jailed -- Currently live with 17 validators - -## *June 13, 2018, 4:30 EST* - New Testnet Gaia-6002 - -- After fixing bugs from gaia-6001, especially [issue - #1197](https://github.com/cosmos/cosmos-sdk/issues/1197), we are announcing a - new testnet, Gaia-6002 -- Gaia-6002 has the same genesis file as Gaia-6001, just with the chain-id - updated -- Update from previous testnet [here](https://github.com/cosmos/cosmos-sdk/tree/master/cmd/gaia/testnets#upgrading-from-previous-testnet) - -## *June 13, 2018, 4:30 EST* - New Release - -- Released gaia - [v0.19.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.19.0) -- Includes various bug-fixes for staking found on Gaia-6001 - -## *June 13, 2018, 2:30 EST* - Published Postmortem of Gaia-6001 failure - -- A bug in the design of the staking data model caused a sanity check to fail -- Full writeup - [here](https://github.com/cosmos/cosmos-sdk/issues/1197#issuecomment-396823021) - -## *June 10, 2018, 8:30 EST* - Gaia-6001 consensus failure - -- Validator unbonding and revocation activity caused a consensus failure -- There is a bug in the staking module that must be fixed -- The team is taking its time to look into this and release a fix following a - proper protocol for hotfix upgrades to the testnet -- Please stay tuned! - -## *June 9, 2018, 14:00 EST* - New Release - -- Released gaia - [v0.18.0](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.18.0) with - update for Tendermint - [v0.20.0](https://github.com/tendermint/tendermint/releases/tag/v0.20.0) -- Includes bug fix for declaring candidacy from the command line - -## *June 8, 2018, 23:30 EST* - Gaia-6001 is making blocks - -- +2/3 of the voting power is finally online for Gaia-6001 and it is making - blocks! -- This is a momentous achievement - a successful asynchronous decentralized - testnet launch -- Congrats everyone! - -## *June 8, 2018, 12:00 EST* - New Testnet Gaia-6001 - -- After some confusion around testnet deployment and a contention testnet - hardfork, a new genesis file and network was released for `gaia-6001` - -## *June 7, 2018, 9:00 EST* - New Testnet Gaia-6000 - -- Released a new `genesis.json` file for `gaia-6000` -- Initial validators include those that were most active in - the gaia-5001 testnet -- Join the network via gaia `v0.18.0-rc0` - -## *June 5, 2018, 21:00 EST* - New Release - -- Released gaia - [v0.17.5](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.17.5) - with update for Tendermint - [v0.19.9](https://github.com/tendermint/tendermint/releases/tag/v0.19.9) -- Fixes many bugs! - - evidence gossipping - - mempool deadlock - - WAL panic - - memory leak -- Please update to this to put a stop to the rampant invalid evidence gossiping - :) - -## *May 31, 2018, 14:00 EST* - New Release - -- Released gaia - [v0.17.4](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.17.4) with update for Tendermint v0.19.7 -- Fixes a WAL bug and some more -- Please update to this if you have trouble restarting a node - -## *May 31, 2018, 2:00 EST* - Testnet Halt - -- A validator equivocated last week and Evidence is being rampantly gossipped -- Peers that can't process the evidence (either too far behind or too far ahead) are disconnecting from the peers that - sent it, causing high peer turn-over -- The high peer turn-over may be causing a memory-leak, resulting in some nodes - crashing and the testnet halting -- We need to fix some issues in the EvidenceReactor to address this and also - investigate the possible memory-leak - -## *May 29, 2018* - New Release - -- Released v0.17.3 with update for Tendermint v0.19.6 -- Fixes fast-sync bug -- Please update to this to sync with the testnet diff --git a/types/invariant.go b/types/invariant.go index aa8aca566507..01209d178488 100644 --- a/types/invariant.go +++ b/types/invariant.go @@ -8,3 +8,8 @@ type Invariant func(ctx Context) error // Invariants defines a group of invariants type Invariants []Invariant + +// expected interface for routing invariants +type InvariantRouter interface { + RegisterRoute(moduleName, route string, invar Invariant) +} diff --git a/types/module.go b/types/module.go new file mode 100644 index 000000000000..339a6ad8e54e --- /dev/null +++ b/types/module.go @@ -0,0 +1,197 @@ +package types + +import ( + "encoding/json" + + "github.com/spf13/cobra" + abci "github.com/tendermint/tendermint/abci/types" +) + +// ModuleClient helps modules provide a standard interface for exporting client functionality +type ModuleClient interface { + GetQueryCmd() *cobra.Command + GetTxCmd() *cobra.Command +} + +// AppModule is the standard form for an application module +type AppModule interface { + + // app name + Name() string + + // registers + RegisterInvariants(InvariantRouter) + + // routes + Route() string + NewHandler() Handler + QuerierRoute() string + NewQuerierHandler() Querier + + //// genesis + //DefaultGenesisState() json.RawMessage + //ValidateGenesis(json.RawMessage) error + InitGenesis(Context, json.RawMessage) ([]abci.ValidatorUpdate, error) + //ExportGenesis(Context) json.RawMessage + + BeginBlock(Context, abci.RequestBeginBlock) Tags + EndBlock(Context, abci.RequestEndBlock) ([]abci.ValidatorUpdate, Tags) +} + +// module manager provides the high level utility for managing and executing +// operations for a group of modules +type ModuleManager struct { + Modules map[string]AppModule + OrderInitGenesis []string + OrderExportGenesis []string + OrderBeginBlockers []string + OrderEndBlockers []string +} + +// NewModuleManager creates a new ModuleManager object +func NewModuleManager(modules ...AppModule) *ModuleManager { + + moduleMap := make(map[string]AppModule) + var modulesStr []string + for _, module := range modules { + moduleMap[module.Name()] = module + modulesStr = append(modulesStr, module.Name()) + } + + return &ModuleManager{ + Modules: moduleMap, + OrderInitGenesis: modulesStr, + OrderExportGenesis: modulesStr, + OrderBeginBlockers: modulesStr, + OrderEndBlockers: modulesStr, + } +} + +// set the order of init genesis calls +func (mm *ModuleManager) SetOrderInitGenesis(moduleNames ...string) { + mm.OrderInitGenesis = moduleNames +} + +// set the order of export genesis calls +func (mm *ModuleManager) SetOrderExportGenesis(moduleNames ...string) { + mm.OrderExportGenesis = moduleNames +} + +// set the order of set begin-blocker calls +func (mm *ModuleManager) SetOrderBeginBlockers(moduleNames ...string) { + mm.OrderBeginBlockers = moduleNames +} + +// set the order of set end-blocker calls +func (mm *ModuleManager) SetOrderEndBlockers(moduleNames ...string) { + mm.OrderEndBlockers = moduleNames +} + +// register all module routes and module querier routes +func (mm *ModuleManager) RegisterInvariants(invarRouter InvariantRouter) { + for _, module := range mm.Modules { + module.RegisterInvariants(invarRouter) + } +} + +// register all module routes and module querier routes +func (mm *ModuleManager) RegisterRoutes(router Router, queryRouter QueryRouter) { + for _, module := range mm.Modules { + if module.Route() != "" { + router.AddRoute(module.Route(), module.NewHandler()) + } + if module.QuerierRoute() != "" { + queryRouter.AddRoute(module.QuerierRoute(), module.NewQuerierHandler()) + } + } +} + +//// validate all genesis information +//func (mm *ModuleManager) ValidateGenesis(genesisData map[string]json.RawMessage) error { +//for _, module := range mm.Modules { +//err := module.ValidateGenesis(genesisDate[module.Name()]) +//if err != nil { +//return err +//} +//} +//return nil +//} + +//// default genesis state for modules +//func (mm *ModuleManager) DefaultGenesisState() map[string]json.RawMessage { +//defaultGenesisState := make(map[string]json.RawMessage) +//for _, module := range mm.Modules { +//defaultGenesisState[module.Name()] = module.DefaultGenesisState() +//} +//return defaultGenesisState +//} + +// perform init genesis functionality for modules +func (mm *ModuleManager) InitGenesis(ctx Context, genesisData map[string]json.RawMessage) ([]abci.ValidatorUpdate, error) { + moduleNames := mm.OrderInitGenesis + + var validatorUpdates []abci.ValidatorUpdate + for _, moduleName := range moduleNames { + moduleValUpdates, err := mm.Modules[moduleName].InitGenesis(ctx, genesisData[moduleName]) + if err != nil { + return []abci.ValidatorUpdate{}, err + } + + // use these validator updates if provided, the module manager assumes + // only one module will update the validator set + if len(moduleValUpdates) > 0 { + validatorUpdates = moduleValUpdates + } + } + return validatorUpdates, nil +} + +//// perform export genesis functionality for modules +//func (mm *ModuleManager) ExportGenesis(ctx Context) (genesisData map[string]json.RawMessage) { +//moduleNames := mm.OrderExportGenesis + +//for _, moduleName := range moduleNames { +//mm.Modules[moduleName].ExportGenesis(ctx) +//} +//return genesisData +//} + +// perform begin block functionality for modules +func (mm *ModuleManager) BeginBlock(ctx Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { + moduleNames := mm.OrderBeginBlockers + + tags := EmptyTags() + for _, moduleName := range moduleNames { + moduleTags := mm.Modules[moduleName].BeginBlock(ctx, req) + tags = tags.AppendTags(moduleTags) + } + + return abci.ResponseBeginBlock{ + Tags: tags.ToKVPairs(), + } +} + +// perform end block functionality for modules +func (mm *ModuleManager) EndBlock(ctx Context, req abci.RequestEndBlock) abci.ResponseEndBlock { + moduleNames := mm.OrderEndBlockers + + validatorUpdates := []abci.ValidatorUpdate{} + tags := EmptyTags() + for _, moduleName := range moduleNames { + moduleValUpdates, moduleTags := mm.Modules[moduleName].EndBlock(ctx, req) + tags = tags.AppendTags(moduleTags) + + // use these validator updates if provided, the module manager assumes + // only one module will update the validator set + if len(moduleValUpdates) > 0 { + validatorUpdates = moduleValUpdates + } + } + + return abci.ResponseEndBlock{ + ValidatorUpdates: validatorUpdates, + Tags: tags, + } +} + +// DONTCOVER diff --git a/types/module_clients.go b/types/module_clients.go deleted file mode 100644 index 3b3a9d9a5d37..000000000000 --- a/types/module_clients.go +++ /dev/null @@ -1,11 +0,0 @@ -package types - -import ( - "github.com/spf13/cobra" -) - -// ModuleClients helps modules provide a standard interface for exporting client functionality -type ModuleClients interface { - GetQueryCmd() *cobra.Command - GetTxCmd() *cobra.Command -} diff --git a/types/module_test.go b/types/module_test.go new file mode 100644 index 000000000000..939d70bfb334 --- /dev/null +++ b/types/module_test.go @@ -0,0 +1,16 @@ +package types + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSetOrderBeginBlockers(t *testing.T) { + mm := NewModuleManager() + mm.SetOrderBeginBlockers("a", "b", "c") + obb := mm.OrderBeginBlockers + require.Equal(t, 3, len(obb)) + assert.Equal(t, []string{"a", "b", "c"}, obb) +} diff --git a/types/router.go b/types/router.go new file mode 100644 index 000000000000..7b45918c3cc6 --- /dev/null +++ b/types/router.go @@ -0,0 +1,13 @@ +package types + +// Router provides handlers for each transaction type. +type Router interface { + AddRoute(r string, h Handler) Router + Route(path string) Handler +} + +// QueryRouter provides queryables for each query path. +type QueryRouter interface { + AddRoute(r string, h Querier) QueryRouter + Route(path string) Querier +} diff --git a/x/auth/account.go b/x/auth/account.go index 0c0e71a48c40..99132d3ba26a 100644 --- a/x/auth/account.go +++ b/x/auth/account.go @@ -81,6 +81,19 @@ type BaseAccount struct { Sequence uint64 `json:"sequence"` } +// NewBaseAccount creates a new BaseAccount object +func NewBaseAccount(address sdk.AccAddress, coins sdk.Coins, + pubKey crypto.PubKey, accountNumber uint64, sequence uint64) *BaseAccount { + + return &BaseAccount{ + Address: address, + Coins: coins, + PubKey: pubKey, + AccountNumber: accountNumber, + Sequence: sequence, + } +} + // String implements fmt.Stringer func (acc BaseAccount) String() string { var pubkey string @@ -190,6 +203,19 @@ type BaseVestingAccount struct { EndTime int64 `json:"end_time"` // when the coins become unlocked } +// NewBaseVestingAccount creates a new BaseVestingAccount object +func NewBaseVestingAccount(baseAccount *BaseAccount, originalVesting sdk.Coins, + delegatedFree sdk.Coins, delegatedVesting sdk.Coins, endTime int64) *BaseVestingAccount { + + return &BaseVestingAccount{ + BaseAccount: baseAccount, + OriginalVesting: originalVesting, + DelegatedFree: delegatedFree, + DelegatedVesting: delegatedVesting, + EndTime: endTime, + } +} + // String implements fmt.Stringer func (bva BaseVestingAccount) String() string { var pubkey string @@ -352,6 +378,16 @@ type ContinuousVestingAccount struct { StartTime int64 `json:"start_time"` // when the coins start to vest } +// NewContinuousVestingAccountRaw creates a new ContinuousVestingAccount object from BaseVestingAccount +func NewContinuousVestingAccountRaw(bva *BaseVestingAccount, + startTime int64) *ContinuousVestingAccount { + + return &ContinuousVestingAccount{ + BaseVestingAccount: bva, + StartTime: startTime, + } +} + // NewContinuousVestingAccount returns a new ContinuousVestingAccount func NewContinuousVestingAccount( baseAcc *BaseAccount, StartTime, EndTime int64, @@ -462,6 +498,13 @@ type DelayedVestingAccount struct { *BaseVestingAccount } +// NewDelayedVestingAccountRaw creates a new DelayedVestingAccount object from BaseVestingAccount +func NewDelayedVestingAccountRaw(bva *BaseVestingAccount) *DelayedVestingAccount { + return &DelayedVestingAccount{ + BaseVestingAccount: bva, + } +} + // NewDelayedVestingAccount returns a DelayedVestingAccount func NewDelayedVestingAccount(baseAcc *BaseAccount, EndTime int64) *DelayedVestingAccount { baseVestingAcc := &BaseVestingAccount{ diff --git a/x/auth/module.go b/x/auth/module.go new file mode 100644 index 000000000000..ef415bd5adac --- /dev/null +++ b/x/auth/module.go @@ -0,0 +1,64 @@ +package auth + +import ( + "encoding/json" + + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +var _ sdk.AppModule = AppModule{} + +// name of this module +const ModuleName = "auth" + +// app module object +type AppModule struct { + accountKeeper AccountKeeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(accountKeeper AccountKeeper) AppModule { + return AppModule{ + accountKeeper: accountKeeper, + } +} + +// module name +func (AppModule) Name() string { + return ModuleName +} + +// register invariants +func (AppModule) RegisterInvariants(_ sdk.InvariantRouter) {} + +// module message route name +func (AppModule) Route() string { return "" } + +// module handler +func (AppModule) NewHandler() sdk.Handler { return nil } + +// module querier route name +func (AppModule) QuerierRoute() string { + return QuerierRoute +} + +// module querier +func (a AppModule) NewQuerierHandler() sdk.Querier { + return NewQuerier(a.accountKeeper) +} + +// module init-genesis +func (a AppModule) InitGenesis(_ sdk.Context, _ json.RawMessage) ([]abci.ValidatorUpdate, error) { + return []abci.ValidatorUpdate{}, nil +} + +// module begin-block +func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) sdk.Tags { + return sdk.EmptyTags() +} + +// module end-block +func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) { + return []abci.ValidatorUpdate{}, sdk.EmptyTags() +} diff --git a/x/auth/params.go b/x/auth/params.go index 0e098d5852cc..e6dae8721db6 100644 --- a/x/auth/params.go +++ b/x/auth/params.go @@ -9,7 +9,7 @@ import ( ) // DefaultParamspace defines the default auth module parameter subspace -const DefaultParamspace = "auth" +const DefaultParamspace = ModuleName // Default parameter values const ( diff --git a/x/auth/simulation/fake.go b/x/auth/simulation/fake.go index 7849bd807848..b1b76f2dc969 100644 --- a/x/auth/simulation/fake.go +++ b/x/auth/simulation/fake.go @@ -20,7 +20,7 @@ func SimulateDeductFee(m auth.AccountKeeper, f auth.FeeCollectionKeeper) simulat account := simulation.RandomAcc(r, accs) stored := m.GetAccount(ctx, account.Address) initCoins := stored.GetCoins() - opMsg = simulation.NewOperationMsgBasic("auth", "deduct_fee", "", false, nil) + opMsg = simulation.NewOperationMsgBasic(auth.ModuleName, "deduct_fee", "", false, nil) if len(initCoins) == 0 { return opMsg, nil, nil diff --git a/x/bank/bench_test.go b/x/bank/bench_test.go index 95918110c4de..8425f0f93008 100644 --- a/x/bank/bench_test.go +++ b/x/bank/bench_test.go @@ -21,7 +21,7 @@ func getBenchmarkMockApp() (*mock.App, error) { mapp.ParamsKeeper.Subspace(DefaultParamspace), DefaultCodespace, ) - mapp.Router().AddRoute("bank", NewHandler(bankKeeper)) + mapp.Router().AddRoute(RouterKey, NewHandler(bankKeeper)) mapp.SetInitChainer(getInitChainer(mapp, bankKeeper)) err := mapp.CompleteSetup() diff --git a/x/bank/errors.go b/x/bank/errors.go index 7c5feaf4a848..5b579fabb28d 100644 --- a/x/bank/errors.go +++ b/x/bank/errors.go @@ -6,7 +6,7 @@ import ( // Bank errors reserve 100 ~ 199. const ( - DefaultCodespace sdk.CodespaceType = "bank" + DefaultCodespace sdk.CodespaceType = ModuleName CodeSendDisabled sdk.CodeType = 101 CodeInvalidInputsOutputs sdk.CodeType = 102 diff --git a/x/bank/expected_keepers.go b/x/bank/expected_keepers.go deleted file mode 100644 index 6d256d926d6e..000000000000 --- a/x/bank/expected_keepers.go +++ /dev/null @@ -1,10 +0,0 @@ -package bank - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// expected crisis keeper -type CrisisKeeper interface { - RegisterRoute(moduleName, route string, invar sdk.Invariant) -} diff --git a/x/bank/invariants.go b/x/bank/invariants.go index 4ca4c3d9a1df..a0e30db98372 100644 --- a/x/bank/invariants.go +++ b/x/bank/invariants.go @@ -9,8 +9,8 @@ import ( ) // register bank invariants -func RegisterInvariants(c CrisisKeeper, ak auth.AccountKeeper) { - c.RegisterRoute("bank", "nonnegative-outstanding", +func RegisterInvariants(ir sdk.InvariantRouter, ak auth.AccountKeeper) { + ir.RegisterRoute(RouterKey, "nonnegative-outstanding", NonnegativeBalanceInvariant(ak)) } diff --git a/x/bank/module.go b/x/bank/module.go new file mode 100644 index 000000000000..856d12f6d5c3 --- /dev/null +++ b/x/bank/module.go @@ -0,0 +1,69 @@ +package bank + +import ( + "encoding/json" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + abci "github.com/tendermint/tendermint/abci/types" +) + +var _ sdk.AppModule = AppModule{} + +// name of this module +const ModuleName = "bank" + +// app module for bank +type AppModule struct { + keeper Keeper + accountKeeper auth.AccountKeeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(keeper Keeper, accountKeeper auth.AccountKeeper) AppModule { + return AppModule{ + keeper: keeper, + accountKeeper: accountKeeper, + } +} + +// module name +func (AppModule) Name() string { + return ModuleName +} + +// register invariants +func (a AppModule) RegisterInvariants(ir sdk.InvariantRouter) { + RegisterInvariants(ir, a.accountKeeper) +} + +// module message route name +func (AppModule) Route() string { + return RouterKey +} + +// module handler +func (a AppModule) NewHandler() sdk.Handler { + return NewHandler(a.keeper) +} + +// module querier route name +func (AppModule) QuerierRoute() string { return "" } + +// module querier +func (AppModule) NewQuerierHandler() sdk.Querier { return nil } + +// module init-genesis +func (a AppModule) InitGenesis(_ sdk.Context, _ json.RawMessage) ([]abci.ValidatorUpdate, error) { + return []abci.ValidatorUpdate{}, nil +} + +// module begin-block +func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) sdk.Tags { + return sdk.EmptyTags() +} + +// module end-block +func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) { + return []abci.ValidatorUpdate{}, sdk.EmptyTags() +} diff --git a/x/bank/msgs.go b/x/bank/msgs.go index c9b4f554482b..2455190d345b 100644 --- a/x/bank/msgs.go +++ b/x/bank/msgs.go @@ -5,7 +5,7 @@ import ( ) // RouterKey is they name of the bank module -const RouterKey = "bank" +const RouterKey = ModuleName // MsgSend - high level transaction of the coin module type MsgSend struct { diff --git a/x/bank/msgs_test.go b/x/bank/msgs_test.go index 521e81761ba8..3b7813e0d508 100644 --- a/x/bank/msgs_test.go +++ b/x/bank/msgs_test.go @@ -15,7 +15,7 @@ func TestMsgSendRoute(t *testing.T) { coins := sdk.NewCoins(sdk.NewInt64Coin("atom", 10)) var msg = NewMsgSend(addr1, addr2, coins) - require.Equal(t, msg.Route(), "bank") + require.Equal(t, msg.Route(), RouterKey) require.Equal(t, msg.Type(), "send") } @@ -80,7 +80,7 @@ func TestMsgMultiSendRoute(t *testing.T) { } // TODO some failures for bad result - require.Equal(t, msg.Route(), "bank") + require.Equal(t, msg.Route(), RouterKey) require.Equal(t, msg.Type(), "multisend") } diff --git a/x/bank/params.go b/x/bank/params.go index b381e4e847e5..01602e52cceb 100644 --- a/x/bank/params.go +++ b/x/bank/params.go @@ -6,7 +6,7 @@ import ( const ( // DefaultParamspace for params keeper - DefaultParamspace = "bank" + DefaultParamspace = ModuleName // DefaultSendEnabled enabled DefaultSendEnabled = true ) diff --git a/x/crisis/abci_app.go b/x/crisis/abci_app.go new file mode 100644 index 000000000000..afd973ea63c2 --- /dev/null +++ b/x/crisis/abci_app.go @@ -0,0 +1,17 @@ +package crisis + +import ( + "github.com/tendermint/tendermint/libs/log" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// check all registered invariants +func EndBlocker(ctx sdk.Context, k Keeper, logger log.Logger) { + + if k.invCheckPeriod == 0 || ctx.BlockHeight()%int64(k.invCheckPeriod) != 0 { + // skip running the invariant check + return + } + k.AssertInvariants(ctx, logger) +} diff --git a/x/crisis/handler.go b/x/crisis/handler.go index da30d976aaa1..475ca8535c99 100644 --- a/x/crisis/handler.go +++ b/x/crisis/handler.go @@ -7,11 +7,8 @@ import ( "github.com/cosmos/cosmos-sdk/x/crisis/tags" ) -// ModuleName is the module name for this module -const ( - ModuleName = "crisis" - RouterKey = ModuleName -) +// RouterKey +const RouterKey = ModuleName func NewHandler(k Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) sdk.Result { diff --git a/x/crisis/handler_test.go b/x/crisis/handler_test.go index acc920e4a1ea..9632ebc52d7c 100644 --- a/x/crisis/handler_test.go +++ b/x/crisis/handler_test.go @@ -27,7 +27,7 @@ func CreateTestInput(t *testing.T) (sdk.Context, Keeper, auth.AccountKeeper, dis distr.CreateTestInputAdvanced(t, false, 10, communityTax) paramSpace := paramsKeeper.Subspace(DefaultParamspace) - crisisKeeper := NewKeeper(paramSpace, distrKeeper, bankKeeper, feeCollectionKeeper) + crisisKeeper := NewKeeper(paramSpace, 1, distrKeeper, bankKeeper, feeCollectionKeeper) constantFee := sdk.NewInt64Coin("stake", 10000000) crisisKeeper.SetConstantFee(ctx, constantFee) diff --git a/x/crisis/keeper.go b/x/crisis/keeper.go index 95c7cf09c1a0..5a25934d3b1e 100644 --- a/x/crisis/keeper.go +++ b/x/crisis/keeper.go @@ -1,14 +1,20 @@ package crisis import ( + "fmt" + "time" + + "github.com/tendermint/tendermint/libs/log" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/x/params" ) // Keeper - crisis keeper type Keeper struct { - routes []InvarRoute - paramSpace params.Subspace + routes []InvarRoute + paramSpace params.Subspace + invCheckPeriod uint distrKeeper DistrKeeper bankKeeper BankKeeper @@ -16,13 +22,14 @@ type Keeper struct { } // NewKeeper creates a new Keeper object -func NewKeeper(paramSpace params.Subspace, +func NewKeeper(paramSpace params.Subspace, invCheckPeriod uint, distrKeeper DistrKeeper, bankKeeper BankKeeper, feeCollectionKeeper FeeCollectionKeeper) Keeper { return Keeper{ routes: []InvarRoute{}, paramSpace: paramSpace.WithKeyTable(ParamKeyTable()), + invCheckPeriod: invCheckPeriod, distrKeeper: distrKeeper, bankKeeper: bankKeeper, feeCollectionKeeper: feeCollectionKeeper, @@ -49,4 +56,25 @@ func (k Keeper) Invariants() []sdk.Invariant { return invars } +// assert all invariants +func (k Keeper) AssertInvariants(ctx sdk.Context, logger log.Logger) { + + start := time.Now() + invarRoutes := k.Routes() + for _, ir := range invarRoutes { + if err := ir.Invar(ctx); err != nil { + + // TODO make "gaiacli" app name a part of context to allow for this to be variable + panic(fmt.Errorf("invariant broken: %s\n"+ + "\tCRITICAL please submit the following transaction:\n"+ + "\t\t gaiacli tx crisis invariant-broken %v %v", err, ir.ModuleName, ir.Route)) + } + } + end := time.Now() + diff := end.Sub(start) + + logger.With("module", "x/crisis").Info( + "Asserted all invariants", "duration", diff, "height", ctx.BlockHeight()) +} + // DONTCOVER diff --git a/x/crisis/module.go b/x/crisis/module.go new file mode 100644 index 000000000000..9ef88493eb40 --- /dev/null +++ b/x/crisis/module.go @@ -0,0 +1,70 @@ +package crisis + +import ( + "encoding/json" + + "github.com/tendermint/tendermint/libs/log" + + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +var _ sdk.AppModule = AppModule{} + +// name of this module +const ModuleName = "crisis" + +// app module for bank +type AppModule struct { + keeper Keeper + logger log.Logger +} + +// NewAppModule creates a new AppModule object +func NewAppModule(keeper Keeper, logger log.Logger) AppModule { + return AppModule{ + keeper: keeper, + logger: logger, + } +} + +// module name +func (AppModule) Name() string { + return ModuleName +} + +// register invariants +func (AppModule) RegisterInvariants(_ sdk.InvariantRouter) {} + +// module querier route name +func (AppModule) Route() string { + return RouterKey +} + +// module handler +func (a AppModule) NewHandler() sdk.Handler { + return NewHandler(a.keeper) +} + +// module querier route name +func (AppModule) QuerierRoute() string { return "" } + +// module querier +func (AppModule) NewQuerierHandler() sdk.Querier { return nil } + +// module init-genesis +func (a AppModule) InitGenesis(ctx sdk.Context, _ json.RawMessage) ([]abci.ValidatorUpdate, error) { + a.keeper.AssertInvariants(ctx, a.logger) + return []abci.ValidatorUpdate{}, nil +} + +// module begin-block +func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) sdk.Tags { + return sdk.EmptyTags() +} + +// module end-block +func (a AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) { + EndBlocker(ctx, a.keeper, a.logger) + return []abci.ValidatorUpdate{}, sdk.EmptyTags() +} diff --git a/x/distribution/abci_app.go b/x/distribution/abci_app.go index 0a2ef5627a90..237145c2e3f3 100644 --- a/x/distribution/abci_app.go +++ b/x/distribution/abci_app.go @@ -8,6 +8,7 @@ import ( ) // set the proposer for determining distribution during endblock +// and distribute rewards for the previous block func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper) { // determine the total power signing the block diff --git a/x/distribution/alias.go b/x/distribution/alias.go index 57038618bcc6..adc046e1a9a0 100644 --- a/x/distribution/alias.go +++ b/x/distribution/alias.go @@ -34,6 +34,7 @@ type ( ) const ( + ModuleName = types.ModuleName DefaultCodespace = types.DefaultCodespace CodeInvalidInput = types.CodeInvalidInput StoreKey = types.StoreKey diff --git a/x/distribution/keeper/invariants.go b/x/distribution/keeper/invariants.go index 907ff02644b2..a224ae1c15ce 100644 --- a/x/distribution/keeper/invariants.go +++ b/x/distribution/keeper/invariants.go @@ -8,19 +8,19 @@ import ( ) // register all distribution invariants -func RegisterInvariants(c types.CrisisKeeper, k Keeper, stk types.StakingKeeper) { - c.RegisterRoute(types.ModuleName, "nonnegative-outstanding", +func RegisterInvariants(ir sdk.InvariantRouter, k Keeper) { + ir.RegisterRoute(types.ModuleName, "nonnegative-outstanding", NonNegativeOutstandingInvariant(k)) - c.RegisterRoute(types.ModuleName, "can-withdraw", - CanWithdrawInvariant(k, stk)) - c.RegisterRoute(types.ModuleName, "reference-count", - ReferenceCountInvariant(k, stk)) + ir.RegisterRoute(types.ModuleName, "can-withdraw", + CanWithdrawInvariant(k)) + ir.RegisterRoute(types.ModuleName, "reference-count", + ReferenceCountInvariant(k)) } // AllInvariants runs all invariants of the distribution module -func AllInvariants(k Keeper, stk types.StakingKeeper) sdk.Invariant { +func AllInvariants(k Keeper) sdk.Invariant { return func(ctx sdk.Context) error { - err := CanWithdrawInvariant(k, stk)(ctx) + err := CanWithdrawInvariant(k)(ctx) if err != nil { return err } @@ -28,7 +28,7 @@ func AllInvariants(k Keeper, stk types.StakingKeeper) sdk.Invariant { if err != nil { return err } - err = ReferenceCountInvariant(k, stk)(ctx) + err = ReferenceCountInvariant(k)(ctx) if err != nil { return err } @@ -60,7 +60,7 @@ func NonNegativeOutstandingInvariant(k Keeper) sdk.Invariant { } // CanWithdrawInvariant checks that current rewards can be completely withdrawn -func CanWithdrawInvariant(k Keeper, sk types.StakingKeeper) sdk.Invariant { +func CanWithdrawInvariant(k Keeper) sdk.Invariant { return func(ctx sdk.Context) error { // cache, we don't want to write changes @@ -69,13 +69,13 @@ func CanWithdrawInvariant(k Keeper, sk types.StakingKeeper) sdk.Invariant { var remaining sdk.DecCoins valDelegationAddrs := make(map[string][]sdk.AccAddress) - for _, del := range sk.GetAllSDKDelegations(ctx) { + for _, del := range k.stakingKeeper.GetAllSDKDelegations(ctx) { valAddr := del.GetValidatorAddr().String() valDelegationAddrs[valAddr] = append(valDelegationAddrs[valAddr], del.GetDelegatorAddr()) } // iterate over all validators - sk.IterateValidators(ctx, func(_ int64, val sdk.Validator) (stop bool) { + k.stakingKeeper.IterateValidators(ctx, func(_ int64, val sdk.Validator) (stop bool) { _, _ = k.WithdrawValidatorCommission(ctx, val.GetOperator()) delegationAddrs, ok := valDelegationAddrs[val.GetOperator().String()] @@ -104,15 +104,15 @@ func CanWithdrawInvariant(k Keeper, sk types.StakingKeeper) sdk.Invariant { } // ReferenceCountInvariant checks that the number of historical rewards records is correct -func ReferenceCountInvariant(k Keeper, sk types.StakingKeeper) sdk.Invariant { +func ReferenceCountInvariant(k Keeper) sdk.Invariant { return func(ctx sdk.Context) error { valCount := uint64(0) - sk.IterateValidators(ctx, func(_ int64, val sdk.Validator) (stop bool) { + k.stakingKeeper.IterateValidators(ctx, func(_ int64, val sdk.Validator) (stop bool) { valCount++ return false }) - dels := sk.GetAllSDKDelegations(ctx) + dels := k.stakingKeeper.GetAllSDKDelegations(ctx) slashCount := uint64(0) k.IterateValidatorSlashEvents(ctx, func(_ sdk.ValAddress, _ uint64, _ types.ValidatorSlashEvent) (stop bool) { diff --git a/x/distribution/module.go b/x/distribution/module.go new file mode 100644 index 000000000000..02ee90953d90 --- /dev/null +++ b/x/distribution/module.go @@ -0,0 +1,68 @@ +package distribution + +import ( + "encoding/json" + + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +var _ sdk.AppModule = AppModule{} + +// app module +type AppModule struct { + keeper Keeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(keeper Keeper) AppModule { + return AppModule{ + keeper: keeper, + } +} + +// module name +func (AppModule) Name() string { + return ModuleName +} + +// register invariants +func (a AppModule) RegisterInvariants(ir sdk.InvariantRouter) { + RegisterInvariants(ir, a.keeper) +} + +// module message route name +func (AppModule) Route() string { + return RouterKey +} + +// module handler +func (a AppModule) NewHandler() sdk.Handler { + return NewHandler(a.keeper) +} + +// module querier route name +func (AppModule) QuerierRoute() string { + return QuerierRoute +} + +// module querier +func (a AppModule) NewQuerierHandler() sdk.Querier { + return NewQuerier(a.keeper) +} + +// module init-genesis +func (a AppModule) InitGenesis(_ sdk.Context, _ json.RawMessage) ([]abci.ValidatorUpdate, error) { + return []abci.ValidatorUpdate{}, nil +} + +// module begin-block +func (a AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) sdk.Tags { + BeginBlocker(ctx, req, a.keeper) + return sdk.EmptyTags() +} + +// module end-block +func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) { + return []abci.ValidatorUpdate{}, sdk.EmptyTags() +} diff --git a/x/distribution/types/expected_keepers.go b/x/distribution/types/expected_keepers.go index 9d2c6a4e53c4..6bf8eaa0a8c1 100644 --- a/x/distribution/types/expected_keepers.go +++ b/x/distribution/types/expected_keepers.go @@ -28,8 +28,3 @@ type FeeCollectionKeeper interface { GetCollectedFees(ctx sdk.Context) sdk.Coins ClearCollectedFees(ctx sdk.Context) } - -// expected crisis keeper -type CrisisKeeper interface { - RegisterRoute(moduleName, route string, invar sdk.Invariant) -} diff --git a/x/gov/keeper.go b/x/gov/keeper.go index f64b0fbc6cf0..9ccae0f81f22 100644 --- a/x/gov/keeper.go +++ b/x/gov/keeper.go @@ -12,9 +12,6 @@ import ( ) const ( - // ModuleKey is the name of the module - ModuleName = "gov" - // StoreKey is the store key string for gov StoreKey = ModuleName diff --git a/x/gov/module.go b/x/gov/module.go new file mode 100644 index 000000000000..59b786c9e3a4 --- /dev/null +++ b/x/gov/module.go @@ -0,0 +1,69 @@ +package gov + +import ( + "encoding/json" + + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +var _ sdk.AppModule = AppModule{} + +// name of this module +const ModuleName = "gov" + +// app module +type AppModule struct { + keeper Keeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(keeper Keeper) AppModule { + return AppModule{ + keeper: keeper, + } +} + +// module name +func (AppModule) Name() string { + return ModuleName +} + +// register invariants +func (AppModule) RegisterInvariants(_ sdk.InvariantRouter) {} + +// module message route name +func (AppModule) Route() string { + return RouterKey +} + +// module handler +func (a AppModule) NewHandler() sdk.Handler { + return NewHandler(a.keeper) +} + +// module querier route name +func (AppModule) QuerierRoute() string { + return QuerierRoute +} + +// module querier +func (a AppModule) NewQuerierHandler() sdk.Querier { + return NewQuerier(a.keeper) +} + +// module init-genesis +func (a AppModule) InitGenesis(_ sdk.Context, _ json.RawMessage) ([]abci.ValidatorUpdate, error) { + return []abci.ValidatorUpdate{}, nil +} + +// module begin-block +func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) sdk.Tags { + return sdk.EmptyTags() +} + +// module end-block +func (a AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) { + tags := EndBlocker(ctx, a.keeper) + return []abci.ValidatorUpdate{}, tags +} diff --git a/x/mint/abci_app.go b/x/mint/abci_app.go index 5016a464d18a..24eeeedfbd17 100644 --- a/x/mint/abci_app.go +++ b/x/mint/abci_app.go @@ -4,7 +4,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// Inflate every block, update inflation parameters once per hour +// mint new tokens for the previous block func BeginBlocker(ctx sdk.Context, k Keeper) { // fetch stored minter & params diff --git a/x/mint/keeper.go b/x/mint/keeper.go index 42a9f19fbaa5..8c7374825ec5 100644 --- a/x/mint/keeper.go +++ b/x/mint/keeper.go @@ -7,14 +7,11 @@ import ( ) const ( - // ModuleName is the name of the module - ModuleName = "minting" - // default paramspace for params keeper - DefaultParamspace = "mint" + DefaultParamspace = ModuleName // StoreKey is the default store key for mint - StoreKey = "mint" + StoreKey = ModuleName // QuerierRoute is the querier route for the minting store. QuerierRoute = StoreKey diff --git a/x/mint/module.go b/x/mint/module.go new file mode 100644 index 000000000000..e26d7638f132 --- /dev/null +++ b/x/mint/module.go @@ -0,0 +1,65 @@ +package mint + +import ( + "encoding/json" + + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +var _ sdk.AppModule = AppModule{} + +// name of this module +const ModuleName = "mint" + +// app module +type AppModule struct { + keeper Keeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(keeper Keeper) AppModule { + return AppModule{ + keeper: keeper, + } +} + +// module name +func (AppModule) Name() string { + return ModuleName +} + +// register invariants +func (a AppModule) RegisterInvariants(_ sdk.InvariantRouter) {} + +// module message route name +func (AppModule) Route() string { return "" } + +// module handler +func (a AppModule) NewHandler() sdk.Handler { return nil } + +// module querier route name +func (AppModule) QuerierRoute() string { + return QuerierRoute +} + +// module querier +func (a AppModule) NewQuerierHandler() sdk.Querier { + return NewQuerier(a.keeper) +} + +// module init-genesis +func (a AppModule) InitGenesis(_ sdk.Context, _ json.RawMessage) ([]abci.ValidatorUpdate, error) { + return []abci.ValidatorUpdate{}, nil +} + +// module begin-block +func (a AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) sdk.Tags { + BeginBlocker(ctx, a.keeper) + return sdk.EmptyTags() +} + +// module end-block +func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) { + return []abci.ValidatorUpdate{}, sdk.EmptyTags() +} diff --git a/x/slashing/codec.go b/x/slashing/codec.go index ebe08428c669..f48ce6fc6afa 100644 --- a/x/slashing/codec.go +++ b/x/slashing/codec.go @@ -9,4 +9,11 @@ func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(MsgUnjail{}, "cosmos-sdk/MsgUnjail", nil) } -var cdcEmpty = codec.New() +var moduleCdc = codec.New() + +func init() { + cdc := codec.New() + RegisterCodec(cdc) + codec.RegisterCrypto(cdc) + moduleCdc = cdc.Seal() +} diff --git a/x/slashing/keys.go b/x/slashing/keys.go index ce3da1c7e601..009a31b4aa48 100644 --- a/x/slashing/keys.go +++ b/x/slashing/keys.go @@ -7,9 +7,6 @@ import ( ) const ( - // ModuleName is the name of the module - ModuleName = "slashing" - // StoreKey is the store key string for slashing StoreKey = ModuleName diff --git a/x/slashing/module.go b/x/slashing/module.go new file mode 100644 index 000000000000..1b5ba7eed39c --- /dev/null +++ b/x/slashing/module.go @@ -0,0 +1,68 @@ +package slashing + +import ( + "encoding/json" + + sdk "github.com/cosmos/cosmos-sdk/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +var _ sdk.AppModule = AppModule{} + +// name of this module +const ModuleName = "slashing" + +// app module +type AppModule struct { + keeper Keeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(keeper Keeper) AppModule { + return AppModule{ + keeper: keeper, + } +} + +// module name +func (AppModule) Name() string { + return ModuleName +} + +// register invariants +func (a AppModule) RegisterInvariants(_ sdk.InvariantRouter) {} + +// module message route name +func (AppModule) Route() string { + return RouterKey +} + +// module handler +func (a AppModule) NewHandler() sdk.Handler { + return NewHandler(a.keeper) +} + +// module querier route name +func (AppModule) QuerierRoute() string { + return QuerierRoute +} + +// module querier +func (a AppModule) NewQuerierHandler() sdk.Querier { + return NewQuerier(a.keeper) +} + +// module init-genesis +func (a AppModule) InitGenesis(_ sdk.Context, _ json.RawMessage) ([]abci.ValidatorUpdate, error) { + return []abci.ValidatorUpdate{}, nil +} + +// module begin-block +func (a AppModule) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) sdk.Tags { + return BeginBlocker(ctx, req, a.keeper) +} + +// module end-block +func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) { + return []abci.ValidatorUpdate{}, sdk.EmptyTags() +} diff --git a/x/slashing/msg.go b/x/slashing/msg.go index a108142f77ee..5e49969f8732 100644 --- a/x/slashing/msg.go +++ b/x/slashing/msg.go @@ -1,12 +1,9 @@ package slashing import ( - "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" ) -var cdc = codec.New() - // verify interface at compile time var _ sdk.Msg = &MsgUnjail{} @@ -30,7 +27,7 @@ func (msg MsgUnjail) GetSigners() []sdk.AccAddress { // get the bytes for the message signer to sign on func (msg MsgUnjail) GetSignBytes() []byte { - bz := cdc.MustMarshalJSON(msg) + bz := moduleCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } diff --git a/x/slashing/querier.go b/x/slashing/querier.go index a0faaeb509f7..3acad87e5c6f 100644 --- a/x/slashing/querier.go +++ b/x/slashing/querier.go @@ -13,21 +13,21 @@ const ( ) // NewQuerier creates a new querier for slashing clients. -func NewQuerier(k Keeper, cdc *codec.Codec) sdk.Querier { +func NewQuerier(k Keeper) sdk.Querier { return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) { switch path[0] { case QueryParameters: - return queryParams(ctx, cdc, k) + return queryParams(ctx, k) default: return nil, sdk.ErrUnknownRequest("unknown staking query endpoint") } } } -func queryParams(ctx sdk.Context, cdc *codec.Codec, k Keeper) ([]byte, sdk.Error) { +func queryParams(ctx sdk.Context, k Keeper) ([]byte, sdk.Error) { params := k.GetParams(ctx) - res, err := codec.MarshalJSONIndent(cdc, params) + res, err := codec.MarshalJSONIndent(moduleCdc, params) if err != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to marshal JSON", err.Error())) } diff --git a/x/slashing/querier_test.go b/x/slashing/querier_test.go index bc1ba804b1eb..a4941e0a9efe 100644 --- a/x/slashing/querier_test.go +++ b/x/slashing/querier_test.go @@ -10,9 +10,8 @@ import ( ) func TestNewQuerier(t *testing.T) { - cdc := codec.New() ctx, _, _, _, keeper := createTestInput(t, keeperTestParams()) - querier := NewQuerier(keeper, cdc) + querier := NewQuerier(keeper) query := abci.RequestQuery{ Path: "", @@ -29,7 +28,7 @@ func TestQueryParams(t *testing.T) { var params Params - res, errRes := queryParams(ctx, cdc, keeper) + res, errRes := queryParams(ctx, keeper) require.NoError(t, errRes) err := cdc.UnmarshalJSON(res, ¶ms) diff --git a/x/staking/alias.go b/x/staking/alias.go index 3c8e19fd9f30..86a6d8a9c25c 100644 --- a/x/staking/alias.go +++ b/x/staking/alias.go @@ -25,6 +25,7 @@ type ( Redelegations = types.Redelegations Params = types.Params Pool = types.Pool + MultiStakingHooks = types.MultiStakingHooks MsgCreateValidator = types.MsgCreateValidator MsgEditValidator = types.MsgEditValidator MsgDelegate = types.MsgDelegate @@ -90,6 +91,7 @@ var ( NewGenesisState = types.NewGenesisState DefaultGenesisState = types.DefaultGenesisState RegisterCodec = types.RegisterCodec + NewMultiStakingHooks = types.NewMultiStakingHooks NewMsgCreateValidator = types.NewMsgCreateValidator NewMsgEditValidator = types.NewMsgEditValidator @@ -122,6 +124,7 @@ const ( ) const ( + ModuleName = types.ModuleName StoreKey = types.StoreKey TStoreKey = types.TStoreKey QuerierRoute = types.QuerierRoute diff --git a/x/staking/genesis.go b/x/staking/genesis.go index 7c10584b5e1e..5c7aa64f6a97 100644 --- a/x/staking/genesis.go +++ b/x/staking/genesis.go @@ -146,6 +146,8 @@ func WriteValidators(ctx sdk.Context, keeper Keeper) (vals []tmtypes.GenesisVali // ValidateGenesis validates the provided staking genesis state to ensure the // expected invariants holds. (i.e. params in correct bounds, no duplicate validators) +// TODO: No validators are both bonded and jailed (#2088) +// TODO: Error if there is a duplicate validator (#1708) func ValidateGenesis(data types.GenesisState) error { err := validateGenesisStateValidators(data.Validators) if err != nil { diff --git a/x/staking/handler.go b/x/staking/handler.go index bfff581f05d2..0012023e228b 100644 --- a/x/staking/handler.go +++ b/x/staking/handler.go @@ -249,7 +249,7 @@ func handleMsgUndelegate(ctx sdk.Context, msg types.MsgUndelegate, k keeper.Keep return err.Result() } - finishTime := types.MsgCdc.MustMarshalBinaryLengthPrefixed(completionTime) + finishTime := types.ModuleCdc.MustMarshalBinaryLengthPrefixed(completionTime) resTags := sdk.NewTags( tags.Category, tags.TxCategory, tags.Sender, msg.DelegatorAddress.String(), @@ -275,7 +275,7 @@ func handleMsgBeginRedelegate(ctx sdk.Context, msg types.MsgBeginRedelegate, k k return err.Result() } - finishTime := types.MsgCdc.MustMarshalBinaryLengthPrefixed(completionTime) + finishTime := types.ModuleCdc.MustMarshalBinaryLengthPrefixed(completionTime) resTags := sdk.NewTags( tags.Category, tags.TxCategory, tags.Sender, msg.DelegatorAddress.String(), diff --git a/x/staking/handler_test.go b/x/staking/handler_test.go index bdf0ab4699c3..6f6c43b3d3ba 100644 --- a/x/staking/handler_test.go +++ b/x/staking/handler_test.go @@ -101,7 +101,7 @@ func TestValidatorByPowerIndex(t *testing.T) { require.True(t, got.IsOK(), "expected msg to be ok, got %v", got) var finishTime time.Time - types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -228,7 +228,7 @@ func TestLegacyValidatorDelegations(t *testing.T) { require.True(t, got.IsOK(), "expected begin unbonding validator msg to be ok, got %v", got) var finishTime time.Time - types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -451,7 +451,7 @@ func TestIncrementsMsgUnbond(t *testing.T) { got := handleMsgUndelegate(ctx, msgUndelegate, keeper) require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) var finishTime time.Time - types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -557,7 +557,7 @@ func TestMultipleMsgCreateValidator(t *testing.T) { var finishTime time.Time // Jump to finishTime for unbonding period and remove from unbonding queue - types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -606,7 +606,7 @@ func TestMultipleMsgDelegate(t *testing.T) { require.True(t, got.IsOK(), "expected msg %d to be ok, got %v", i, got) var finishTime time.Time - types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -639,7 +639,7 @@ func TestJailValidator(t *testing.T) { require.True(t, got.IsOK(), "expected no error: %v", got) var finishTime time.Time - types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -653,7 +653,7 @@ func TestJailValidator(t *testing.T) { got = handleMsgUndelegate(ctx, msgUndelegateDelegator, keeper) require.True(t, got.IsOK(), "expected no error") - types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -693,7 +693,7 @@ func TestValidatorQueue(t *testing.T) { require.True(t, got.IsOK(), "expected no error: %v", got) var finishTime time.Time - types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime) EndBlocker(ctx, keeper) @@ -789,7 +789,7 @@ func TestUnbondingFromUnbondingValidator(t *testing.T) { // change the ctx to Block Time one second before the validator would have unbonded var finishTime time.Time - types.MsgCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) + types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(got.Data, &finishTime) ctx = ctx.WithBlockTime(finishTime.Add(time.Second * -1)) // unbond the delegator from the validator diff --git a/x/staking/keeper/invariants.go b/x/staking/keeper/invariants.go index f9a495a4f6eb..e53e01f95465 100644 --- a/x/staking/keeper/invariants.go +++ b/x/staking/keeper/invariants.go @@ -10,16 +10,16 @@ import ( ) // register all staking invariants -func RegisterInvariants(c types.CrisisKeeper, k Keeper, f types.FeeCollectionKeeper, +func RegisterInvariants(ir sdk.InvariantRouter, k Keeper, f types.FeeCollectionKeeper, d types.DistributionKeeper, am auth.AccountKeeper) { - c.RegisterRoute(types.ModuleName, "supply", + ir.RegisterRoute(types.ModuleName, "supply", SupplyInvariants(k, f, d, am)) - c.RegisterRoute(types.ModuleName, "nonnegative-power", + ir.RegisterRoute(types.ModuleName, "nonnegative-power", NonNegativePowerInvariant(k)) - c.RegisterRoute(types.ModuleName, "positive-delegation", + ir.RegisterRoute(types.ModuleName, "positive-delegation", PositiveDelegationInvariant(k)) - c.RegisterRoute(types.ModuleName, "delegator-shares", + ir.RegisterRoute(types.ModuleName, "delegator-shares", DelegatorSharesInvariant(k)) } diff --git a/x/staking/module.go b/x/staking/module.go new file mode 100644 index 000000000000..3a867d38531a --- /dev/null +++ b/x/staking/module.go @@ -0,0 +1,77 @@ +package staking + +import ( + "encoding/json" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/auth" + "github.com/cosmos/cosmos-sdk/x/staking/types" + abci "github.com/tendermint/tendermint/abci/types" +) + +var _ sdk.AppModule = AppModule{} + +// app module +type AppModule struct { + keeper Keeper + fcKeeper FeeCollectionKeeper + distrKeeper DistributionKeeper + accKeeper auth.AccountKeeper +} + +// NewAppModule creates a new AppModule object +func NewAppModule(keeper Keeper, fcKeeper types.FeeCollectionKeeper, + distrKeeper types.DistributionKeeper, accKeeper auth.AccountKeeper) AppModule { + + return AppModule{ + keeper: keeper, + fcKeeper: fcKeeper, + distrKeeper: distrKeeper, + accKeeper: accKeeper, + } +} + +// module name +func (AppModule) Name() string { + return ModuleName +} + +// register invariants +func (a AppModule) RegisterInvariants(ir sdk.InvariantRouter) { + RegisterInvariants(ir, a.keeper, a.fcKeeper, a.distrKeeper, a.accKeeper) +} + +// module message route name +func (AppModule) Route() string { + return RouterKey +} + +// module handler +func (a AppModule) NewHandler() sdk.Handler { + return NewHandler(a.keeper) +} + +// module querier route name +func (AppModule) QuerierRoute() string { + return QuerierRoute +} + +// module querier +func (a AppModule) NewQuerierHandler() sdk.Querier { + return NewQuerier(a.keeper) +} + +// module init-genesis +func (a AppModule) InitGenesis(_ sdk.Context, _ json.RawMessage) ([]abci.ValidatorUpdate, error) { + return []abci.ValidatorUpdate{}, nil +} + +// module begin-block +func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) sdk.Tags { + return sdk.EmptyTags() +} + +// module end-block +func (a AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) ([]abci.ValidatorUpdate, sdk.Tags) { + return EndBlocker(ctx, a.keeper) +} diff --git a/x/staking/querier/querier.go b/x/staking/querier/querier.go index 8694a35b9ca2..611575cda038 100644 --- a/x/staking/querier/querier.go +++ b/x/staking/querier/querier.go @@ -32,35 +32,35 @@ const ( ) // creates a querier for staking REST endpoints -func NewQuerier(k keep.Keeper, cdc *codec.Codec) sdk.Querier { +func NewQuerier(k keep.Keeper) sdk.Querier { return func(ctx sdk.Context, path []string, req abci.RequestQuery) (res []byte, err sdk.Error) { switch path[0] { case QueryValidators: - return queryValidators(ctx, cdc, req, k) + return queryValidators(ctx, req, k) case QueryValidator: - return queryValidator(ctx, cdc, req, k) + return queryValidator(ctx, req, k) case QueryValidatorDelegations: - return queryValidatorDelegations(ctx, cdc, req, k) + return queryValidatorDelegations(ctx, req, k) case QueryValidatorUnbondingDelegations: - return queryValidatorUnbondingDelegations(ctx, cdc, req, k) + return queryValidatorUnbondingDelegations(ctx, req, k) case QueryDelegation: - return queryDelegation(ctx, cdc, req, k) + return queryDelegation(ctx, req, k) case QueryUnbondingDelegation: - return queryUnbondingDelegation(ctx, cdc, req, k) + return queryUnbondingDelegation(ctx, req, k) case QueryDelegatorDelegations: - return queryDelegatorDelegations(ctx, cdc, req, k) + return queryDelegatorDelegations(ctx, req, k) case QueryDelegatorUnbondingDelegations: - return queryDelegatorUnbondingDelegations(ctx, cdc, req, k) + return queryDelegatorUnbondingDelegations(ctx, req, k) case QueryRedelegations: - return queryRedelegations(ctx, cdc, req, k) + return queryRedelegations(ctx, req, k) case QueryDelegatorValidators: - return queryDelegatorValidators(ctx, cdc, req, k) + return queryDelegatorValidators(ctx, req, k) case QueryDelegatorValidator: - return queryDelegatorValidator(ctx, cdc, req, k) + return queryDelegatorValidator(ctx, req, k) case QueryPool: - return queryPool(ctx, cdc, k) + return queryPool(ctx, k) case QueryParameters: - return queryParameters(ctx, cdc, k) + return queryParameters(ctx, k) default: return nil, sdk.ErrUnknownRequest("unknown staking query endpoint") } @@ -129,10 +129,10 @@ func NewQueryRedelegationParams(delegatorAddr sdk.AccAddress, srcValidatorAddr s } } -func queryValidators(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) ([]byte, sdk.Error) { +func queryValidators(ctx sdk.Context, req abci.RequestQuery, k keep.Keeper) ([]byte, sdk.Error) { var params QueryValidatorsParams - err := cdc.UnmarshalJSON(req.Data, ¶ms) + err := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if err != nil { return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } @@ -165,7 +165,7 @@ func queryValidators(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k filteredVals = filteredVals[start:end] } - res, err := codec.MarshalJSONIndent(cdc, filteredVals) + res, err := codec.MarshalJSONIndent(types.ModuleCdc, filteredVals) if err != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("failed to JSON marshal result: %s", err.Error())) } @@ -173,10 +173,10 @@ func queryValidators(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k return res, nil } -func queryValidator(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { +func queryValidator(ctx sdk.Context, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { var params QueryValidatorParams - errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + errRes := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if errRes != nil { return []byte{}, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } @@ -186,104 +186,104 @@ func queryValidator(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k return []byte{}, types.ErrNoValidatorFound(types.DefaultCodespace) } - res, errRes = codec.MarshalJSONIndent(cdc, validator) + res, errRes = codec.MarshalJSONIndent(types.ModuleCdc, validator) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } return res, nil } -func queryValidatorDelegations(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { +func queryValidatorDelegations(ctx sdk.Context, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { var params QueryValidatorParams - errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + errRes := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if errRes != nil { return []byte{}, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } delegations := k.GetValidatorDelegations(ctx, params.ValidatorAddr) - res, errRes = codec.MarshalJSONIndent(cdc, delegations) + res, errRes = codec.MarshalJSONIndent(types.ModuleCdc, delegations) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } return res, nil } -func queryValidatorUnbondingDelegations(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { +func queryValidatorUnbondingDelegations(ctx sdk.Context, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { var params QueryValidatorParams - errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + errRes := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if errRes != nil { return []byte{}, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } unbonds := k.GetUnbondingDelegationsFromValidator(ctx, params.ValidatorAddr) - res, errRes = codec.MarshalJSONIndent(cdc, unbonds) + res, errRes = codec.MarshalJSONIndent(types.ModuleCdc, unbonds) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } return res, nil } -func queryDelegatorDelegations(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { +func queryDelegatorDelegations(ctx sdk.Context, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { var params QueryDelegatorParams - errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + errRes := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if errRes != nil { return []byte{}, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } delegations := k.GetAllDelegatorDelegations(ctx, params.DelegatorAddr) - res, errRes = codec.MarshalJSONIndent(cdc, delegations) + res, errRes = codec.MarshalJSONIndent(types.ModuleCdc, delegations) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } return res, nil } -func queryDelegatorUnbondingDelegations(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { +func queryDelegatorUnbondingDelegations(ctx sdk.Context, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { var params QueryDelegatorParams - errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + errRes := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if errRes != nil { return []byte{}, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } unbondingDelegations := k.GetAllUnbondingDelegations(ctx, params.DelegatorAddr) - res, errRes = codec.MarshalJSONIndent(cdc, unbondingDelegations) + res, errRes = codec.MarshalJSONIndent(types.ModuleCdc, unbondingDelegations) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } return res, nil } -func queryDelegatorValidators(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { +func queryDelegatorValidators(ctx sdk.Context, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { var params QueryDelegatorParams stakingParams := k.GetParams(ctx) - errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + errRes := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if errRes != nil { return []byte{}, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } validators := k.GetDelegatorValidators(ctx, params.DelegatorAddr, stakingParams.MaxValidators) - res, errRes = codec.MarshalJSONIndent(cdc, validators) + res, errRes = codec.MarshalJSONIndent(types.ModuleCdc, validators) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } return res, nil } -func queryDelegatorValidator(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { +func queryDelegatorValidator(ctx sdk.Context, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { var params QueryBondsParams - errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + errRes := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if errRes != nil { return []byte{}, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } @@ -293,17 +293,17 @@ func queryDelegatorValidator(ctx sdk.Context, cdc *codec.Codec, req abci.Request return } - res, errRes = codec.MarshalJSONIndent(cdc, validator) + res, errRes = codec.MarshalJSONIndent(types.ModuleCdc, validator) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } return res, nil } -func queryDelegation(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { +func queryDelegation(ctx sdk.Context, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { var params QueryBondsParams - errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + errRes := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if errRes != nil { return []byte{}, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } @@ -313,17 +313,17 @@ func queryDelegation(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k return []byte{}, types.ErrNoDelegation(types.DefaultCodespace) } - res, errRes = codec.MarshalJSONIndent(cdc, delegation) + res, errRes = codec.MarshalJSONIndent(types.ModuleCdc, delegation) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } return res, nil } -func queryUnbondingDelegation(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { +func queryUnbondingDelegation(ctx sdk.Context, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { var params QueryBondsParams - errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + errRes := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if errRes != nil { return []byte{}, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err)) } @@ -333,17 +333,17 @@ func queryUnbondingDelegation(ctx sdk.Context, cdc *codec.Codec, req abci.Reques return []byte{}, types.ErrNoUnbondingDelegation(types.DefaultCodespace) } - res, errRes = codec.MarshalJSONIndent(cdc, unbond) + res, errRes = codec.MarshalJSONIndent(types.ModuleCdc, unbond) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } return res, nil } -func queryRedelegations(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { +func queryRedelegations(ctx sdk.Context, req abci.RequestQuery, k keep.Keeper) (res []byte, err sdk.Error) { var params QueryRedelegationParams - errRes := cdc.UnmarshalJSON(req.Data, ¶ms) + errRes := types.ModuleCdc.UnmarshalJSON(req.Data, ¶ms) if errRes != nil { return []byte{}, sdk.ErrUnknownRequest(string(req.Data)) } @@ -362,27 +362,27 @@ func queryRedelegations(ctx sdk.Context, cdc *codec.Codec, req abci.RequestQuery redels = k.GetAllRedelegations(ctx, params.DelegatorAddr, params.SrcValidatorAddr, params.DstValidatorAddr) } - res, errRes = codec.MarshalJSONIndent(cdc, redels) + res, errRes = codec.MarshalJSONIndent(types.ModuleCdc, redels) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } return res, nil } -func queryPool(ctx sdk.Context, cdc *codec.Codec, k keep.Keeper) (res []byte, err sdk.Error) { +func queryPool(ctx sdk.Context, k keep.Keeper) (res []byte, err sdk.Error) { pool := k.GetPool(ctx) - res, errRes := codec.MarshalJSONIndent(cdc, pool) + res, errRes := codec.MarshalJSONIndent(types.ModuleCdc, pool) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } return res, nil } -func queryParameters(ctx sdk.Context, cdc *codec.Codec, k keep.Keeper) (res []byte, err sdk.Error) { +func queryParameters(ctx sdk.Context, k keep.Keeper) (res []byte, err sdk.Error) { params := k.GetParams(ctx) - res, errRes := codec.MarshalJSONIndent(cdc, params) + res, errRes := codec.MarshalJSONIndent(types.ModuleCdc, params) if errRes != nil { return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", errRes.Error())) } diff --git a/x/staking/querier/querier_test.go b/x/staking/querier/querier_test.go index f83c950706e9..2ab85496f7d4 100644 --- a/x/staking/querier/querier_test.go +++ b/x/staking/querier/querier_test.go @@ -39,7 +39,7 @@ func TestNewQuerier(t *testing.T) { Data: []byte{}, } - querier := NewQuerier(keeper, cdc) + querier := NewQuerier(keeper) bz, err := querier(ctx, []string{"other"}, query) require.NotNil(t, err) @@ -95,7 +95,7 @@ func TestQueryParametersPool(t *testing.T) { cdc := codec.New() ctx, _, keeper := keep.CreateTestInput(t, false, 1000) - res, err := queryParameters(ctx, cdc, keeper) + res, err := queryParameters(ctx, keeper) require.Nil(t, err) var params types.Params @@ -103,7 +103,7 @@ func TestQueryParametersPool(t *testing.T) { require.Nil(t, errRes) require.Equal(t, keeper.GetParams(ctx), params) - res, err = queryPool(ctx, cdc, keeper) + res, err = queryPool(ctx, keeper) require.Nil(t, err) var pool types.Pool @@ -138,20 +138,20 @@ func TestQueryValidators(t *testing.T) { for i, s := range status { queryValsParams := NewQueryValidatorsParams(1, int(params.MaxValidators), s.String()) - bz, errRes := cdc.MarshalJSON(queryValsParams) - require.Nil(t, errRes) + bz, err := cdc.MarshalJSON(queryValsParams) + require.Nil(t, err) req := abci.RequestQuery{ Path: fmt.Sprintf("/custom/%s/%s", types.QuerierRoute, QueryValidators), Data: bz, } - res, err := queryValidators(ctx, cdc, req, keeper) + res, err := queryValidators(ctx, req, keeper) require.Nil(t, err) var validatorsResp []types.Validator - errRes = cdc.UnmarshalJSON(res, &validatorsResp) - require.Nil(t, errRes) + err = cdc.UnmarshalJSON(res, &validatorsResp) + require.Nil(t, err) require.Equal(t, 1, len(validatorsResp)) require.ElementsMatch(t, validators[i].OperatorAddress, validatorsResp[0].OperatorAddress) @@ -160,19 +160,19 @@ func TestQueryValidators(t *testing.T) { // Query each validator queryParams := NewQueryValidatorParams(addrVal1) - bz, errRes := cdc.MarshalJSON(queryParams) - require.Nil(t, errRes) + bz, err := cdc.MarshalJSON(queryParams) + require.Nil(t, err) query := abci.RequestQuery{ Path: "/custom/staking/validator", Data: bz, } - res, err := queryValidator(ctx, cdc, query, keeper) + res, err := queryValidator(ctx, query, keeper) require.Nil(t, err) var validator types.Validator - errRes = cdc.UnmarshalJSON(res, &validator) - require.Nil(t, errRes) + err = cdc.UnmarshalJSON(res, &validator) + require.Nil(t, err) require.Equal(t, queriedValidators[0], validator) } @@ -209,7 +209,7 @@ func TestQueryDelegation(t *testing.T) { delValidators := keeper.GetDelegatorValidators(ctx, addrAcc2, params.MaxValidators) - res, err := queryDelegatorValidators(ctx, cdc, query, keeper) + res, err := queryDelegatorValidators(ctx, query, keeper) require.Nil(t, err) var validatorsResp []types.Validator @@ -222,7 +222,7 @@ func TestQueryDelegation(t *testing.T) { // error unknown request query.Data = bz[:len(bz)-1] - _, err = queryDelegatorValidators(ctx, cdc, query, keeper) + _, err = queryDelegatorValidators(ctx, query, keeper) require.NotNil(t, err) // Query bonded validator @@ -235,7 +235,7 @@ func TestQueryDelegation(t *testing.T) { Data: bz, } - res, err = queryDelegatorValidator(ctx, cdc, query, keeper) + res, err = queryDelegatorValidator(ctx, query, keeper) require.Nil(t, err) var validator types.Validator @@ -247,7 +247,7 @@ func TestQueryDelegation(t *testing.T) { // error unknown request query.Data = bz[:len(bz)-1] - _, err = queryDelegatorValidator(ctx, cdc, query, keeper) + _, err = queryDelegatorValidator(ctx, query, keeper) require.NotNil(t, err) // Query delegation @@ -260,7 +260,7 @@ func TestQueryDelegation(t *testing.T) { delegation, found := keeper.GetDelegation(ctx, addrAcc2, addrVal1) require.True(t, found) - res, err = queryDelegation(ctx, cdc, query, keeper) + res, err = queryDelegation(ctx, query, keeper) require.Nil(t, err) var delegationRes types.Delegation @@ -276,7 +276,7 @@ func TestQueryDelegation(t *testing.T) { Data: bz, } - res, err = queryDelegatorDelegations(ctx, cdc, query, keeper) + res, err = queryDelegatorDelegations(ctx, query, keeper) require.Nil(t, err) var delegatorDelegations []types.Delegation @@ -288,7 +288,7 @@ func TestQueryDelegation(t *testing.T) { // error unknown request query.Data = bz[:len(bz)-1] - _, err = queryDelegation(ctx, cdc, query, keeper) + _, err = queryDelegation(ctx, query, keeper) require.NotNil(t, err) // Query validator delegations @@ -301,7 +301,7 @@ func TestQueryDelegation(t *testing.T) { Data: bz, } - res, err = queryValidatorDelegations(ctx, cdc, query, keeper) + res, err = queryValidatorDelegations(ctx, query, keeper) require.Nil(t, err) var delegationsRes []types.Delegation @@ -327,7 +327,7 @@ func TestQueryDelegation(t *testing.T) { unbond, found := keeper.GetUnbondingDelegation(ctx, addrAcc2, addrVal1) require.True(t, found) - res, err = queryUnbondingDelegation(ctx, cdc, query, keeper) + res, err = queryUnbondingDelegation(ctx, query, keeper) require.Nil(t, err) var unbondRes types.UnbondingDelegation @@ -339,7 +339,7 @@ func TestQueryDelegation(t *testing.T) { // error unknown request query.Data = bz[:len(bz)-1] - _, err = queryUnbondingDelegation(ctx, cdc, query, keeper) + _, err = queryUnbondingDelegation(ctx, query, keeper) require.NotNil(t, err) // Query Delegator Delegations @@ -349,7 +349,7 @@ func TestQueryDelegation(t *testing.T) { Data: bz, } - res, err = queryDelegatorUnbondingDelegations(ctx, cdc, query, keeper) + res, err = queryDelegatorUnbondingDelegations(ctx, query, keeper) require.Nil(t, err) var delegatorUbds []types.UnbondingDelegation @@ -360,7 +360,7 @@ func TestQueryDelegation(t *testing.T) { // error unknown request query.Data = bz[:len(bz)-1] - _, err = queryDelegatorUnbondingDelegations(ctx, cdc, query, keeper) + _, err = queryDelegatorUnbondingDelegations(ctx, query, keeper) require.NotNil(t, err) // Query redelegation @@ -379,7 +379,7 @@ func TestQueryDelegation(t *testing.T) { Data: bz, } - res, err = queryRedelegations(ctx, cdc, query, keeper) + res, err = queryRedelegations(ctx, query, keeper) require.Nil(t, err) var redelRes []types.Redelegation @@ -420,7 +420,7 @@ func TestQueryRedelegations(t *testing.T) { Data: bz, } - res, err := queryRedelegations(ctx, cdc, query, keeper) + res, err := queryRedelegations(ctx, query, keeper) require.Nil(t, err) var redsRes []types.Redelegation @@ -439,7 +439,7 @@ func TestQueryRedelegations(t *testing.T) { Data: bz, } - res, err = queryRedelegations(ctx, cdc, query, keeper) + res, err = queryRedelegations(ctx, query, keeper) require.Nil(t, err) errRes = cdc.UnmarshalJSON(res, &redsRes) diff --git a/x/staking/types/codec.go b/x/staking/types/codec.go index 9b43705f8f49..d4f3ad594aff 100644 --- a/x/staking/types/codec.go +++ b/x/staking/types/codec.go @@ -13,12 +13,12 @@ func RegisterCodec(cdc *codec.Codec) { cdc.RegisterConcrete(MsgBeginRedelegate{}, "cosmos-sdk/MsgBeginRedelegate", nil) } -// generic sealed codec to be used throughout sdk -var MsgCdc *codec.Codec +// generic sealed codec to be used throughout this module +var ModuleCdc *codec.Codec func init() { cdc := codec.New() RegisterCodec(cdc) codec.RegisterCrypto(cdc) - MsgCdc = cdc.Seal() + ModuleCdc = cdc.Seal() } diff --git a/x/staking/types/delegation.go b/x/staking/types/delegation.go index 2d8647ba8ec9..6d2563287dcc 100644 --- a/x/staking/types/delegation.go +++ b/x/staking/types/delegation.go @@ -183,8 +183,8 @@ func UnmarshalUBD(cdc *codec.Codec, value []byte) (ubd UnbondingDelegation, err // nolint // inefficient but only used in testing func (d UnbondingDelegation) Equal(d2 UnbondingDelegation) bool { - bz1 := MsgCdc.MustMarshalBinaryLengthPrefixed(&d) - bz2 := MsgCdc.MustMarshalBinaryLengthPrefixed(&d2) + bz1 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&d) + bz2 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&d2) return bytes.Equal(bz1, bz2) } @@ -304,8 +304,8 @@ func UnmarshalRED(cdc *codec.Codec, value []byte) (red Redelegation, err error) // nolint // inefficient but only used in tests func (d Redelegation) Equal(d2 Redelegation) bool { - bz1 := MsgCdc.MustMarshalBinaryLengthPrefixed(&d) - bz2 := MsgCdc.MustMarshalBinaryLengthPrefixed(&d2) + bz1 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&d) + bz2 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&d2) return bytes.Equal(bz1, bz2) } diff --git a/x/staking/types/expected_keepers.go b/x/staking/types/expected_keepers.go index 2a2aff06046b..54c9bad62287 100644 --- a/x/staking/types/expected_keepers.go +++ b/x/staking/types/expected_keepers.go @@ -18,8 +18,3 @@ type BankKeeper interface { DelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Tags, sdk.Error) UndelegateCoins(ctx sdk.Context, addr sdk.AccAddress, amt sdk.Coins) (sdk.Tags, sdk.Error) } - -// expected crisis keeper -type CrisisKeeper interface { - RegisterRoute(moduleName, route string, invar sdk.Invariant) -} diff --git a/x/staking/types/hooks.go b/x/staking/types/hooks.go new file mode 100644 index 000000000000..83df7bc5af2d --- /dev/null +++ b/x/staking/types/hooks.go @@ -0,0 +1,64 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// combine multiple staking hooks, all hook functions are run in array sequence +type MultiStakingHooks []sdk.StakingHooks + +func NewMultiStakingHooks(hooks ...sdk.StakingHooks) MultiStakingHooks { + return hooks +} + +// nolint +func (h MultiStakingHooks) AfterValidatorCreated(ctx sdk.Context, valAddr sdk.ValAddress) { + for i := range h { + h[i].AfterValidatorCreated(ctx, valAddr) + } +} +func (h MultiStakingHooks) BeforeValidatorModified(ctx sdk.Context, valAddr sdk.ValAddress) { + for i := range h { + h[i].BeforeValidatorModified(ctx, valAddr) + } +} +func (h MultiStakingHooks) AfterValidatorRemoved(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) { + for i := range h { + h[i].AfterValidatorRemoved(ctx, consAddr, valAddr) + } +} +func (h MultiStakingHooks) AfterValidatorBonded(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) { + for i := range h { + h[i].AfterValidatorBonded(ctx, consAddr, valAddr) + } +} +func (h MultiStakingHooks) AfterValidatorBeginUnbonding(ctx sdk.Context, consAddr sdk.ConsAddress, valAddr sdk.ValAddress) { + for i := range h { + h[i].AfterValidatorBeginUnbonding(ctx, consAddr, valAddr) + } +} +func (h MultiStakingHooks) BeforeDelegationCreated(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + for i := range h { + h[i].BeforeDelegationCreated(ctx, delAddr, valAddr) + } +} +func (h MultiStakingHooks) BeforeDelegationSharesModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + for i := range h { + h[i].BeforeDelegationSharesModified(ctx, delAddr, valAddr) + } +} +func (h MultiStakingHooks) BeforeDelegationRemoved(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + for i := range h { + h[i].BeforeDelegationRemoved(ctx, delAddr, valAddr) + } +} +func (h MultiStakingHooks) AfterDelegationModified(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) { + for i := range h { + h[i].AfterDelegationModified(ctx, delAddr, valAddr) + } +} +func (h MultiStakingHooks) BeforeValidatorSlashed(ctx sdk.Context, valAddr sdk.ValAddress, fraction sdk.Dec) { + for i := range h { + h[i].BeforeValidatorSlashed(ctx, valAddr, fraction) + } +} diff --git a/x/staking/types/msg.go b/x/staking/types/msg.go index 9bf839fa2443..0114324c74bd 100644 --- a/x/staking/types/msg.go +++ b/x/staking/types/msg.go @@ -114,7 +114,7 @@ func (msg *MsgCreateValidator) UnmarshalJSON(bz []byte) error { // GetSignBytes returns the message bytes to sign over. func (msg MsgCreateValidator) GetSignBytes() []byte { - bz := MsgCdc.MustMarshalJSON(msg) + bz := ModuleCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } @@ -181,7 +181,7 @@ func (msg MsgEditValidator) GetSigners() []sdk.AccAddress { // get the bytes for the message signer to sign on func (msg MsgEditValidator) GetSignBytes() []byte { - bz := MsgCdc.MustMarshalJSON(msg) + bz := ModuleCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } @@ -232,7 +232,7 @@ func (msg MsgDelegate) GetSigners() []sdk.AccAddress { // get the bytes for the message signer to sign on func (msg MsgDelegate) GetSignBytes() []byte { - bz := MsgCdc.MustMarshalJSON(msg) + bz := ModuleCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } @@ -280,7 +280,7 @@ func (msg MsgBeginRedelegate) GetSigners() []sdk.AccAddress { // get the bytes for the message signer to sign on func (msg MsgBeginRedelegate) GetSignBytes() []byte { - bz := MsgCdc.MustMarshalJSON(msg) + bz := ModuleCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } @@ -323,7 +323,7 @@ func (msg MsgUndelegate) GetSigners() []sdk.AccAddress { return []sdk.AccAddress // get the bytes for the message signer to sign on func (msg MsgUndelegate) GetSignBytes() []byte { - bz := MsgCdc.MustMarshalJSON(msg) + bz := ModuleCdc.MustMarshalJSON(msg) return sdk.MustSortJSON(bz) } diff --git a/x/staking/types/params.go b/x/staking/types/params.go index 3239bdc25da7..c0f0e636275e 100644 --- a/x/staking/types/params.go +++ b/x/staking/types/params.go @@ -66,8 +66,8 @@ func (p *Params) ParamSetPairs() params.ParamSetPairs { // Equal returns a boolean determining if two Param types are identical. // TODO: This is slower than comparing struct fields directly func (p Params) Equal(p2 Params) bool { - bz1 := MsgCdc.MustMarshalBinaryLengthPrefixed(&p) - bz2 := MsgCdc.MustMarshalBinaryLengthPrefixed(&p2) + bz1 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&p) + bz2 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&p2) return bytes.Equal(bz1, bz2) } diff --git a/x/staking/types/pool.go b/x/staking/types/pool.go index d3905085a6c7..6ab2f17cdb53 100644 --- a/x/staking/types/pool.go +++ b/x/staking/types/pool.go @@ -17,8 +17,8 @@ type Pool struct { // nolint // TODO: This is slower than comparing struct fields directly func (p Pool) Equal(p2 Pool) bool { - bz1 := MsgCdc.MustMarshalBinaryLengthPrefixed(&p) - bz2 := MsgCdc.MustMarshalBinaryLengthPrefixed(&p2) + bz1 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&p) + bz2 := ModuleCdc.MustMarshalBinaryLengthPrefixed(&p2) return bytes.Equal(bz1, bz2) }