feat: Add PrepareCheckState and Precommit callbacks (#14860)
Co-authored-by: dydxwill <119354122+dydxwill@users.noreply.github.com>
This commit is contained in:
@@ -19,6 +19,13 @@ type BeginBlocker func(ctx Context, req abci.RequestBeginBlock) (abci.ResponseBe
|
||||
// e.g. BFT timestamps rather than block height for any periodic EndBlock logic
|
||||
type EndBlocker func(ctx Context, req abci.RequestEndBlock) (abci.ResponseEndBlock, error)
|
||||
|
||||
// PrepareCheckStater runs code during commit after the block has been committed, and the `checkState`
|
||||
// has been branched for the new block.
|
||||
type PrepareCheckStater func(ctx Context)
|
||||
|
||||
// Precommiter runs code during commit immediately before the `deliverState` is written to the `rootMultiStore`.
|
||||
type Precommiter func(ctx Context)
|
||||
|
||||
// PeerFilter responds to p2p filtering queries from Tendermint
|
||||
type PeerFilter func(info string) abci.ResponseQuery
|
||||
|
||||
|
||||
+79
-16
@@ -213,6 +213,19 @@ type EndBlockAppModule interface {
|
||||
EndBlock(sdk.Context, abci.RequestEndBlock) []abci.ValidatorUpdate
|
||||
}
|
||||
|
||||
// PrepareCheckStateAppModule is an extension interface that contains information about the AppModule
|
||||
// and PrepareCheckState.
|
||||
type PrepareCheckStateAppModule interface {
|
||||
AppModule
|
||||
PrepareCheckState(sdk.Context)
|
||||
}
|
||||
|
||||
// PreommitAppModule is an extension interface that contains information about the AppModule and Precommit.
|
||||
type PrecommitAppModule interface {
|
||||
AppModule
|
||||
Precommit(sdk.Context)
|
||||
}
|
||||
|
||||
type HasABCIEndblock interface {
|
||||
AppModule
|
||||
EndBlock(context.Context) ([]abci.ValidatorUpdate, error)
|
||||
@@ -259,12 +272,14 @@ func (GenesisOnlyAppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []ab
|
||||
// Manager defines a module manager that provides the high level utility for managing and executing
|
||||
// operations for a group of modules
|
||||
type Manager struct {
|
||||
Modules map[string]interface{} // interface{} is used now to support the legacy AppModule as well as new core appmodule.AppModule.
|
||||
OrderInitGenesis []string
|
||||
OrderExportGenesis []string
|
||||
OrderBeginBlockers []string
|
||||
OrderEndBlockers []string
|
||||
OrderMigrations []string
|
||||
Modules map[string]interface{} // interface{} is used now to support the legacy AppModule as well as new core appmodule.AppModule.
|
||||
OrderInitGenesis []string
|
||||
OrderExportGenesis []string
|
||||
OrderBeginBlockers []string
|
||||
OrderEndBlockers []string
|
||||
OrderPrepareCheckStaters []string
|
||||
OrderPrecommiters []string
|
||||
OrderMigrations []string
|
||||
}
|
||||
|
||||
// NewManager creates a new Manager object.
|
||||
@@ -277,11 +292,13 @@ func NewManager(modules ...AppModule) *Manager {
|
||||
}
|
||||
|
||||
return &Manager{
|
||||
Modules: moduleMap,
|
||||
OrderInitGenesis: modulesStr,
|
||||
OrderExportGenesis: modulesStr,
|
||||
OrderBeginBlockers: modulesStr,
|
||||
OrderEndBlockers: modulesStr,
|
||||
Modules: moduleMap,
|
||||
OrderInitGenesis: modulesStr,
|
||||
OrderExportGenesis: modulesStr,
|
||||
OrderBeginBlockers: modulesStr,
|
||||
OrderPrepareCheckStaters: modulesStr,
|
||||
OrderPrecommiters: modulesStr,
|
||||
OrderEndBlockers: modulesStr,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,11 +316,13 @@ func NewManagerFromMap(moduleMap map[string]appmodule.AppModule) *Manager {
|
||||
sort.Strings(modulesStr)
|
||||
|
||||
return &Manager{
|
||||
Modules: simpleModuleMap,
|
||||
OrderInitGenesis: modulesStr,
|
||||
OrderExportGenesis: modulesStr,
|
||||
OrderBeginBlockers: modulesStr,
|
||||
OrderEndBlockers: modulesStr,
|
||||
Modules: simpleModuleMap,
|
||||
OrderInitGenesis: modulesStr,
|
||||
OrderExportGenesis: modulesStr,
|
||||
OrderBeginBlockers: modulesStr,
|
||||
OrderEndBlockers: modulesStr,
|
||||
OrderPrecommiters: modulesStr,
|
||||
OrderPrepareCheckStaters: modulesStr,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,6 +376,28 @@ func (m *Manager) SetOrderEndBlockers(moduleNames ...string) {
|
||||
m.OrderEndBlockers = moduleNames
|
||||
}
|
||||
|
||||
// SetOrderPrepareCheckStaters sets the order of set prepare-check-stater calls
|
||||
func (m *Manager) SetOrderPrepareCheckStaters(moduleNames ...string) {
|
||||
m.assertNoForgottenModules("SetOrderPrepareCheckStaters", moduleNames,
|
||||
func(moduleName string) bool {
|
||||
module := m.Modules[moduleName]
|
||||
_, hasPrepareCheckState := module.(PrepareCheckStateAppModule)
|
||||
return !hasPrepareCheckState
|
||||
})
|
||||
m.OrderPrepareCheckStaters = moduleNames
|
||||
}
|
||||
|
||||
// SetOrderPrecommiters sets the order of set precommiter calls
|
||||
func (m *Manager) SetOrderPrecommiters(moduleNames ...string) {
|
||||
m.assertNoForgottenModules("SetOrderPrecommiters", moduleNames,
|
||||
func(moduleName string) bool {
|
||||
module := m.Modules[moduleName]
|
||||
_, hasPrecommit := module.(PrecommitAppModule)
|
||||
return !hasPrecommit
|
||||
})
|
||||
m.OrderPrecommiters = moduleNames
|
||||
}
|
||||
|
||||
// SetOrderMigrations sets the order of migrations to be run. If not set
|
||||
// then migrations will be run with an order defined in `DefaultMigrationsOrder`.
|
||||
func (m *Manager) SetOrderMigrations(moduleNames ...string) {
|
||||
@@ -728,6 +769,28 @@ func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) (abci.Resp
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Precommit performs precommit functionality for all modules.
|
||||
func (m *Manager) Precommit(ctx sdk.Context) {
|
||||
for _, moduleName := range m.OrderPrecommiters {
|
||||
module, ok := m.Modules[moduleName].(PrecommitAppModule)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
module.Precommit(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// PrepareCheckState performs functionality for preparing the check state for all modules.
|
||||
func (m *Manager) PrepareCheckState(ctx sdk.Context) {
|
||||
for _, moduleName := range m.OrderPrepareCheckStaters {
|
||||
module, ok := m.Modules[moduleName].(PrepareCheckStateAppModule)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
module.PrepareCheckState(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
// GetVersionMap gets consensus version from all modules
|
||||
func (m *Manager) GetVersionMap() VersionMap {
|
||||
vermap := make(VersionMap)
|
||||
|
||||
@@ -100,6 +100,60 @@ func TestGenesisOnlyAppModule(t *testing.T) {
|
||||
goam.RegisterInvariants(mockInvariantRegistry)
|
||||
}
|
||||
|
||||
func TestAssertNoForgottenModules(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
t.Cleanup(mockCtrl.Finish)
|
||||
mockAppModule1 := mock.NewMockEndBlockAppModule(mockCtrl)
|
||||
mockAppModule2 := mock.NewMockBeginBlockAppModule(mockCtrl)
|
||||
mockAppModule3 := mock.NewMockCoreAppModule(mockCtrl)
|
||||
mockAppModule4 := mock.NewMockPrecommitAppModule(mockCtrl)
|
||||
mockAppModule5 := mock.NewMockPrepareCheckStateAppModule(mockCtrl)
|
||||
|
||||
mockAppModule1.EXPECT().Name().Times(2).Return("module1")
|
||||
mockAppModule2.EXPECT().Name().Times(2).Return("module2")
|
||||
mockAppModule4.EXPECT().Name().Times(2).Return("module4")
|
||||
mockAppModule5.EXPECT().Name().Times(2).Return("module5")
|
||||
mm := module.NewManager(
|
||||
mockAppModule1,
|
||||
mockAppModule2,
|
||||
module.CoreAppModuleBasicAdaptor("module3", mockAppModule3),
|
||||
mockAppModule4,
|
||||
mockAppModule5,
|
||||
)
|
||||
require.NotNil(t, mm)
|
||||
require.Equal(t, 5, len(mm.Modules))
|
||||
|
||||
require.Equal(t, []string{"module1", "module2", "module3", "module4", "module5"}, mm.OrderInitGenesis)
|
||||
require.PanicsWithValue(t, "all modules must be defined when setting SetOrderInitGenesis, missing: [module3]", func() {
|
||||
mm.SetOrderInitGenesis("module2", "module1")
|
||||
})
|
||||
|
||||
require.Equal(t, []string{"module1", "module2", "module3", "module4", "module5"}, mm.OrderExportGenesis)
|
||||
require.PanicsWithValue(t, "all modules must be defined when setting SetOrderExportGenesis, missing: [module3]", func() {
|
||||
mm.SetOrderExportGenesis("module2", "module1")
|
||||
})
|
||||
|
||||
require.Equal(t, []string{"module1", "module2", "module3", "module4", "module5"}, mm.OrderBeginBlockers)
|
||||
require.PanicsWithValue(t, "all modules must be defined when setting SetOrderBeginBlockers, missing: [module2]", func() {
|
||||
mm.SetOrderBeginBlockers("module1", "module3")
|
||||
})
|
||||
|
||||
require.Equal(t, []string{"module1", "module2", "module3", "module4", "module5"}, mm.OrderEndBlockers)
|
||||
require.PanicsWithValue(t, "all modules must be defined when setting SetOrderEndBlockers, missing: [module1]", func() {
|
||||
mm.SetOrderEndBlockers("module2", "module3")
|
||||
})
|
||||
|
||||
require.Equal(t, []string{"module1", "module2", "module3", "module4", "module5"}, mm.OrderPrecommiters)
|
||||
require.PanicsWithValue(t, "all modules must be defined when setting SetOrderPrecommiters, missing: [module4]", func() {
|
||||
mm.SetOrderPrecommiters("module2", "module1")
|
||||
})
|
||||
|
||||
require.Equal(t, []string{"module1", "module2", "module3", "module4", "module5"}, mm.OrderPrepareCheckStaters)
|
||||
require.PanicsWithValue(t, "all modules must be defined when setting SetOrderPrepareCheckStaters, missing: [module5]", func() {
|
||||
mm.SetOrderPrepareCheckStaters("module2", "module1")
|
||||
})
|
||||
}
|
||||
|
||||
func TestManagerOrderSetters(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
t.Cleanup(mockCtrl.Finish)
|
||||
@@ -128,6 +182,14 @@ func TestManagerOrderSetters(t *testing.T) {
|
||||
require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderEndBlockers)
|
||||
mm.SetOrderEndBlockers("module2", "module1", "module3")
|
||||
require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderEndBlockers)
|
||||
|
||||
require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderPrepareCheckStaters)
|
||||
mm.SetOrderPrepareCheckStaters("module3", "module2", "module1")
|
||||
require.Equal(t, []string{"module3", "module2", "module1"}, mm.OrderPrepareCheckStaters)
|
||||
|
||||
require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderPrecommiters)
|
||||
mm.SetOrderPrecommiters("module3", "module2", "module1")
|
||||
require.Equal(t, []string{"module3", "module2", "module1"}, mm.OrderPrecommiters)
|
||||
}
|
||||
|
||||
func TestManager_RegisterInvariants(t *testing.T) {
|
||||
@@ -319,6 +381,40 @@ func TestManager_EndBlock(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestManager_PrepareCheckState(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
t.Cleanup(mockCtrl.Finish)
|
||||
|
||||
mockAppModule1 := mock.NewMockPrepareCheckStateAppModule(mockCtrl)
|
||||
mockAppModule2 := mock.NewMockPrepareCheckStateAppModule(mockCtrl)
|
||||
mockAppModule1.EXPECT().Name().Times(2).Return("module1")
|
||||
mockAppModule2.EXPECT().Name().Times(2).Return("module2")
|
||||
mm := module.NewManager(mockAppModule1, mockAppModule2)
|
||||
require.NotNil(t, mm)
|
||||
require.Equal(t, 2, len(mm.Modules))
|
||||
|
||||
mockAppModule1.EXPECT().PrepareCheckState(gomock.Any()).Times(1)
|
||||
mockAppModule2.EXPECT().PrepareCheckState(gomock.Any()).Times(1)
|
||||
mm.PrepareCheckState(sdk.Context{})
|
||||
}
|
||||
|
||||
func TestManager_Precommit(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
t.Cleanup(mockCtrl.Finish)
|
||||
|
||||
mockAppModule1 := mock.NewMockPrecommitAppModule(mockCtrl)
|
||||
mockAppModule2 := mock.NewMockPrecommitAppModule(mockCtrl)
|
||||
mockAppModule1.EXPECT().Name().Times(2).Return("module1")
|
||||
mockAppModule2.EXPECT().Name().Times(2).Return("module2")
|
||||
mm := module.NewManager(mockAppModule1, mockAppModule2)
|
||||
require.NotNil(t, mm)
|
||||
require.Equal(t, 2, len(mm.Modules))
|
||||
|
||||
mockAppModule1.EXPECT().Precommit(gomock.Any()).Times(1)
|
||||
mockAppModule2.EXPECT().Precommit(gomock.Any()).Times(1)
|
||||
mm.Precommit(sdk.Context{})
|
||||
}
|
||||
|
||||
// Core API exclusive tests
|
||||
func TestCoreAPIManager(t *testing.T) {
|
||||
mockCtrl := gomock.NewController(t)
|
||||
@@ -431,6 +527,14 @@ func TestCoreAPIManagerOrderSetters(t *testing.T) {
|
||||
require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderEndBlockers)
|
||||
mm.SetOrderEndBlockers("module2", "module1", "module3")
|
||||
require.Equal(t, []string{"module2", "module1", "module3"}, mm.OrderEndBlockers)
|
||||
|
||||
require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderPrepareCheckStaters)
|
||||
mm.SetOrderPrepareCheckStaters("module3", "module2", "module1")
|
||||
require.Equal(t, []string{"module3", "module2", "module1"}, mm.OrderPrepareCheckStaters)
|
||||
|
||||
require.Equal(t, []string{"module1", "module2", "module3"}, mm.OrderPrecommiters)
|
||||
mm.SetOrderPrecommiters("module3", "module2", "module1")
|
||||
require.Equal(t, []string{"module3", "module2", "module1"}, mm.OrderPrecommiters)
|
||||
}
|
||||
|
||||
func TestCoreAPIManager_BeginBlock(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user