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

add precommit callback #7

Merged
merged 2 commits into from
Feb 23, 2023
Merged
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions baseapp/abci.go
Original file line number Diff line number Diff line change
@@ -396,6 +396,10 @@ func (app *BaseApp) Commit() abci.ResponseCommit {
app.setPrepareProposalState(header)
app.setProcessProposalState(header)

if app.precommiter != nil {
app.precommiter(app.deliverState.ctx)
}

// empty/reset the deliver state
app.deliverState = nil

21 changes: 21 additions & 0 deletions baseapp/abci_test.go
Original file line number Diff line number Diff line change
@@ -153,6 +153,27 @@ func TestCommiterCalledWithCheckState(t *testing.T) {
require.Equal(t, true, wasCommiterCalled)
}

// Verifies that the Precommiter is called with the deliverState.
func TestPrecommiterCalledWithDeliverState(t *testing.T) {
t.Parallel()

logger := defaultLogger()
db := dbm.NewMemDB()
name := t.Name()
app := NewBaseApp(name, logger, db, nil)

wasPrecommiterCalled := false
app.precommiter = func(ctx sdk.Context) {
require.Equal(t, app.deliverState.ctx, ctx)
wasPrecommiterCalled = true
}

app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{Height: 1}})
app.Commit()

require.Equal(t, true, wasPrecommiterCalled)
}

// Test and ensure that invalid block heights always cause errors.
// See issues:
// - https://github.com/cosmos/cosmos-sdk/issues/11220
1 change: 1 addition & 0 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
@@ -70,6 +70,7 @@ type BaseApp struct { //nolint: maligned
prepareProposal sdk.PrepareProposalHandler // the handler which runs on ABCI PrepareProposal
endBlocker sdk.EndBlocker // logic to run after all txs, and to determine valset changes
commiter sdk.Commiter // logic to run during commit
precommiter sdk.Precommiter // logic to run during commit using the deliverState
addrPeerFilter sdk.PeerFilter // filter peers by address and port
idPeerFilter sdk.PeerFilter // filter peers by node ID
fauxMerkleMode bool // if true, IAVL MountStores uses MountStoresDB for simulation speed.
30 changes: 30 additions & 0 deletions baseapp/deliver_tx_test.go
Original file line number Diff line number Diff line change
@@ -420,6 +420,9 @@ func TestBaseAppOptionSeal(t *testing.T) {
require.Panics(t, func() {
app.SetCommiter(nil)
})
require.Panics(t, func() {
app.SetPrecommiter(nil)
})
require.Panics(t, func() {
app.SetAnteHandler(nil)
})
@@ -1032,6 +1035,33 @@ func TestBaseApp_Commit(t *testing.T) {
require.Equal(t, true, wasCommiterCalled)
}

func TestBaseApp_Precommit(t *testing.T) {
db := dbm.NewMemDB()
name := t.Name()
logger := defaultLogger()

cp := &tmproto.ConsensusParams{
Block: &tmproto.BlockParams{
MaxGas: 5000000,
},
}

app := baseapp.NewBaseApp(name, logger, db, nil)
app.SetParamStore(&paramStore{db: dbm.NewMemDB()})
app.InitChain(abci.RequestInitChain{
ConsensusParams: cp,
})

wasPrecommiterCalled := false
app.SetPrecommiter(func(ctx sdk.Context) {
wasPrecommiterCalled = true
})
app.Seal()

app.Commit()
require.Equal(t, true, wasPrecommiterCalled)
}

// Test that txs can be unmarshalled and read and that
// correct error codes are returned when not
func TestTxDecoder(t *testing.T) {
8 changes: 8 additions & 0 deletions baseapp/options.go
Original file line number Diff line number Diff line change
@@ -164,6 +164,14 @@ func (app *BaseApp) SetCommiter(commiter sdk.Commiter) {
app.commiter = commiter
}

func (app *BaseApp) SetPrecommiter(precommiter sdk.Precommiter) {
if app.sealed {
panic("SetPrecommiter() on sealed BaseApp")
}

app.precommiter = precommiter
}

func (app *BaseApp) SetAnteHandler(ah sdk.AnteHandler) {
if app.sealed {
panic("SetAnteHandler() on sealed BaseApp")
141 changes: 141 additions & 0 deletions testutil/mock/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
@@ -23,6 +23,9 @@ type EndBlocker func(ctx Context, req abci.RequestEndBlock) abci.ResponseEndBloc
// branched for the new block.
type Commiter func(ctx Context)

// Precommiter runs code during commit before the `deliverState` is reset.
type Precommiter func(ctx Context)

// PeerFilter responds to p2p filtering queries from Tendermint
type PeerFilter func(info string) abci.ResponseQuery

24 changes: 24 additions & 0 deletions types/module/module.go
Original file line number Diff line number Diff line change
@@ -211,6 +211,12 @@ type CommitAppModule interface {
Commit(sdk.Context)
}

// PreommitAppModule is an extension interface that contains information about the AppModule and Precommit.
type PrecommitAppModule interface {
AppModule
Precommit(sdk.Context)
}

// GenesisOnlyAppModule is an AppModule that only has import/export functionality
type GenesisOnlyAppModule struct {
AppModuleGenesis
@@ -258,6 +264,7 @@ type Manager struct {
OrderBeginBlockers []string
OrderEndBlockers []string
OrderCommiters []string
OrderPrecommiters []string
OrderMigrations []string
}

@@ -276,6 +283,7 @@ func NewManager(modules ...AppModule) *Manager {
OrderExportGenesis: modulesStr,
OrderBeginBlockers: modulesStr,
OrderCommiters: modulesStr,
OrderPrecommiters: modulesStr,
OrderEndBlockers: modulesStr,
}
}
@@ -322,6 +330,11 @@ func (m *Manager) SetOrderCommiters(moduleNames ...string) {
m.OrderCommiters = moduleNames
}

// SetOrderPrecommiters sets the order of set precommiter calls
func (m *Manager) SetOrderPrecommiters(moduleNames ...string) {
m.OrderPrecommiters = moduleNames
}

// SetOrderEndBlockers sets the order of set end-blocker calls
func (m *Manager) SetOrderEndBlockers(moduleNames ...string) {
m.assertNoForgottenModules("SetOrderEndBlockers", moduleNames)
@@ -623,6 +636,17 @@ func (m *Manager) Commit(ctx sdk.Context) {
}
}

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

// GetVersionMap gets consensus version from all modules
func (m *Manager) GetVersionMap() VersionMap {
vermap := make(VersionMap)
21 changes: 21 additions & 0 deletions types/module/module_test.go
Original file line number Diff line number Diff line change
@@ -105,6 +105,10 @@ func TestManagerOrderSetters(t *testing.T) {
require.Equal(t, []string{"module1", "module2"}, mm.OrderCommiters)
mm.SetOrderCommiters("module2", "module1")
require.Equal(t, []string{"module2", "module1"}, mm.OrderCommiters)

require.Equal(t, []string{"module1", "module2"}, mm.OrderPrecommiters)
mm.SetOrderPrecommiters("module2", "module1")
require.Equal(t, []string{"module2", "module1"}, mm.OrderPrecommiters)
}

func TestManager_RegisterInvariants(t *testing.T) {
@@ -270,3 +274,20 @@ func TestManager_Commit(t *testing.T) {
mockAppModule2.EXPECT().Commit(gomock.Any()).Times(1)
mm.Commit(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{})
}