feat!: return errors in module manager ABCI methods (#14847)
This commit is contained in:
parent
8eec98dcc5
commit
deeb4bd362
@ -169,8 +169,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### API Breaking Changes
|
||||
|
||||
* [#14847](https://github.com/cosmos/cosmos-sdk/pull/14847) App and ModuleManager methods `InitGenesis`, `ExportGenesis`, `BeginBlock` and `EndBlock` now also return an error.
|
||||
* (simulation) [#14728](https://github.com/cosmos/cosmos-sdk/pull/14728) Rename the `ParamChanges` field to `LegacyParamChange` and `Contents` to `LegacyProposalContents` in `simulation.SimulationState`. Additionally it adds a `ProposalMsgs` field to `simulation.SimulationState`.
|
||||
* (x/upgrade) [14764](https://github.com/cosmos/cosmos-sdk/pull/14764) The `x/upgrade` module is extracted to have a separate go.mod file which allows it to be a standalone module.
|
||||
* (x/upgrade) [#14764](https://github.com/cosmos/cosmos-sdk/pull/14764) The `x/upgrade` module is extracted to have a separate go.mod file which allows it to be a standalone module.
|
||||
* (x/gov) [#14782](https://github.com/cosmos/cosmos-sdk/pull/14782) Move the `metadata` argument in `govv1.NewProposal` alongside `title` and `summary`.
|
||||
* (store) [#14746](https://github.com/cosmos/cosmos-sdk/pull/14746) Extract Store in its own go.mod and rename the package to `cosmossdk.io/store`.
|
||||
* (simulation) [#14751](https://github.com/cosmos/cosmos-sdk/pull/14751) Remove the `MsgType` field from `simulation.OperationInput` struct.
|
||||
|
||||
@ -73,7 +73,10 @@ func (app *BaseApp) InitChain(req abci.RequestInitChain) (res abci.ResponseInitC
|
||||
// add block gas meter for any genesis transactions (allow infinite gas)
|
||||
app.deliverState.ctx = app.deliverState.ctx.WithBlockGasMeter(storetypes.NewInfiniteGasMeter())
|
||||
|
||||
res = app.initChainer(app.deliverState.ctx, req)
|
||||
res, err := app.initChainer(app.deliverState.ctx, req)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// sanity check
|
||||
if len(req.Validators) > 0 {
|
||||
@ -195,7 +198,11 @@ func (app *BaseApp) BeginBlock(req abci.RequestBeginBlock) (res abci.ResponseBeg
|
||||
}
|
||||
|
||||
if app.beginBlocker != nil {
|
||||
res = app.beginBlocker(app.deliverState.ctx, req)
|
||||
var err error
|
||||
res, err = app.beginBlocker(app.deliverState.ctx, req)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
res.Events = sdk.MarkEventsToIndex(res.Events, app.indexEvents)
|
||||
}
|
||||
// set the signed validators for addition to context in deliverTx
|
||||
@ -218,7 +225,11 @@ func (app *BaseApp) EndBlock(req abci.RequestEndBlock) (res abci.ResponseEndBloc
|
||||
}
|
||||
|
||||
if app.endBlocker != nil {
|
||||
res = app.endBlocker(app.deliverState.ctx, req)
|
||||
var err error
|
||||
res, err = app.endBlocker(app.deliverState.ctx, req)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
res.Events = sdk.MarkEventsToIndex(res.Events, app.indexEvents)
|
||||
}
|
||||
|
||||
|
||||
@ -54,10 +54,10 @@ func TestABCI_InitChain(t *testing.T) {
|
||||
|
||||
// set a value in the store on init chain
|
||||
key, value := []byte("hello"), []byte("goodbye")
|
||||
var initChainer sdk.InitChainer = func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
var initChainer sdk.InitChainer = func(ctx sdk.Context, req abci.RequestInitChain) (abci.ResponseInitChain, error) {
|
||||
store := ctx.KVStore(capKey)
|
||||
store.Set(key, value)
|
||||
return abci.ResponseInitChain{}
|
||||
return abci.ResponseInitChain{}, nil
|
||||
}
|
||||
|
||||
query := abci.RequestQuery{
|
||||
@ -579,12 +579,12 @@ func TestABCI_EndBlock(t *testing.T) {
|
||||
ConsensusParams: cp,
|
||||
})
|
||||
|
||||
app.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||
app.SetEndBlocker(func(ctx sdk.Context, req abci.RequestEndBlock) (abci.ResponseEndBlock, error) {
|
||||
return abci.ResponseEndBlock{
|
||||
ValidatorUpdates: []abci.ValidatorUpdate{
|
||||
{Power: 100},
|
||||
},
|
||||
}
|
||||
}, nil
|
||||
})
|
||||
app.Seal()
|
||||
|
||||
@ -1384,9 +1384,9 @@ func TestABCI_Proposal_Read_State_PrepareProposal(t *testing.T) {
|
||||
someKey := []byte("some-key")
|
||||
|
||||
setInitChainerOpt := func(bapp *baseapp.BaseApp) {
|
||||
bapp.SetInitChainer(func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
bapp.SetInitChainer(func(ctx sdk.Context, req abci.RequestInitChain) (abci.ResponseInitChain, error) {
|
||||
ctx.KVStore(capKey1).Set(someKey, []byte("foo"))
|
||||
return abci.ResponseInitChain{}
|
||||
return abci.ResponseInitChain{}, nil
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -116,17 +116,17 @@ func (a *App) Load(loadLatest bool) error {
|
||||
}
|
||||
|
||||
// BeginBlocker application updates every begin block
|
||||
func (a *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
||||
func (a *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) (abci.ResponseBeginBlock, error) {
|
||||
return a.ModuleManager.BeginBlock(ctx, req)
|
||||
}
|
||||
|
||||
// EndBlocker application updates every end block
|
||||
func (a *App) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||
func (a *App) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) (abci.ResponseEndBlock, error) {
|
||||
return a.ModuleManager.EndBlock(ctx, req)
|
||||
}
|
||||
|
||||
// InitChainer initializes the chain.
|
||||
func (a *App) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
func (a *App) InitChainer(ctx sdk.Context, req abci.RequestInitChain) (abci.ResponseInitChain, error) {
|
||||
var genesisState map[string]json.RawMessage
|
||||
if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
|
||||
panic(err)
|
||||
|
||||
@ -22,13 +22,13 @@ type AppI interface {
|
||||
LegacyAmino() *codec.LegacyAmino
|
||||
|
||||
// Application updates every begin block.
|
||||
BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock
|
||||
BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) (abci.ResponseBeginBlock, error)
|
||||
|
||||
// Application updates every end block.
|
||||
EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock
|
||||
EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) (abci.ResponseEndBlock, error)
|
||||
|
||||
// Application update at chain (i.e app) initialization.
|
||||
InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain
|
||||
InitChainer(ctx sdk.Context, req abci.RequestInitChain) (abci.ResponseInitChain, error)
|
||||
|
||||
// Loads the app at a given height.
|
||||
LoadHeight(height int64) error
|
||||
|
||||
@ -96,22 +96,21 @@ type GenesisJSON struct {
|
||||
|
||||
// InitChainer returns a function that can initialize the chain
|
||||
// with key/value pairs
|
||||
func InitChainer(key storetypes.StoreKey) func(sdk.Context, abci.RequestInitChain) abci.ResponseInitChain {
|
||||
return func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
func InitChainer(key storetypes.StoreKey) func(sdk.Context, abci.RequestInitChain) (abci.ResponseInitChain, error) {
|
||||
return func(ctx sdk.Context, req abci.RequestInitChain) (abci.ResponseInitChain, error) {
|
||||
stateJSON := req.AppStateBytes
|
||||
|
||||
genesisState := new(GenesisJSON)
|
||||
err := json.Unmarshal(stateJSON, genesisState)
|
||||
if err != nil {
|
||||
panic(err) // TODO https://github.com/cosmos/cosmos-sdk/issues/468
|
||||
// return sdk.ErrGenesisParse("").TraceCause(err, "")
|
||||
return abci.ResponseInitChain{}, err
|
||||
}
|
||||
|
||||
for _, val := range genesisState.Values {
|
||||
store := ctx.KVStore(key)
|
||||
store.Set([]byte(val.Key), []byte(val.Value))
|
||||
}
|
||||
return abci.ResponseInitChain{}
|
||||
return abci.ResponseInitChain{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -29,11 +29,12 @@ import (
|
||||
upgradeclient "cosmossdk.io/x/upgrade/client"
|
||||
upgradekeeper "cosmossdk.io/x/upgrade/keeper"
|
||||
upgradetypes "cosmossdk.io/x/upgrade/types"
|
||||
|
||||
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
"cosmossdk.io/x/feegrant"
|
||||
feegrantkeeper "cosmossdk.io/x/feegrant/keeper"
|
||||
feegrantmodule "cosmossdk.io/x/feegrant/module"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
@ -559,12 +560,12 @@ func (app *SimApp) setPostHandler() {
|
||||
func (app *SimApp) Name() string { return app.BaseApp.Name() }
|
||||
|
||||
// BeginBlocker application updates every begin block
|
||||
func (app *SimApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
||||
func (app *SimApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) (abci.ResponseBeginBlock, error) {
|
||||
return app.ModuleManager.BeginBlock(ctx, req)
|
||||
}
|
||||
|
||||
// EndBlocker application updates every end block
|
||||
func (app *SimApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||
func (app *SimApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) (abci.ResponseEndBlock, error) {
|
||||
return app.ModuleManager.EndBlock(ctx, req)
|
||||
}
|
||||
|
||||
@ -573,7 +574,7 @@ func (a *SimApp) Configurator() module.Configurator {
|
||||
}
|
||||
|
||||
// InitChainer application update at chain initialization
|
||||
func (app *SimApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
func (app *SimApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) (abci.ResponseInitChain, error) {
|
||||
var genesisState GenesisState
|
||||
if err := json.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
|
||||
panic(err)
|
||||
|
||||
@ -30,7 +30,11 @@ func (app *SimApp) ExportAppStateAndValidators(forZeroHeight bool, jailAllowedAd
|
||||
app.prepForZeroHeightGenesis(ctx, jailAllowedAddrs)
|
||||
}
|
||||
|
||||
genState := app.ModuleManager.ExportGenesisForModules(ctx, app.appCodec, modulesToExport)
|
||||
genState, err := app.ModuleManager.ExportGenesisForModules(ctx, app.appCodec, modulesToExport)
|
||||
if err != nil {
|
||||
return servertypes.ExportedApp{}, err
|
||||
}
|
||||
|
||||
appState, err := json.MarshalIndent(genState, "", " ")
|
||||
if err != nil {
|
||||
return servertypes.ExportedApp{}, err
|
||||
|
||||
@ -78,7 +78,7 @@ func (s *E2ETestSuite) SetupSuite() {
|
||||
|
||||
// Make sure not to forget to persist `myParams` into the actual store,
|
||||
// this is done in InitChain.
|
||||
app.SetInitChainer(func(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
app.SetInitChainer(func(ctx sdk.Context, req abci.RequestInitChain) (abci.ResponseInitChain, error) {
|
||||
subspace.SetParamSet(ctx, ¶mSet)
|
||||
|
||||
return app.InitChainer(ctx, req)
|
||||
|
||||
@ -1497,7 +1497,6 @@ func (s *E2ETestSuite) TestBlockResults() {
|
||||
)
|
||||
|
||||
return nil
|
||||
|
||||
}, 10)
|
||||
}
|
||||
|
||||
|
||||
@ -5,19 +5,19 @@ import (
|
||||
)
|
||||
|
||||
// InitChainer initializes application state at genesis
|
||||
type InitChainer func(ctx Context, req abci.RequestInitChain) abci.ResponseInitChain
|
||||
type InitChainer func(ctx Context, req abci.RequestInitChain) (abci.ResponseInitChain, error)
|
||||
|
||||
// BeginBlocker runs code before the transactions in a block
|
||||
//
|
||||
// Note: applications which set create_empty_blocks=false will not have regular block timing and should use
|
||||
// e.g. BFT timestamps rather than block height for any periodic BeginBlock logic
|
||||
type BeginBlocker func(ctx Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock
|
||||
type BeginBlocker func(ctx Context, req abci.RequestBeginBlock) (abci.ResponseBeginBlock, error)
|
||||
|
||||
// EndBlocker runs code after the transactions in a block and return updates to the validator set
|
||||
//
|
||||
// Note: applications which set create_empty_blocks=false will not have regular block timing and should use
|
||||
// e.g. BFT timestamps rather than block height for any periodic EndBlock logic
|
||||
type EndBlocker func(ctx Context, req abci.RequestEndBlock) abci.ResponseEndBlock
|
||||
type EndBlocker func(ctx Context, req abci.RequestEndBlock) (abci.ResponseEndBlock, error)
|
||||
|
||||
// PeerFilter responds to p2p filtering queries from Tendermint
|
||||
type PeerFilter func(info string) abci.ResponseQuery
|
||||
|
||||
@ -30,6 +30,7 @@ package module
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
@ -376,7 +377,7 @@ func (m *Manager) RegisterServices(cfg Configurator) {
|
||||
// InitGenesis performs init genesis functionality for modules. Exactly one
|
||||
// module must return a non-empty validator set update to correctly initialize
|
||||
// the chain.
|
||||
func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage) abci.ResponseInitChain {
|
||||
func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage) (abci.ResponseInitChain, error) {
|
||||
var validatorUpdates []abci.ValidatorUpdate
|
||||
ctx.Logger().Info("initializing blockchain state from genesis.json")
|
||||
for _, moduleName := range m.OrderInitGenesis {
|
||||
@ -391,12 +392,12 @@ func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData
|
||||
// core API genesis
|
||||
source, err := genesis.SourceFromRawJSON(genesisData[moduleName])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return abci.ResponseInitChain{}, err
|
||||
}
|
||||
|
||||
err = module.InitGenesis(ctx, source)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return abci.ResponseInitChain{}, err
|
||||
}
|
||||
} else if module, ok := mod.(HasGenesis); ok {
|
||||
ctx.Logger().Debug("running initialization for module", "module", moduleName)
|
||||
@ -406,7 +407,7 @@ func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData
|
||||
// only one module will update the validator set
|
||||
if len(moduleValUpdates) > 0 {
|
||||
if len(validatorUpdates) > 0 {
|
||||
panic("validator InitGenesis updates already set by a previous module")
|
||||
return abci.ResponseInitChain{}, errors.New("validator InitGenesis updates already set by a previous module")
|
||||
}
|
||||
validatorUpdates = moduleValUpdates
|
||||
}
|
||||
@ -420,60 +421,72 @@ func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData
|
||||
|
||||
return abci.ResponseInitChain{
|
||||
Validators: validatorUpdates,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ExportGenesis performs export genesis functionality for modules
|
||||
func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) map[string]json.RawMessage {
|
||||
func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) (map[string]json.RawMessage, error) {
|
||||
return m.ExportGenesisForModules(ctx, cdc, []string{})
|
||||
}
|
||||
|
||||
// ExportGenesisForModules performs export genesis functionality for modules
|
||||
func (m *Manager) ExportGenesisForModules(ctx sdk.Context, cdc codec.JSONCodec, modulesToExport []string) map[string]json.RawMessage {
|
||||
func (m *Manager) ExportGenesisForModules(ctx sdk.Context, cdc codec.JSONCodec, modulesToExport []string) (map[string]json.RawMessage, error) {
|
||||
if len(modulesToExport) == 0 {
|
||||
modulesToExport = m.OrderExportGenesis
|
||||
}
|
||||
// verify modules exists in app, so that we don't panic in the middle of an export
|
||||
if err := m.checkModulesExists(modulesToExport); err != nil {
|
||||
panic(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
channels := make(map[string]chan json.RawMessage)
|
||||
type genesisResult struct {
|
||||
bz json.RawMessage
|
||||
err error
|
||||
}
|
||||
|
||||
channels := make(map[string]chan genesisResult)
|
||||
for _, moduleName := range modulesToExport {
|
||||
mod := m.Modules[moduleName]
|
||||
if module, ok := mod.(appmodule.HasGenesis); ok {
|
||||
// core API genesis
|
||||
channels[moduleName] = make(chan json.RawMessage)
|
||||
go func(module appmodule.HasGenesis, ch chan json.RawMessage) {
|
||||
channels[moduleName] = make(chan genesisResult)
|
||||
go func(module appmodule.HasGenesis, ch chan genesisResult) {
|
||||
ctx := ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) // avoid race conditions
|
||||
target := genesis.RawJSONTarget{}
|
||||
err := module.ExportGenesis(ctx, target.Target())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
ch <- genesisResult{nil, err}
|
||||
return
|
||||
}
|
||||
|
||||
rawJSON, err := target.JSON()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
ch <- genesisResult{nil, err}
|
||||
return
|
||||
}
|
||||
|
||||
ch <- rawJSON
|
||||
ch <- genesisResult{rawJSON, nil}
|
||||
}(module, channels[moduleName])
|
||||
} else if module, ok := mod.(HasGenesis); ok {
|
||||
channels[moduleName] = make(chan json.RawMessage)
|
||||
go func(module HasGenesis, ch chan json.RawMessage) {
|
||||
channels[moduleName] = make(chan genesisResult)
|
||||
go func(module HasGenesis, ch chan genesisResult) {
|
||||
ctx := ctx.WithGasMeter(storetypes.NewInfiniteGasMeter()) // avoid race conditions
|
||||
ch <- module.ExportGenesis(ctx, cdc)
|
||||
ch <- genesisResult{module.ExportGenesis(ctx, cdc), nil}
|
||||
}(module, channels[moduleName])
|
||||
}
|
||||
}
|
||||
|
||||
genesisData := make(map[string]json.RawMessage)
|
||||
for moduleName := range channels {
|
||||
genesisData[moduleName] = <-channels[moduleName]
|
||||
res := <-channels[moduleName]
|
||||
if res.err != nil {
|
||||
return nil, res.err
|
||||
}
|
||||
|
||||
genesisData[moduleName] = res.bz
|
||||
}
|
||||
|
||||
return genesisData
|
||||
return genesisData, nil
|
||||
}
|
||||
|
||||
// checkModulesExists verifies that all modules in the list exist in the app
|
||||
@ -623,7 +636,7 @@ func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, fromVM Version
|
||||
// BeginBlock performs begin block functionality for all modules. It creates a
|
||||
// child context with an event manager to aggregate events emitted from all
|
||||
// modules.
|
||||
func (m *Manager) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
||||
func (m *Manager) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) (abci.ResponseBeginBlock, error) {
|
||||
ctx = ctx.WithEventManager(sdk.NewEventManager())
|
||||
|
||||
for _, moduleName := range m.OrderBeginBlockers {
|
||||
@ -635,13 +648,13 @@ func (m *Manager) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) abci.R
|
||||
|
||||
return abci.ResponseBeginBlock{
|
||||
Events: ctx.EventManager().ABCIEvents(),
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// EndBlock performs end block functionality for all modules. It creates a
|
||||
// child context with an event manager to aggregate events emitted from all
|
||||
// modules.
|
||||
func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
|
||||
func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) (abci.ResponseEndBlock, error) {
|
||||
ctx = ctx.WithEventManager(sdk.NewEventManager())
|
||||
validatorUpdates := []abci.ValidatorUpdate{}
|
||||
|
||||
@ -656,7 +669,7 @@ func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo
|
||||
// only one module will update the validator set
|
||||
if len(moduleValUpdates) > 0 {
|
||||
if len(validatorUpdates) > 0 {
|
||||
panic("validator EndBlock updates already set by a previous module")
|
||||
return abci.ResponseEndBlock{}, errors.New("validator EndBlock updates already set by a previous module")
|
||||
}
|
||||
|
||||
validatorUpdates = moduleValUpdates
|
||||
@ -666,7 +679,7 @@ func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo
|
||||
return abci.ResponseEndBlock{
|
||||
ValidatorUpdates: validatorUpdates,
|
||||
Events: ctx.EventManager().ABCIEvents(),
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetVersionMap gets consensus version from all modules
|
||||
|
||||
@ -206,7 +206,8 @@ func TestManager_InitGenesis(t *testing.T) {
|
||||
// panic because more than one module returns validator set updates
|
||||
mockAppModule1.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module1"])).Times(1).Return([]abci.ValidatorUpdate{{}})
|
||||
mockAppModule2.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module2"])).Times(1).Return([]abci.ValidatorUpdate{{}})
|
||||
require.Panics(t, func() { mm.InitGenesis(ctx, cdc, genesisData) })
|
||||
_, err := mm.InitGenesis(ctx, cdc, genesisData)
|
||||
require.Error(t, err)
|
||||
|
||||
// happy path
|
||||
mockAppModule1.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module1"])).Times(1).Return([]abci.ValidatorUpdate{{}})
|
||||
@ -242,14 +243,24 @@ func TestManager_ExportGenesis(t *testing.T) {
|
||||
}`),
|
||||
}
|
||||
|
||||
require.Equal(t, want, mm.ExportGenesis(ctx, cdc))
|
||||
require.Equal(t, want, mm.ExportGenesisForModules(ctx, cdc, []string{}))
|
||||
require.Equal(t, map[string]json.RawMessage{"module1": json.RawMessage(`{"key1": "value1"}`)}, mm.ExportGenesisForModules(ctx, cdc, []string{"module1"}))
|
||||
require.NotEqual(t, map[string]json.RawMessage{"module1": json.RawMessage(`{"key1": "value1"}`)}, mm.ExportGenesisForModules(ctx, cdc, []string{"module2"}))
|
||||
res, err := mm.ExportGenesis(ctx, cdc)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, res)
|
||||
|
||||
require.Panics(t, func() {
|
||||
mm.ExportGenesisForModules(ctx, cdc, []string{"module1", "modulefoo"})
|
||||
})
|
||||
res, err = mm.ExportGenesisForModules(ctx, cdc, []string{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, res)
|
||||
|
||||
res, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module1"})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, map[string]json.RawMessage{"module1": json.RawMessage(`{"key1": "value1"}`)}, res)
|
||||
|
||||
res, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module2"})
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, map[string]json.RawMessage{"module1": json.RawMessage(`{"key1": "value1"}`)}, res)
|
||||
|
||||
_, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module1", "modulefoo"})
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestManager_BeginBlock(t *testing.T) {
|
||||
@ -287,13 +298,15 @@ func TestManager_EndBlock(t *testing.T) {
|
||||
|
||||
mockAppModule1.EXPECT().EndBlock(gomock.Any(), gomock.Eq(req)).Times(1).Return([]abci.ValidatorUpdate{{}})
|
||||
mockAppModule2.EXPECT().EndBlock(gomock.Any(), gomock.Eq(req)).Times(1)
|
||||
ret := mm.EndBlock(sdk.Context{}, req)
|
||||
ret, err := mm.EndBlock(sdk.Context{}, req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []abci.ValidatorUpdate{{}}, ret.ValidatorUpdates)
|
||||
|
||||
// test panic
|
||||
mockAppModule1.EXPECT().EndBlock(gomock.Any(), gomock.Eq(req)).Times(1).Return([]abci.ValidatorUpdate{{}})
|
||||
mockAppModule2.EXPECT().EndBlock(gomock.Any(), gomock.Eq(req)).Times(1).Return([]abci.ValidatorUpdate{{}})
|
||||
require.Panics(t, func() { mm.EndBlock(sdk.Context{}, req) })
|
||||
_, err = mm.EndBlock(sdk.Context{}, req)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
// Core API exclusive tests
|
||||
@ -355,14 +368,24 @@ func TestCoreAPIManager_ExportGenesis(t *testing.T) {
|
||||
}`),
|
||||
}
|
||||
|
||||
require.Equal(t, want, mm.ExportGenesis(ctx, cdc))
|
||||
require.Equal(t, want, mm.ExportGenesisForModules(ctx, cdc, []string{}))
|
||||
require.Equal(t, map[string]json.RawMessage{"module1": want["module1"]}, mm.ExportGenesisForModules(ctx, cdc, []string{"module1"}))
|
||||
require.NotEqual(t, map[string]json.RawMessage{"module1": want["module1"]}, mm.ExportGenesisForModules(ctx, cdc, []string{"module2"}))
|
||||
res, err := mm.ExportGenesis(ctx, cdc)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, res)
|
||||
|
||||
require.Panics(t, func() {
|
||||
mm.ExportGenesisForModules(ctx, cdc, []string{"module1", "modulefoo"})
|
||||
})
|
||||
res, err = mm.ExportGenesisForModules(ctx, cdc, []string{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, res)
|
||||
|
||||
res, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module1"})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, map[string]json.RawMessage{"module1": want["module1"]}, res)
|
||||
|
||||
res, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module2"})
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, map[string]json.RawMessage{"module1": want["module1"]}, res)
|
||||
|
||||
_, err = mm.ExportGenesisForModules(ctx, cdc, []string{"module1", "modulefoo"})
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestCoreAPIManagerOrderSetters(t *testing.T) {
|
||||
|
||||
@ -45,9 +45,9 @@ be a matter of minutes and not even require them to be awake at that time.
|
||||
Setup an upgrade Keeper for the app and then define a BeginBlocker that calls the upgrade
|
||||
keeper's BeginBlocker method:
|
||||
|
||||
func (app *myApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock {
|
||||
func (app *myApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) (abci.ResponseBeginBlock, error) {
|
||||
app.upgradeKeeper.BeginBlocker(ctx, req)
|
||||
return abci.ResponseBeginBlock{}
|
||||
return abci.ResponseBeginBlock{}, nil
|
||||
}
|
||||
|
||||
The app must then integrate the upgrade keeper with its governance module as appropriate. The governance module
|
||||
|
||||
Loading…
Reference in New Issue
Block a user