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

feat: migrate x/capability to app wiring #12058

Merged
merged 26 commits into from
Jun 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
cfee9c8
feat: migrate x/capability to app wiring
facundomedica May 26, 2022
96cfc00
added some fixes from Matt's PR + changed MemStoreKey
facundomedica May 26, 2022
117673f
Merge branch 'main' of https://github.com/cosmos/cosmos-sdk into facu…
facundomedica May 26, 2022
7b560b1
fix name
facundomedica May 26, 2022
5002e6a
fix name
facundomedica May 26, 2022
5d81575
small change
facundomedica May 26, 2022
f1094f5
Merge branch 'main' into facu/app-wiring-capability
facundomedica May 26, 2022
229be85
Merge branch 'main' into facu/app-wiring-capability
facundomedica May 27, 2022
ad191ea
rollback MemStoreKey change
facundomedica May 27, 2022
3e6a4d5
Merge branch 'facu/app-wiring-capability' of https://github.com/cosmo…
facundomedica May 27, 2022
87a461d
Revert "rollback MemStoreKey change"
facundomedica May 27, 2022
6f1ee5c
Merge branch 'main' into facu/app-wiring-capability
facundomedica May 27, 2022
d63dbfd
Merge branch 'main' into facu/app-wiring-capability
facundomedica May 27, 2022
15a83b0
Merge branch 'main' into facu/app-wiring-capability
facundomedica May 30, 2022
efb0394
Merge branch 'main' into facu/app-wiring-capability
facundomedica May 30, 2022
6606c18
merge main
facundomedica Jun 1, 2022
8da73e5
Merge branch 'facu/app-wiring-capability' of https://github.com/cosmo…
facundomedica Jun 1, 2022
27146e6
add suggestions by @aaronc
facundomedica Jun 1, 2022
e9c81a9
Merge branch 'main' into facu/app-wiring-capability
facundomedica Jun 1, 2022
7ac22c1
add IsSealed()
facundomedica Jun 1, 2022
14b798d
Merge branch 'facu/app-wiring-capability' of https://github.com/cosmo…
facundomedica Jun 1, 2022
0ecb89f
Merge branch 'main' into facu/app-wiring-capability
facundomedica Jun 1, 2022
aa33d9c
Merge branch 'main' into facu/app-wiring-capability
aaronc Jun 1, 2022
5bde56e
fix conflicts
facundomedica Jun 2, 2022
30c207c
fix
facundomedica Jun 2, 2022
90fc1ef
Merge branch 'main' into facu/app-wiring-capability
facundomedica Jun 2, 2022
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
572 changes: 572 additions & 0 deletions api/cosmos/capability/module/v1/module.pulsar.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,9 @@ func (app *BaseApp) MountStores(keys ...storetypes.StoreKey) {
case *storetypes.TransientStoreKey:
app.MountStore(key, storetypes.StoreTypeTransient)

case *storetypes.MemoryStoreKey:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if adding this to baseapp is the way to go

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the context here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runtime/builder uses baseApps' MountStores. Without this addition we get this error Unrecognized store key type :*types.MemoryStoreKey.
I think that if we filter out any MemoryStoreKeys before calling this everything works just fine... I don't know enough about these things to know exactly what's up 😅

// Build builds an *App instance.
func (a *AppBuilder) Build(logger log.Logger, db dbm.DB, traceStore io.Writer, baseAppOptions ...func(*baseapp.BaseApp)) *App {
for _, option := range a.app.baseAppOptions {
baseAppOptions = append(baseAppOptions, option)
}
// TODO: when the auth module is configured, fill-in txDecoder
bApp := baseapp.NewBaseApp(a.app.config.AppName, logger, db, nil, baseAppOptions...)
bApp.SetCommitMultiStoreTracer(traceStore)
bApp.SetVersion(version.Version)
bApp.SetInterfaceRegistry(a.app.interfaceRegistry)
bApp.MountStores(a.app.storeKeys...)
a.app.BaseApp = bApp
return a.app
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nvm tried again removing it and it doesn't work

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really sure about this code. I'd have to delegate to @aaronc here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this addition is correct. IMHO the fact that the multi-store doesn't know how to map store keys -> store types is a really strange and error prone. So this patch is sort of needed, but really the multi-store design should be cleaned up a bit

app.MountStore(key, storetypes.StoreTypeMemory)

default:
panic(fmt.Sprintf("Unrecognized store key type :%T", key))
}
Expand Down
16 changes: 16 additions & 0 deletions proto/cosmos/capability/module/v1/module.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
syntax = "proto3";

package cosmos.capability.module.v1;

import "cosmos/app/v1alpha1/module.proto";

// Module is the config object of the capability module.
message Module {
option (cosmos.app.v1alpha1.module) = {
go_import: "github.com/cosmos/cosmos-sdk/x/capability"
};

// seal_keeper defines if keeper.Seal() will run on BeginBlock() to prevent further modules from creating a scoped
// keeper. For more details check x/capability/keeper.go.
bool seal_keeper = 1;
}
144 changes: 66 additions & 78 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,102 +208,81 @@ func NewSimApp(
homePath string, invCheckPeriod uint, encodingConfig simappparams.EncodingConfig,
appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp),
) *SimApp {
app := &SimApp{
invCheckPeriod: invCheckPeriod,
}

var appBuilder *runtime.AppBuilder
var paramsKeeper paramskeeper.Keeper
var accountKeeper authkeeper.AccountKeeper
var bankKeeper bankkeeper.Keeper
var appCodec codec.Codec
var legacyAmino *codec.LegacyAmino
var interfaceRegistry codectypes.InterfaceRegistry

err := depinject.Inject(AppConfig,
&appBuilder,
&paramsKeeper,
&appCodec,
&legacyAmino,
&interfaceRegistry,
&accountKeeper,
&bankKeeper,
&app.ParamsKeeper,
&app.CapabilityKeeper,
&app.appCodec,
&app.legacyAmino,
&app.interfaceRegistry,
&app.AccountKeeper,
&app.BankKeeper,
)
if err != nil {
panic(err)
}

runtimeApp := appBuilder.Build(logger, db, traceStore, baseAppOptions...)
app.App = appBuilder.Build(logger, db, traceStore, baseAppOptions...)

keys := sdk.NewKVStoreKeys(
stakingtypes.StoreKey,
minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey,
govtypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey,
evidencetypes.StoreKey, capabilitytypes.StoreKey,
authzkeeper.StoreKey, nftkeeper.StoreKey, group.StoreKey,
app.keys = sdk.NewKVStoreKeys(
stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey,
slashingtypes.StoreKey, govtypes.StoreKey, upgradetypes.StoreKey,
feegrant.StoreKey, evidencetypes.StoreKey, authzkeeper.StoreKey,
nftkeeper.StoreKey, group.StoreKey,
)
// NOTE: The testingkey is just mounted for testing purposes. Actual applications should
// not include this key.
memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey, "testingkey")
app.memKeys = sdk.NewMemoryStoreKeys("testingkey")

// configure state listening capabilities using AppOptions
// we are doing nothing with the returned streamingServices and waitGroup in this case
if _, _, err := streaming.LoadStreamingServices(runtimeApp.BaseApp, appOpts, appCodec, keys); err != nil {
if _, _, err := streaming.LoadStreamingServices(app.App.BaseApp, appOpts, app.appCodec, app.keys); err != nil {
tmos.Exit(err.Error())
}

app := &SimApp{
App: runtimeApp,
legacyAmino: legacyAmino,
appCodec: appCodec,
interfaceRegistry: interfaceRegistry,
invCheckPeriod: invCheckPeriod,
keys: keys,
memKeys: memKeys,
}

app.ParamsKeeper = paramsKeeper
initParamsKeeper(paramsKeeper)

app.AccountKeeper = accountKeeper

app.CapabilityKeeper = capabilitykeeper.NewKeeper(appCodec, keys[capabilitytypes.StoreKey], memKeys[capabilitytypes.MemStoreKey])
// Applications that wish to enforce statically created ScopedKeepers should call `Seal` after creating
// their scoped modules in `NewApp` with `ScopeToModule`
app.CapabilityKeeper.Seal()
initParamsKeeper(app.ParamsKeeper)

// add keepers
app.BankKeeper = bankKeeper

stakingKeeper := stakingkeeper.NewKeeper(
appCodec, keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName),
app.appCodec, app.keys[stakingtypes.StoreKey], app.AccountKeeper, app.BankKeeper, app.GetSubspace(stakingtypes.ModuleName),
)
app.MintKeeper = mintkeeper.NewKeeper(
appCodec, keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &stakingKeeper,
app.appCodec, app.keys[minttypes.StoreKey], app.GetSubspace(minttypes.ModuleName), &stakingKeeper,
app.AccountKeeper, app.BankKeeper, authtypes.FeeCollectorName,
)
app.DistrKeeper = distrkeeper.NewKeeper(
appCodec, keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
app.appCodec, app.keys[distrtypes.StoreKey], app.GetSubspace(distrtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, authtypes.FeeCollectorName,
)
app.SlashingKeeper = slashingkeeper.NewKeeper(
appCodec, keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
app.appCodec, app.keys[slashingtypes.StoreKey], &stakingKeeper, app.GetSubspace(slashingtypes.ModuleName),
)
app.CrisisKeeper = crisiskeeper.NewKeeper(
app.GetSubspace(crisistypes.ModuleName), invCheckPeriod, app.BankKeeper, authtypes.FeeCollectorName,
)

app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper)
app.FeeGrantKeeper = feegrantkeeper.NewKeeper(app.appCodec, app.keys[feegrant.StoreKey], app.AccountKeeper)

// register the staking hooks
// NOTE: stakingKeeper above is passed by reference, so that it will contain these hooks
app.StakingKeeper = *stakingKeeper.SetHooks(
stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()),
)

