Skip to content

Commit

Permalink
Add midblock to sei-cosmos (sei-protocol#118)
Browse files Browse the repository at this point in the history
## Describe your changes and provide context
This adds the midblock interfaces and module manager functionality to
sei-cosmos


## Testing performed to validate your change
Added unit test for module manager behavior and also tested with local
sei with sei-chain changes
  • Loading branch information
udpatil authored Dec 21, 2022
1 parent d0d03b1 commit 8520877
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 0 deletions.
18 changes: 18 additions & 0 deletions baseapp/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,24 @@ func (app *BaseApp) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) (res
return res
}

func (app *BaseApp) MidBlock(ctx sdk.Context, height int64) (events []abci.Event) {
defer telemetry.MeasureSince(time.Now(), "abci", "mid_block")

if app.midBlocker != nil {
midBlockEvents := app.midBlocker(ctx, height)
events = sdk.MarkEventsToIndex(midBlockEvents, app.indexEvents)
}
// TODO: add listener handling
// // call the streaming service hooks with the EndBlock messages
// for _, streamingListener := range app.abciListeners {
// if err := streamingListener.ListenMidBlock(app.deliverState.ctx, req, res); err != nil {
// app.logger.Error("MidBlock listening hook failed", "height", req.Height, "err", err)
// }
// }

return events
}

// EndBlock implements the ABCI interface.
func (app *BaseApp) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) (res abci.ResponseEndBlock) {
defer telemetry.MeasureSince(time.Now(), "abci", "end_block")
Expand Down
1 change: 1 addition & 0 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ type moduleRouter struct {
type abciData struct {
initChainer sdk.InitChainer // initialize state with validators and state blob
beginBlocker sdk.BeginBlocker // logic to run before any txs
midBlocker sdk.MidBlocker // logic to run after all txs, and to determine valset changes
endBlocker sdk.EndBlocker // logic to run after all txs, and to determine valset changes

// absent validators from begin block
Expand Down
8 changes: 8 additions & 0 deletions baseapp/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ func (app *BaseApp) SetBeginBlocker(beginBlocker sdk.BeginBlocker) {
app.beginBlocker = beginBlocker
}

func (app *BaseApp) SetMidBlocker(midBlocker sdk.MidBlocker) {
if app.sealed {
panic("SetMidBlocker() on sealed BaseApp")
}

app.midBlocker = midBlocker
}

func (app *BaseApp) SetEndBlocker(endBlocker sdk.EndBlocker) {
if app.sealed {
panic("SetEndBlocker() on sealed BaseApp")
Expand Down
5 changes: 5 additions & 0 deletions simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,11 @@ func (app *SimApp) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abc
return app.mm.BeginBlock(ctx, req)
}

// EndBlocker application updates every end block
func (app *SimApp) MidBlocker(ctx sdk.Context, height int64) []abci.Event {
return app.mm.MidBlock(ctx, height)
}

// EndBlocker application updates every end block
func (app *SimApp) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock {
return app.mm.EndBlock(ctx, req)
Expand Down
1 change: 1 addition & 0 deletions telemetry/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
// Common metric key constants
const (
MetricKeyBeginBlocker = "begin_blocker"
MetricKeyMidBlocker = "mid_blocker"
MetricKeyEndBlocker = "end_blocker"
MetricLabelNameModule = "module"
)
Expand Down
13 changes: 13 additions & 0 deletions tests/mocks/types_module_module.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions types/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ type InitChainer func(ctx Context, req abci.RequestInitChain) abci.ResponseInitC
// e.g. BFT timestamps rather than block height for any periodic BeginBlock logic
type BeginBlocker func(ctx Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock

// MidBlocker runs code after the early transactions in a block and return any relevant events
type MidBlocker func(ctx Context, height int64) []abci.Event

// 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
Expand Down
30 changes: 30 additions & 0 deletions types/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,11 @@ type BeginBlockAppModule interface {
BeginBlock(sdk.Context, abci.RequestBeginBlock)
}

type MidBlockAppModule interface {
AppModule
MidBlock(sdk.Context, int64)
}

// EndBlockAppModule is an extension interface that contains information about the AppModule and EndBlock.
type EndBlockAppModule interface {
AppModule
Expand Down Expand Up @@ -237,6 +242,7 @@ type Manager struct {
OrderInitGenesis []string
OrderExportGenesis []string
OrderBeginBlockers []string
OrderMidBlockers []string
OrderEndBlockers []string
OrderMigrations []string
}
Expand Down Expand Up @@ -278,6 +284,13 @@ func (m *Manager) SetOrderBeginBlockers(moduleNames ...string) {
m.OrderBeginBlockers = moduleNames
}

// SetOrderMidBlockers sets the order of set mid-blocker calls
func (m *Manager) SetOrderMidBlockers(moduleNames ...string) {
// TODO: do we need this assertion? maybe its ok to not have it to only have some modules have MidBlock implementations
// m.assertNoForgottenModules("SetOrderMidBlockers", moduleNames)
m.OrderMidBlockers = moduleNames
}

// SetOrderEndBlockers sets the order of set end-blocker calls
func (m *Manager) SetOrderEndBlockers(moduleNames ...string) {
m.assertNoForgottenModules("SetOrderEndBlockers", moduleNames)
Expand Down Expand Up @@ -498,6 +511,23 @@ func (m *Manager) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) abci.R
}
}

// 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) MidBlock(ctx sdk.Context, height int64) []abci.Event {
ctx = ctx.WithEventManager(sdk.NewEventManager())

for _, moduleName := range m.OrderMidBlockers {
module, ok := m.Modules[moduleName].(MidBlockAppModule)
if !ok {
continue
}
module.MidBlock(ctx, height)
}

return ctx.EventManager().ABCIEvents()
}

// EndBlock performs end block functionality for all modules. It creates a
// child context with an event manager to aggregate events emitted from all
// modules.
Expand Down
25 changes: 25 additions & 0 deletions types/module/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ func TestManagerOrderSetters(t *testing.T) {
mm.SetOrderBeginBlockers("module2", "module1")
require.Equal(t, []string{"module2", "module1"}, mm.OrderBeginBlockers)

// we expect none of the modules to be included by default
require.Empty(t, mm.OrderMidBlockers)
mm.SetOrderMidBlockers("module2", "module1")
require.Equal(t, []string{"module2", "module1"}, mm.OrderMidBlockers)

require.Equal(t, []string{"module1", "module2"}, mm.OrderEndBlockers)
mm.SetOrderEndBlockers("module2", "module1")
require.Equal(t, []string{"module2", "module1"}, mm.OrderEndBlockers)
Expand Down Expand Up @@ -258,6 +263,26 @@ func TestManager_BeginBlock(t *testing.T) {
mm.BeginBlock(sdk.Context{}, req)
}

func TestManager_MidBlock(t *testing.T) {
mockCtrl := gomock.NewController(t)
t.Cleanup(mockCtrl.Finish)

mockAppModule1 := mocks.NewMockAppModule(mockCtrl)
mockAppModule2 := mocks.NewMockAppModule(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))
mm.SetOrderMidBlockers("module2", "module1")

height := int64(10)

mockAppModule1.EXPECT().MidBlock(gomock.Any(), gomock.Eq(height)).Times(1)
mockAppModule2.EXPECT().MidBlock(gomock.Any(), gomock.Eq(height)).Times(1)
mm.MidBlock(sdk.Context{}, height)
}

func TestManager_EndBlock(t *testing.T) {
mockCtrl := gomock.NewController(t)
t.Cleanup(mockCtrl.Finish)
Expand Down

0 comments on commit 8520877

Please sign in to comment.