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

refactor(core)!: clean-up core and simplify preblock #19672

Merged
merged 9 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
16 changes: 6 additions & 10 deletions baseapp/abci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2041,11 +2041,9 @@ func TestBaseApp_PreBlocker(t *testing.T) {
require.NoError(t, err)

wasHookCalled := false
app.SetPreBlocker(func(ctx sdk.Context, req *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
app.SetPreBlocker(func(ctx sdk.Context, req *abci.RequestFinalizeBlock) error {
wasHookCalled = true
return &sdk.ResponsePreBlock{
ConsensusParamsChanged: true,
}, nil
return nil
})
app.Seal()

Expand All @@ -2058,8 +2056,8 @@ func TestBaseApp_PreBlocker(t *testing.T) {
_, err = app.InitChain(&abci.RequestInitChain{})
require.NoError(t, err)

app.SetPreBlocker(func(ctx sdk.Context, req *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
return nil, errors.New("some error")
app.SetPreBlocker(func(ctx sdk.Context, req *abci.RequestFinalizeBlock) error {
return errors.New("some error")
})
app.Seal()

Expand Down Expand Up @@ -2148,7 +2146,7 @@ func TestBaseApp_VoteExtensions(t *testing.T) {
return &abci.ResponseProcessProposal{Status: abci.ResponseProcessProposal_ACCEPT}, nil
})

app.SetPreBlocker(func(ctx sdk.Context, req *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
app.SetPreBlocker(func(ctx sdk.Context, req *abci.RequestFinalizeBlock) error {
count := uint64(0)
pricesSum := uint64(0)
for _, v := range req.Txs {
Expand All @@ -2167,9 +2165,7 @@ func TestBaseApp_VoteExtensions(t *testing.T) {
ctx.KVStore(capKey1).Set([]byte("avgPrice"), buf)
}

return &sdk.ResponsePreBlock{
ConsensusParamsChanged: true,
}, nil
return nil
})
}

Expand Down
17 changes: 7 additions & 10 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -706,19 +706,16 @@ func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) (sdk.Context
func (app *BaseApp) preBlock(req *abci.RequestFinalizeBlock) error {
if app.preBlocker != nil {
ctx := app.finalizeBlockState.Context()
rsp, err := app.preBlocker(ctx, req)
if err != nil {
if err := app.preBlocker(ctx, req); err != nil {
return err
}
// rsp.ConsensusParamsChanged is true from preBlocker means ConsensusParams in store get changed
// ConsensusParams can change in preblocker, so we need to
// write the consensus parameters in store to context
if rsp.ConsensusParamsChanged {
Copy link
Member

Choose a reason for hiding this comment

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

I like this being removed 👍

ctx = ctx.WithConsensusParams(app.GetConsensusParams(ctx))
// GasMeter must be set after we get a context with updated consensus params.
gasMeter := app.getBlockGasMeter(ctx)
ctx = ctx.WithBlockGasMeter(gasMeter)
app.finalizeBlockState.SetContext(ctx)
}
ctx = ctx.WithConsensusParams(app.GetConsensusParams(ctx))
// GasMeter must be set after we get a context with updated consensus params.
gasMeter := app.getBlockGasMeter(ctx)
ctx = ctx.WithBlockGasMeter(gasMeter)
app.finalizeBlockState.SetContext(ctx)
}
return nil
}
Expand Down
3 changes: 1 addition & 2 deletions core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
* Add `MsgHandler` as an alternative to grpc handlers
* Provide separate `MigrationRegistrar` instead of grouping with `RegisterServices`

### Improvements

### API Breaking Changes

* [#19672](https://github.com/cosmos/cosmos-sdk/pull/19672) `PreBlock` now returns only an error for consistency with server/v2. The SDK has upgraded x/upgrade accordingly.
* [#18857](https://github.com/cosmos/cosmos-sdk/pull/18857) Moved `FormatCoins` to `x/tx`.
Copy link
Contributor

Choose a reason for hiding this comment

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

The URL for PR #18861 contains a typo: httpes://github.com/cosmos/cosmos-sdk/pull/18861. It should be https://.

- * [#18861](httpes://github.com/cosmos/cosmos-sdk/pull/18861) Moved `coin.ParseCoin` to `client/v2/internal`.
+ * [#18861](https://github.com/cosmos/cosmos-sdk/pull/18861) Moved `coin.ParseCoin` to `client/v2/internal`.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
* [#18857](https://github.com/cosmos/cosmos-sdk/pull/18857) Moved `FormatCoins` to `x/tx`.
* [#18857](https://github.com/cosmos/cosmos-sdk/pull/18857) Moved `FormatCoins` to `x/tx`.
* [#18861](https://github.com/cosmos/cosmos-sdk/pull/18861) Moved `coin.ParseCoin` to `client/v2/internal`.

* [#18861](httpes://github.com/cosmos/cosmos-sdk/pull/18861) Moved `coin.ParseCoin` to `client/v2/internal`.
* [#18866](https://github.com/cosmos/cosmos-sdk/pull/18866) All items related to depinject have been moved to `cosmossdk.io/depinject` (`Provide`, `Invoke`, `Register`)
Comment on lines 54 to 62
Copy link
Contributor

Choose a reason for hiding this comment

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

📝 NOTE
This review was outside the diff hunks, and no overlapping diff hunk was found. Original lines [42-42]

There's a missing space after the period in the entry for PR #18457. This is a minor formatting issue but important for readability.

- * [#18457](https://github.com/cosmos/cosmos-sdk/pull/18457) Add branch.ExecuteWithGasLimit.
+ * [#18457](https://github.com/cosmos/cosmos-sdk/pull/18457) Add branch.ExecuteWithGasLimit. 

Expand Down
27 changes: 14 additions & 13 deletions core/appmodule/migrations.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package appmodule

import "context"
import (
"cosmossdk.io/core/appmodule/v2"
)

type MigrationRegistrar interface {
// Register registers an in-place store migration for a module. The
// handler is a migration script to perform in-place migrations from version
// `fromVersion` to version `fromVersion+1`.
//
// EACH TIME a module's ConsensusVersion increments, a new migration MUST
// be registered using this function. If a migration handler is missing for
// a particular function, the upgrade logic (see RunMigrations function)
// will panic. If the ConsensusVersion bump does not introduce any store
// changes, then a no-op function must be registered here.
Register(moduleName string, fromVersion uint64, handler func(context.Context) error) error
}
// HasConsensusVersion is the interface for declaring a module consensus version.
type HasConsensusVersion = appmodule.HasConsensusVersion

// HasMigrations is implemented by a module which upgrades or has upgraded to a new consensus version.
type HasMigrations = appmodule.HasMigrations

// MigrationRegistrar is the interface for registering in-place store migrations.
type MigrationRegistrar = appmodule.MigrationRegistrar

// MigrationHandler is the migration function that each module registers.
type MigrationHandler = appmodule.MigrationHandler
65 changes: 14 additions & 51 deletions core/appmodule/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"

"google.golang.org/grpc"
"google.golang.org/protobuf/runtime/protoiface"

"cosmossdk.io/core/appmodule/v2"
)
Expand All @@ -15,16 +14,22 @@ import (
// by other modules (usually via depinject) as app modules.
type AppModule = appmodule.AppModule

// HasMigrations is the extension interface that modules should implement to register migrations.
type HasMigrations interface {
AppModule
// HasPreBlocker is the extension interface that modules should implement to run
// custom logic before BeginBlock.
// It can modify consensus parameters in storage and signal the caller through the return value.
Copy link
Member

Choose a reason for hiding this comment

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

// It can modify consensus parameters in storage and signal the caller through the return value.

This is not like this anymore, should be removed right?

// The new context (ctx) must be passed to all the other lifecycle methods.
type HasPreBlocker = appmodule.HasPreBlocker

// RegisterMigrations registers the module's migrations with the app's migrator.
RegisterMigrations(MigrationRegistrar) error
}
// HasBeginBlocker is the extension interface that modules should implement to run
// custom logic before transaction processing in a block.
type HasBeginBlocker = appmodule.HasBeginBlocker

// HasEndBlocker is the extension interface that modules should implement to run
// custom logic after transaction processing in a block.
type HasEndBlocker = appmodule.HasEndBlocker
Copy link
Contributor

Choose a reason for hiding this comment

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

The removal of the HasMigrations interface and the addition of HasBeginBlocker and HasEndBlocker interfaces are significant changes that enhance the modularity and clarity of the module's functionality. These changes align with the PR's objective of simplifying and cleaning up the core components. However, ensure that the removal of HasMigrations does not impact modules that might rely on this interface for migration logic.


// HasConsensusVersion is the interface for declaring a module consensus version.
type HasConsensusVersion = appmodule.HasConsensusVersion
// HasRegisterInterfaces is the interface for modules to register their msg types.
type HasRegisterInterfaces = appmodule.HasRegisterInterfaces

// HasServices is the extension interface that modules should implement to register
// implementations of services defined in .proto files.
Expand All @@ -46,48 +51,6 @@ type HasServices interface {
RegisterServices(grpc.ServiceRegistrar) error
}

// ResponsePreBlock represents the response from the PreBlock method.
// It can modify consensus parameters in storage and signal the caller through the return value.
// When it returns ConsensusParamsChanged=true, the caller must refresh the consensus parameter in the finalize context.
// The new context (ctx) must be passed to all the other lifecycle methods.
type ResponsePreBlock interface {
IsConsensusParamsChanged() bool
}

// HasPreBlocker is the extension interface that modules should implement to run
// custom logic before BeginBlock.
type HasPreBlocker interface {
appmodule.AppModule
// PreBlock is method that will be run before BeginBlock.
PreBlock(context.Context) (ResponsePreBlock, error)
}

// HasBeginBlocker is the extension interface that modules should implement to run
// custom logic before transaction processing in a block.
type HasBeginBlocker = appmodule.HasBeginBlocker

// HasEndBlocker is the extension interface that modules should implement to run
// custom logic after transaction processing in a block.
type HasEndBlocker = appmodule.HasEndBlocker

// HasRegisterInterfaces is the interface for modules to register their msg types.
type HasRegisterInterfaces = appmodule.HasRegisterInterfaces

// MsgHandlerRouter is implemented by the runtime provider.
type MsgHandlerRouter interface {
// RegisterHandler is called by modules to register msg handler functions.
RegisterHandler(name string, handler func(ctx context.Context, msg protoiface.MessageV1) (msgResp protoiface.MessageV1, err error))
}

// HasMsgHandler is implemented by modules that instead of exposing msg server expose
// a set of handlers.
type HasMsgHandler interface {
// RegisterMsgHandlers is implemented by the module that will register msg handlers.
RegisterMsgHandlers(router MsgHandlerRouter)
}

// ---------------------------------------------------------------------------- //

// HasPrepareCheckState is an extension interface that contains information about the AppModule
// and PrepareCheckState.
type HasPrepareCheckState interface {
Expand Down
4 changes: 2 additions & 2 deletions core/appmodule/v2/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ type HasConsensusVersion interface {
ConsensusVersion() uint64
}

// HasMigrations is implemented by a module which upgrades or has upgraded
// to a new consensus version.
// HasMigrations is implemented by a module which upgrades or has upgraded to a new consensus version.
type HasMigrations interface {
AppModule
HasConsensusVersion
Expand All @@ -21,6 +20,7 @@ type HasMigrations interface {
RegisterMigrations(MigrationRegistrar) error
}

// MigrationRegistrar is the interface for registering in-place store migrations.
type MigrationRegistrar interface {
// Register registers an in-place store migration for a module. The
// handler is a migration script to perform in-place migrations from version
Expand Down
10 changes: 10 additions & 0 deletions core/appmodule/v2/appmodule.go → core/appmodule/v2/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ type AppModule interface {
IsOnePerModuleType()
}

// HasPreBlocker is the extension interface that modules should implement to run
// custom logic before BeginBlock.
// It can modify consensus parameters in storage and signal the caller through the return value.
// The new context (ctx) must be passed to all the other lifecycle methods.
type HasPreBlocker interface {
AppModule
// PreBlock is method that will be run before BeginBlock.
PreBlock(context.Context) error
}

// HasBeginBlocker is the extension interface that modules should implement to run
// custom logic before transaction processing in a block.
type HasBeginBlocker interface {
Expand Down
2 changes: 1 addition & 1 deletion runtime/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func (a *App) Load(loadLatest bool) error {
}

// PreBlocker application updates every pre block
func (a *App) PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
func (a *App) PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) error {
return a.ModuleManager.PreBlock(ctx)
}

Expand Down
4 changes: 3 additions & 1 deletion runtime/services/autocli.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ func (a *autocliConfigurator) RegisterMigration(string, uint64, module.Migration
return nil
}

func (a *autocliConfigurator) Register(string, uint64, func(context.Context) error) error { return nil }
func (a *autocliConfigurator) Register(string, uint64, appmodule.MigrationHandler) error {
return nil
}
Comment on lines +116 to +118
Copy link
Contributor

Choose a reason for hiding this comment

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

Updating the Register method to take a MigrationHandler type for the third parameter simplifies the method signature and potentially aligns with the broader refactoring efforts to streamline error handling and module migrations. Ensure this change is consistently applied across all relevant parts of the SDK where the Register method is used.


func (a *autocliConfigurator) RegisterService(sd *grpc.ServiceDesc, ss interface{}) {
if a.registryCache == nil {
Expand Down
2 changes: 1 addition & 1 deletion simapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,7 @@ func (app *SimApp) Close() error {
func (app *SimApp) Name() string { return app.BaseApp.Name() }

// PreBlocker application updates every pre block
func (app *SimApp) PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) {
func (app *SimApp) PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) error {
return app.ModuleManager.PreBlock(ctx)
}

Expand Down
7 changes: 3 additions & 4 deletions testutil/mock/types_mock_appmodule.go

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

10 changes: 1 addition & 9 deletions types/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type VerifyVoteExtensionHandler func(Context, *abci.RequestVerifyVoteExtension)
// persist their results in state.
//
// Note: returning an error will make FinalizeBlock fail.
type PreBlocker func(Context, *abci.RequestFinalizeBlock) (*ResponsePreBlock, error)
type PreBlocker func(Context, *abci.RequestFinalizeBlock) error

// BeginBlocker defines a function type alias for executing application
// business logic before transactions are executed.
Expand Down Expand Up @@ -66,11 +66,3 @@ type EndBlock struct {
type BeginBlock struct {
Events []abci.Event
}

type ResponsePreBlock struct {
ConsensusParamsChanged bool
}

func (r ResponsePreBlock) IsConsensusParamsChanged() bool {
return r.ConsensusParamsChanged
}
6 changes: 3 additions & 3 deletions types/module/configurator.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package module

import (
"context"
"fmt"

"github.com/cosmos/gogoproto/grpc"
Expand All @@ -10,6 +9,7 @@ import (
"google.golang.org/protobuf/reflect/protoreflect"

cosmosmsg "cosmossdk.io/api/cosmos/msg/v1"
"cosmossdk.io/core/appmodule"
errorsmod "cosmossdk.io/errors"

"github.com/cosmos/cosmos-sdk/codec"
Expand Down Expand Up @@ -47,7 +47,7 @@ type Configurator interface {

// Register registers an in-place store migration for a module.
// It permits to register modules migrations that have migrated to serverv2 but still be compatible with baseapp.
Register(moduleName string, fromVersion uint64, handler func(context.Context) error) error
Register(moduleName string, fromVersion uint64, handler appmodule.MigrationHandler) error
}

type configurator struct {
Expand Down Expand Up @@ -124,7 +124,7 @@ func (c *configurator) RegisterMigration(moduleName string, fromVersion uint64,

// Register implements the Configurator.Register method
// It allows to register modules migrations that have migrated to server/v2 but still be compatible with baseapp.
func (c *configurator) Register(moduleName string, fromVersion uint64, handler func(context.Context) error) error {
func (c *configurator) Register(moduleName string, fromVersion uint64, handler appmodule.MigrationHandler) error {
return c.RegisterMigration(moduleName, fromVersion, func(sdkCtx sdk.Context) error {
return handler(sdkCtx)
})
Expand Down
15 changes: 4 additions & 11 deletions types/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -706,23 +706,16 @@ func (m Manager) RunMigrations(ctx context.Context, cfg Configurator, fromVM Ver
// PreBlock performs begin block functionality for upgrade module.
// It takes the current context as a parameter and returns a boolean value
// indicating whether the migration was successfully executed or not.
func (m *Manager) PreBlock(ctx sdk.Context) (*sdk.ResponsePreBlock, error) {
func (m *Manager) PreBlock(ctx sdk.Context) error {
ctx = ctx.WithEventManager(sdk.NewEventManager())
paramsChanged := false
for _, moduleName := range m.OrderPreBlockers {
if module, ok := m.Modules[moduleName].(appmodule.HasPreBlocker); ok {
rsp, err := module.PreBlock(ctx)
if err != nil {
return nil, err
}
if rsp.IsConsensusParamsChanged() {
paramsChanged = true
if err := module.PreBlock(ctx); err != nil {
return err
}
}
}
return &sdk.ResponsePreBlock{
ConsensusParamsChanged: paramsChanged,
}, nil
return nil
}

// BeginBlock performs begin block functionality for all modules. It creates a
Expand Down
17 changes: 3 additions & 14 deletions types/module/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,24 +418,13 @@ func TestCoreAPIManager_PreBlock(t *testing.T) {
require.Equal(t, 2, len(mm.Modules))
require.Equal(t, 1, len(mm.OrderPreBlockers))

mockAppModule1.EXPECT().PreBlock(gomock.Any()).Times(1).Return(&sdk.ResponsePreBlock{
ConsensusParamsChanged: true,
}, nil)
res, err := mm.PreBlock(sdk.Context{})
mockAppModule1.EXPECT().PreBlock(gomock.Any()).Times(1).Return(nil)
err := mm.PreBlock(sdk.Context{})
require.NoError(t, err)
require.True(t, res.ConsensusParamsChanged)

// test false
mockAppModule1.EXPECT().PreBlock(gomock.Any()).Times(1).Return(&sdk.ResponsePreBlock{
ConsensusParamsChanged: false,
}, nil)
res, err = mm.PreBlock(sdk.Context{})
require.NoError(t, err)
require.False(t, res.ConsensusParamsChanged)

// test error
mockAppModule1.EXPECT().PreBlock(gomock.Any()).Times(1).Return(nil, errors.New("some error"))
_, err = mm.PreBlock(sdk.Context{})
err = mm.PreBlock(sdk.Context{})
require.EqualError(t, err, "some error")
}

Expand Down
Loading
Loading