Merge PR #4854: Crisis Module Manager Fixes

This commit is contained in:
Alexander Bezobchuk 2019-08-06 15:11:55 -04:00 committed by GitHub
parent 1f8cdeed55
commit c8ee82b40a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 116 additions and 49 deletions

View File

@ -163,14 +163,17 @@ func NewSimApp(
// register the staking hooks // register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks // NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.stakingKeeper = *stakingKeeper.SetHooks( 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( app.mm = module.NewManager(
genaccounts.NewAppModule(app.accountKeeper), genaccounts.NewAppModule(app.accountKeeper),
genutil.NewAppModule(app.accountKeeper, app.stakingKeeper, app.BaseApp.DeliverTx), genutil.NewAppModule(app.accountKeeper, app.stakingKeeper, app.BaseApp.DeliverTx),
auth.NewAppModule(app.accountKeeper), auth.NewAppModule(app.accountKeeper),
bank.NewAppModule(app.bankKeeper, app.accountKeeper), bank.NewAppModule(app.bankKeeper, app.accountKeeper),
crisis.NewAppModule(app.crisisKeeper), crisis.NewAppModule(&app.crisisKeeper),
supply.NewAppModule(app.supplyKeeper, app.accountKeeper), supply.NewAppModule(app.supplyKeeper, app.accountKeeper),
distr.NewAppModule(app.distrKeeper, app.supplyKeeper), distr.NewAppModule(app.distrKeeper, app.supplyKeeper),
gov.NewAppModule(app.govKeeper, app.supplyKeeper), gov.NewAppModule(app.govKeeper, app.supplyKeeper),
@ -184,13 +187,15 @@ func NewSimApp(
// CanWithdrawInvariant invariant. // CanWithdrawInvariant invariant.
app.mm.SetOrderBeginBlockers(mint.ModuleName, distr.ModuleName, slashing.ModuleName) 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 // NOTE: The genutils moodule must occur after staking so that pools are
// initialized with tokens from genesis accounts. // properly initialized with tokens from genesis accounts.
app.mm.SetOrderInitGenesis(genaccounts.ModuleName, distr.ModuleName, app.mm.SetOrderInitGenesis(
staking.ModuleName, auth.ModuleName, bank.ModuleName, slashing.ModuleName, genaccounts.ModuleName, distr.ModuleName, staking.ModuleName,
gov.ModuleName, mint.ModuleName, supply.ModuleName, crisis.ModuleName, genutil.ModuleName) auth.ModuleName, bank.ModuleName, slashing.ModuleName, gov.ModuleName,
mint.ModuleName, supply.ModuleName, crisis.ModuleName, genutil.ModuleName,
)
app.mm.RegisterInvariants(&app.crisisKeeper) app.mm.RegisterInvariants(&app.crisisKeeper)
app.mm.RegisterRoutes(app.Router(), app.QueryRouter()) app.mm.RegisterRoutes(app.Router(), app.QueryRouter())

View File

@ -554,7 +554,7 @@ func TestAppImportExport(t *testing.T) {
defer func() { defer func() {
newDB.Close() newDB.Close()
os.RemoveAll(newDir) _ = os.RemoveAll(newDir)
}() }()
newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt) newApp := NewSimApp(log.NewNopLogger(), newDB, nil, true, 0, fauxMerkleModeOpt)
@ -566,11 +566,11 @@ func TestAppImportExport(t *testing.T) {
panic(err) panic(err)
} }
ctxB := newApp.NewContext(true, abci.Header{}) ctxB := newApp.NewContext(true, abci.Header{Height: app.LastBlockHeight()})
newApp.mm.InitGenesis(ctxB, genesisState) newApp.mm.InitGenesis(ctxB, genesisState)
fmt.Printf("Comparing stores...\n") fmt.Printf("Comparing stores...\n")
ctxA := app.NewContext(true, abci.Header{}) ctxA := app.NewContext(true, abci.Header{Height: app.LastBlockHeight()})
type StoreKeysPrefixes struct { type StoreKeysPrefixes struct {
A sdk.StoreKey A sdk.StoreKey

View File

@ -23,11 +23,13 @@ type Keeper struct {
} }
// NewKeeper creates a new Keeper object // NewKeeper creates a new Keeper object
func NewKeeper(paramSpace params.Subspace, invCheckPeriod uint, func NewKeeper(
supplyKeeper types.SupplyKeeper, feeCollectorName string) Keeper { paramSpace params.Subspace, invCheckPeriod uint, supplyKeeper types.SupplyKeeper,
feeCollectorName string,
) Keeper {
return Keeper{ return Keeper{
routes: []types.InvarRoute{}, routes: make([]types.InvarRoute, 0),
paramSpace: paramSpace.WithKeyTable(types.ParamKeyTable()), paramSpace: paramSpace.WithKeyTable(types.ParamKeyTable()),
invCheckPeriod: invCheckPeriod, invCheckPeriod: invCheckPeriod,
supplyKeeper: supplyKeeper, supplyKeeper: supplyKeeper,
@ -53,22 +55,23 @@ func (k Keeper) Routes() []types.InvarRoute {
// Invariants returns all the registered Crisis keeper invariants. // Invariants returns all the registered Crisis keeper invariants.
func (k Keeper) Invariants() []sdk.Invariant { func (k Keeper) Invariants() []sdk.Invariant {
var invars []sdk.Invariant invars := make([]sdk.Invariant, len(k.routes))
for _, route := range k.routes { for i, route := range k.routes {
invars = append(invars, route.Invar) invars[i] = route.Invar
} }
return invars return invars
} }
// assert all invariants // AssertInvariants asserts all registered invariants. If any invariant fails,
// the method panics.
func (k Keeper) AssertInvariants(ctx sdk.Context) { func (k Keeper) AssertInvariants(ctx sdk.Context) {
logger := k.Logger(ctx) logger := k.Logger(ctx)
start := time.Now() start := time.Now()
invarRoutes := k.Routes() invarRoutes := k.Routes()
for _, ir := range invarRoutes { for _, ir := range invarRoutes {
if res, stop := ir.Invar(ctx); stop { if res, stop := ir.Invar(ctx); stop {
// TODO: Include app name as part of context to allow for this to be // TODO: Include app name as part of context to allow for this to be
// variable. // variable.
panic(fmt.Errorf("invariant broken: %s\n"+ panic(fmt.Errorf("invariant broken: %s\n"+
@ -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 { func (k Keeper) SendCoinsFromAccountToFeeCollector(ctx sdk.Context, senderAddr sdk.AccAddress, amt sdk.Coins) sdk.Error {
return k.supplyKeeper.SendCoinsFromAccountToModule(ctx, senderAddr, k.feeCollectorName, amt) return k.supplyKeeper.SendCoinsFromAccountToModule(ctx, senderAddr, k.feeCollectorName, amt)
} }
// DONTCOVER

View File

@ -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) })
}

View File

@ -22,27 +22,26 @@ var (
_ module.AppModuleBasic = AppModuleBasic{} _ module.AppModuleBasic = AppModuleBasic{}
) )
// app module basics object // AppModuleBasic defines the basic application module used by the crisis module.
type AppModuleBasic struct{} type AppModuleBasic struct{}
var _ module.AppModuleBasic = AppModuleBasic{} // Name returns the crisis module's name.
// module name
func (AppModuleBasic) Name() string { func (AppModuleBasic) Name() string {
return ModuleName return ModuleName
} }
// register module codec // RegisterCodec registers the crisis module's types for the given codec.
func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) { func (AppModuleBasic) RegisterCodec(cdc *codec.Codec) {
RegisterCodec(cdc) RegisterCodec(cdc)
} }
// default genesis state // DefaultGenesis returns default genesis state as raw bytes for the crisis
// module.
func (AppModuleBasic) DefaultGenesis() json.RawMessage { func (AppModuleBasic) DefaultGenesis() json.RawMessage {
return types.ModuleCdc.MustMarshalJSON(DefaultGenesisState()) return types.ModuleCdc.MustMarshalJSON(DefaultGenesisState())
} }
// module validate genesis // ValidateGenesis performs genesis state validation for the crisis module.
func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error { func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
var data types.GenesisState var data types.GenesisState
if err := types.ModuleCdc.UnmarshalJSON(bz, &data); err != nil { if err := types.ModuleCdc.UnmarshalJSON(bz, &data); err != nil {
@ -51,77 +50,83 @@ func (AppModuleBasic) ValidateGenesis(bz json.RawMessage) error {
return types.ValidateGenesis(data) return types.ValidateGenesis(data)
} }
// register rest routes // RegisterRESTRoutes registers no REST routes for the crisis module.
func (AppModuleBasic) RegisterRESTRoutes(_ context.CLIContext, _ *mux.Router) {} 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 { func (AppModuleBasic) GetTxCmd(cdc *codec.Codec) *cobra.Command {
return cli.GetTxCmd(cdc) 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 } func (AppModuleBasic) GetQueryCmd(_ *codec.Codec) *cobra.Command { return nil }
//___________________________ // AppModule implements an application module for the crisis module.
// app module for bank
type AppModule struct { type AppModule struct {
AppModuleBasic 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 // NewAppModule creates a new AppModule object
func NewAppModule(keeper keeper.Keeper) AppModule { func NewAppModule(keeper *keeper.Keeper) AppModule {
return AppModule{ return AppModule{
AppModuleBasic: AppModuleBasic{}, AppModuleBasic: AppModuleBasic{},
keeper: keeper, keeper: keeper,
} }
} }
// module name // Name returns the crisis module's name.
func (AppModule) Name() string { func (AppModule) Name() string {
return ModuleName return ModuleName
} }
// register invariants // RegisterInvariants performs a no-op.
func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {}
// module querier route name // Route returns the message routing key for the crisis module.
func (AppModule) Route() string { func (AppModule) Route() string {
return RouterKey return RouterKey
} }
// module handler // NewHandler returns an sdk.Handler for the crisis module.
func (am AppModule) NewHandler() sdk.Handler { 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 "" } func (AppModule) QuerierRoute() string { return "" }
// module querier // NewQuerierHandler returns no sdk.Querier.
func (AppModule) NewQuerierHandler() sdk.Querier { return nil } 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 { func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {
var genesisState GenesisState var genesisState GenesisState
types.ModuleCdc.MustUnmarshalJSON(data, &genesisState) types.ModuleCdc.MustUnmarshalJSON(data, &genesisState)
InitGenesis(ctx, am.keeper, genesisState) InitGenesis(ctx, *am.keeper, genesisState)
am.keeper.AssertInvariants(ctx) am.keeper.AssertInvariants(ctx)
return []abci.ValidatorUpdate{} 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 { func (am AppModule) ExportGenesis(ctx sdk.Context) json.RawMessage {
gs := ExportGenesis(ctx, am.keeper) gs := ExportGenesis(ctx, *am.keeper)
return types.ModuleCdc.MustMarshalJSON(gs) return types.ModuleCdc.MustMarshalJSON(gs)
} }
// module begin-block // BeginBlock returns the begin blocker for the crisis module.
func (AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {} 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 { func (am AppModule) EndBlock(ctx sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate {
EndBlocker(ctx, am.keeper) EndBlocker(ctx, *am.keeper)
return []abci.ValidatorUpdate{} return []abci.ValidatorUpdate{}
} }