Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crisis Module Manager Fixes #4854

Merged
merged 5 commits into from
Aug 6, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,17 @@ func NewSimApp(
// register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.stakingKeeper = *stakingKeeper.SetHooks(
staking.NewMultiStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks()))
staking.NewMultiStakingHooks(app.distrKeeper.Hooks(), app.slashingKeeper.Hooks()),
)

// NOTE: Any module instantiated in the module manager that is later modified
// must be passed by reference here.
app.mm = module.NewManager(
genaccounts.NewAppModule(app.accountKeeper),
genutil.NewAppModule(app.accountKeeper, app.stakingKeeper, app.BaseApp.DeliverTx),
auth.NewAppModule(app.accountKeeper),
bank.NewAppModule(app.bankKeeper, app.accountKeeper),
crisis.NewAppModule(app.crisisKeeper),
crisis.NewAppModule(&app.crisisKeeper),
supply.NewAppModule(app.supplyKeeper, app.accountKeeper),
distr.NewAppModule(app.distrKeeper, app.supplyKeeper),
gov.NewAppModule(app.govKeeper, app.supplyKeeper),
Expand All @@ -184,13 +187,15 @@ func NewSimApp(
// CanWithdrawInvariant invariant.
app.mm.SetOrderBeginBlockers(mint.ModuleName, distr.ModuleName, slashing.ModuleName)

app.mm.SetOrderEndBlockers(gov.ModuleName, staking.ModuleName)
app.mm.SetOrderEndBlockers(crisis.ModuleName, gov.ModuleName, staking.ModuleName)

// genutils must occur after staking so that pools are properly
// initialized with tokens from genesis accounts.
app.mm.SetOrderInitGenesis(genaccounts.ModuleName, distr.ModuleName,
staking.ModuleName, auth.ModuleName, bank.ModuleName, slashing.ModuleName,
gov.ModuleName, mint.ModuleName, supply.ModuleName, crisis.ModuleName, genutil.ModuleName)
// NOTE: The genutils moodule must occur after staking so that pools are
// properly initialized with tokens from genesis accounts.
app.mm.SetOrderInitGenesis(
genaccounts.ModuleName, distr.ModuleName, staking.ModuleName,
auth.ModuleName, bank.ModuleName, slashing.ModuleName, gov.ModuleName,
mint.ModuleName, supply.ModuleName, crisis.ModuleName, genutil.ModuleName,
)

app.mm.RegisterInvariants(&app.crisisKeeper)
app.mm.RegisterRoutes(app.Router(), app.QueryRouter())
Expand Down
21 changes: 11 additions & 10 deletions x/crisis/internal/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ type Keeper struct {
}

// NewKeeper creates a new Keeper object
func NewKeeper(paramSpace params.Subspace, invCheckPeriod uint,
supplyKeeper types.SupplyKeeper, feeCollectorName string) Keeper {
func NewKeeper(
paramSpace params.Subspace, invCheckPeriod uint, supplyKeeper types.SupplyKeeper,
feeCollectorName string,
) Keeper {

return Keeper{
routes: []types.InvarRoute{},
routes: make([]types.InvarRoute, 0),
paramSpace: paramSpace.WithKeyTable(types.ParamKeyTable()),
invCheckPeriod: invCheckPeriod,
supplyKeeper: supplyKeeper,
Expand All @@ -53,22 +55,23 @@ func (k Keeper) Routes() []types.InvarRoute {

// Invariants returns all the registered Crisis keeper invariants.
func (k Keeper) Invariants() []sdk.Invariant {
var invars []sdk.Invariant
for _, route := range k.routes {
invars = append(invars, route.Invar)
invars := make([]sdk.Invariant, len(k.routes))
for i, route := range k.routes {
invars[i] = route.Invar
}
return invars
}

// assert all invariants
// AssertInvariants asserts all registered invariants. If any invariant fails,
// the method panics.
func (k Keeper) AssertInvariants(ctx sdk.Context) {
logger := k.Logger(ctx)

start := time.Now()
invarRoutes := k.Routes()

for _, ir := range invarRoutes {
if res, stop := ir.Invar(ctx); stop {

// TODO: Include app name as part of context to allow for this to be
// variable.
panic(fmt.Errorf("invariant broken: %s\n"+
Expand All @@ -90,5 +93,3 @@ func (k Keeper) InvCheckPeriod() uint { return k.invCheckPeriod }
func (k Keeper) SendCoinsFromAccountToFeeCollector(ctx sdk.Context, senderAddr sdk.AccAddress, amt sdk.Coins) sdk.Error {
return k.supplyKeeper.SendCoinsFromAccountToModule(ctx, senderAddr, k.feeCollectorName, amt)
}

// DONTCOVER
56 changes: 56 additions & 0 deletions x/crisis/internal/keeper/keeper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package keeper

import (
"testing"

"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log"

"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/crisis/internal/types"
"github.com/cosmos/cosmos-sdk/x/params"
)

func testPassingInvariant(_ sdk.Context) (string, bool) {
return "", false
}

func testFailingInvariant(_ sdk.Context) (string, bool) {
return "", true
}

func testKeeper(checkPeriod uint) Keeper {
cdc := codec.New()
paramsKeeper := params.NewKeeper(
cdc, sdk.NewKVStoreKey(params.StoreKey), sdk.NewTransientStoreKey(params.TStoreKey), params.DefaultCodespace,
)

return NewKeeper(paramsKeeper.Subspace(types.DefaultParamspace), checkPeriod, nil, "test")
}

func TestLogger(t *testing.T) {
k := testKeeper(5)

ctx := sdk.Context{}.WithLogger(log.NewNopLogger())
require.Equal(t, ctx.Logger(), k.Logger(ctx))
}

func TestInvariants(t *testing.T) {
k := testKeeper(5)
require.Equal(t, k.InvCheckPeriod(), uint(5))

k.RegisterRoute("testModule", "testRoute", testPassingInvariant)
require.Len(t, k.Routes(), 1)
}

func TestAssertInvariants(t *testing.T) {
k := testKeeper(5)
ctx := sdk.Context{}.WithLogger(log.NewNopLogger())

k.RegisterRoute("testModule", "testRoute1", testPassingInvariant)
require.NotPanics(t, func() { k.AssertInvariants(ctx) })

k.RegisterRoute("testModule", "testRoute2", testFailingInvariant)
require.Panics(t, func() { k.AssertInvariants(ctx) })
}
61 changes: 33 additions & 28 deletions x/crisis/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,26 @@ var (
_ module.AppModuleBasic = AppModuleBasic{}
)

// app module basics object
// AppModuleBasic defines the basic application module used by the crisis module.
type AppModuleBasic struct{}

var _ module.AppModuleBasic = AppModuleBasic{}

// module name
// Name returns the crisis module's name.
func (AppModuleBasic) Name() string {
return ModuleName
}

// register module codec
// RegisterCodec registers the crisis module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {
RegisterCodec(cdc)
}

// default genesis state
// DefaultGenesis returns default genesis state as raw bytes for the crisis
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return types.ModuleCdc.MustMarshalJSON(DefaultGenesisState())
}

// module validate genesis
// ValidateGenesis performs genesis state validation for the crisis module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data types.GenesisState
if err := types.ModuleCdc.UnmarshalJSON(bz, &data); err != nil {
Expand All @@ -51,77 +50,83 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return types.ValidateGenesis(data)
}

// register rest routes
// RegisterRESTRoutes registers no REST routes for the crisis module.
func (AppModuleBasic) RegisterRESTRoutes(_ context.CLIContext, _ *mux.Router) {}

// get the root tx command of this module
// GetTxCmd returns the root tx command for the crisis module.
func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetTxCmd(cdc)
}

// get the root query command of this module
// GetQueryCmd returns no root query command for the crisis module.
func (AppModuleBasic) GetQueryCmd(_ *codec.Codec) *cobra.Command { return nil }

//___________________________
// app module for bank
// AppModule implements an application module for the crisis module.
type AppModule struct {
AppModuleBasic
keeper keeper.Keeper

// NOTE: We store a reference to the keeper here so that after a module
// manager is created, the invariants can be properly registered and
// executed.
keeper *keeper.Keeper
}

// NewAppModule creates a new AppModule object
func NewAppModule(keeper keeper.Keeper) AppModule {
func NewAppModule(keeper *keeper.Keeper) AppModule {
return AppModule{
AppModuleBasic: AppModuleBasic{},
keeper: keeper,
}
}

// module name
// Name returns the crisis module's name.
func (AppModule) Name() string {
return ModuleName
}

// register invariants
// RegisterInvariants performs a no-op.
func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}

// module querier route name
// Route returns the message routing key for the crisis module.
func (AppModule) Route() string {
return RouterKey
}

// module handler
// NewHandler returns an sdk.Handler for the crisis module.
func (am AppModule) NewHandler() sdk.Handler {
return NewHandler(am.keeper)
return NewHandler(*am.keeper)
}

// module querier route name
// QuerierRoute returns no querier route.
func (AppModule) QuerierRoute() string { return "" }

// module querier
// NewQuerierHandler returns no sdk.Querier.
func (AppModule) NewQuerierHandler() sdk.Querier { return nil }

// module init-genesis
// InitGenesis performs genesis initialization for the crisis module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState
types.ModuleCdc.MustUnmarshalJSON(data, &genesisState)
InitGenesis(ctx, am.keeper, genesisState)
InitGenesis(ctx, *am.keeper, genesisState)

am.keeper.AssertInvariants(ctx)
return []abci.ValidatorUpdate{}
}

// module export genesis
// ExportGenesis returns the exported genesis state as raw bytes for the crisis
// module.
func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper)
gs := ExportGenesis(ctx, *am.keeper)
return types.ModuleCdc.MustMarshalJSON(gs)
}

// module begin-block
// BeginBlock returns the begin blocker for the crisis module.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}

// module end-block
// EndBlock returns the end blocker for the crisis module. It returns no validator
// updates.
func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
EndBlocker(ctx, am.keeper)
EndBlocker(ctx, *am.keeper)
return []abci.ValidatorUpdate{}
}