app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper)
app.AuthzKeeper = authzkeeper.NewKeeper(app.keys[authzkeeper.StoreKey], app.appCodec, app.MsgServiceRouter(), app.AccountKeeper)

groupConfig := group.DefaultConfig()
/*
Example of setting group params:
groupConfig.MaxMetadataLen = 1000
*/
app.GroupKeeper = groupkeeper.NewKeeper(keys[group.StoreKey], appCodec, app.MsgServiceRouter(), app.AccountKeeper, groupConfig)
app.GroupKeeper = groupkeeper.NewKeeper(app.keys[group.StoreKey], app.appCodec, app.MsgServiceRouter(), app.AccountKeeper, groupConfig)

// register the proposal types
govRouter := govv1beta1.NewRouter()
Expand All @@ -317,7 +296,7 @@ func NewSimApp(
govConfig.MaxMetadataLen = 10000
*/
govKeeper := govkeeper.NewKeeper(
appCodec, keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
app.appCodec, app.keys[govtypes.StoreKey], app.GetSubspace(govtypes.ModuleName), app.AccountKeeper, app.BankKeeper,
&stakingKeeper, govRouter, app.MsgServiceRouter(), govConfig,
)

Expand All @@ -327,13 +306,13 @@ func NewSimApp(
),
)
// set the governance module account as the authority for conducting upgrades
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp, authtypes.NewModuleAddress(govtypes.ModuleName).String())
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, app.keys[upgradetypes.StoreKey], app.appCodec, homePath, app.BaseApp, authtypes.NewModuleAddress(govtypes.ModuleName).String())

app.NFTKeeper = nftkeeper.NewKeeper(keys[nftkeeper.StoreKey], appCodec, app.AccountKeeper, app.BankKeeper)
app.NFTKeeper = nftkeeper.NewKeeper(app.keys[nftkeeper.StoreKey], app.appCodec, app.AccountKeeper, app.BankKeeper)

// create evidence keeper with router
evidenceKeeper := evidencekeeper.NewKeeper(
appCodec, keys[evidencetypes.StoreKey], &app.StakingKeeper, app.SlashingKeeper,
app.appCodec, app.keys[evidencetypes.StoreKey], &app.StakingKeeper, app.SlashingKeeper,
)
// If evidence needs to be handled for the app, set routes in router here and seal
app.EvidenceKeeper = *evidenceKeeper
Expand All @@ -352,19 +331,18 @@ func NewSimApp(
encodingConfig.TxConfig,
),
vesting.NewAppModule(app.AccountKeeper, app.BankKeeper),
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
feegrantmodule.NewAppModule(app.appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(app.appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
mint.NewAppModule(app.appCodec, app.MintKeeper, app.AccountKeeper, nil),
slashing.NewAppModule(app.appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
distr.NewAppModule(app.appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
staking.NewAppModule(app.appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
upgrade.NewAppModule(app.UpgradeKeeper),
evidence.NewAppModule(app.EvidenceKeeper),
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
nftmodule.NewAppModule(appCodec, app.NFTKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
authzmodule.NewAppModule(app.appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
groupmodule.NewAppModule(app.appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
nftmodule.NewAppModule(app.appCodec, app.NFTKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
)
if err != nil {
panic(err)
Expand Down Expand Up @@ -402,27 +380,26 @@ func NewSimApp(
// NOTE: this is not required apps that don't use the simulator for fuzz testing
// transactions
app.sm = module.NewSimulationManager(
auth.NewAppModule(appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper),
capability.NewAppModule(appCodec, *app.CapabilityKeeper),
feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper, nil),
staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
auth.NewAppModule(app.appCodec, app.AccountKeeper, authsims.RandomGenesisAccounts),
bank.NewAppModule(app.appCodec, app.BankKeeper, app.AccountKeeper),
feegrantmodule.NewAppModule(app.appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry),
gov.NewAppModule(app.appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper),
mint.NewAppModule(app.appCodec, app.MintKeeper, app.AccountKeeper, nil),
staking.NewAppModule(app.appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper),
distr.NewAppModule(app.appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
slashing.NewAppModule(app.appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper),
params.NewAppModule(app.ParamsKeeper),
evidence.NewAppModule(app.EvidenceKeeper),
authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
groupmodule.NewAppModule(appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
nftmodule.NewAppModule(appCodec, app.NFTKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
authzmodule.NewAppModule(app.appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
groupmodule.NewAppModule(app.appCodec, app.GroupKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
nftmodule.NewAppModule(app.appCodec, app.NFTKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry),
)

app.sm.RegisterStoreDecoders()

// initialize stores
app.MountKVStores(keys)
app.MountMemoryStores(memKeys)
app.MountKVStores(app.keys)
app.MountMemoryStores(app.memKeys)

// initialize BaseApp
app.SetTxDecoder(encodingConfig.TxConfig.TxDecoder())
Expand Down Expand Up @@ -547,7 +524,18 @@ func (app *SimApp) GetTKey(storeKey string) *storetypes.TransientStoreKey {
//
// NOTE: This is solely used for testing purposes.
func (app *SimApp) GetMemKey(storeKey string) *storetypes.MemoryStoreKey {
return app.memKeys[storeKey]
msk := app.memKeys[storeKey]
if msk != nil {
return msk
}

sk := app.UnsafeFindStoreKey(storeKey)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When would a mem key be found in the list of real store keys?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

provideMemoryStoreKey calls registerStoreKey which appends the key to the list of store keys. Should we have a separate list for them?

func provideMemoryStoreKey(key container.ModuleKey, app appWrapper) *storetypes.MemoryStoreKey {
storeKey := storetypes.NewMemoryStoreKey(fmt.Sprintf("memory:%s", key.Name()))
registerStoreKey(app, storeKey)
return storeKey
}

memStoreKey, ok := sk.(*storetypes.MemoryStoreKey)
if !ok {
return nil
}

return memStoreKey
}

// GetSubspace returns a param subspace for a given module name.
Expand Down
7 changes: 6 additions & 1 deletion simapp/app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,9 @@ modules:

- name: bank
config:
"@type": cosmos.bank.module.v1.Module
"@type": cosmos.bank.module.v1.Module

- name: capability
config:
"@type": cosmos.capability.module.v1.Module
seal_keeper: true
4 changes: 2 additions & 2 deletions x/capability/capability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (suite *CapabilityTestSuite) SetupTest() {
suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1})
suite.keeper = keeper
suite.cdc = cdc
suite.module = capability.NewAppModule(cdc, *keeper)
suite.module = capability.NewAppModule(cdc, *keeper, true)
}

// The following test case mocks a specific bug discovered in https://github.com/cosmos/cosmos-sdk/issues/9800
Expand All @@ -63,7 +63,7 @@ func (suite *CapabilityTestSuite) TestInitializeMemStore() {
// Mock app beginblock and ensure that no gas has been consumed and memstore is initialized
ctx = suite.app.BaseApp.NewContext(false, tmproto.Header{}).WithBlockGasMeter(sdk.NewGasMeter(50))
prevGas := ctx.BlockGasMeter().GasConsumed()
restartedModule := capability.NewAppModule(suite.cdc, *newKeeper)
restartedModule := capability.NewAppModule(suite.cdc, *newKeeper, true)
restartedModule.BeginBlock(ctx, abci.RequestBeginBlock{})
suite.Require().True(newKeeper.IsInitialized(ctx), "memstore initialized flag not set")
gasUsed := ctx.BlockGasMeter().GasConsumed()
Expand Down
5 changes: 5 additions & 0 deletions x/capability/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ func (k *Keeper) Seal() {
k.sealed = true
}

// IsSealed returns if the keeper is sealed.
func (k *Keeper) IsSealed() bool {
return k.sealed
}

// InitMemStore will assure that the module store is a memory store (it will panic if it's not)
// and willl initialize it. The function is safe to be called multiple times.
// InitMemStore must be called every time the app starts before the keeper is used (so
Expand Down
Loading