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

feat: introduce PreBlock #17421

Merged
merged 42 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
9944fe1
replace RunMigrationBeginBlock with PreBeginBlock
mmsqe Aug 17, 2023
97437d2
fix test
mmsqe Aug 17, 2023
5df47ca
update doc
mmsqe Aug 17, 2023
4cb3ead
Merge branch 'main' into pre-begin
mmsqe Aug 17, 2023
875aef9
fix doc
mmsqe Aug 17, 2023
fa4d36c
add test
mmsqe Aug 17, 2023
8f901a2
Apply suggestions from code review
mmsqe Aug 17, 2023
0bf24db
force register in upgrade
mmsqe Aug 18, 2023
6aef95e
Merge branch 'main' into pre-begin
mmsqe Aug 18, 2023
952c619
keep UpgradeModule
mmsqe Aug 18, 2023
9ab334d
Revert "keep UpgradeModule"
mmsqe Aug 19, 2023
81aea05
Merge branch 'main' into pre-begin
mmsqe Aug 19, 2023
bded698
add proto
mmsqe Aug 19, 2023
1294aba
allow sim test use latest config.PreBlockers
mmsqe Aug 19, 2023
41eac61
add SetOrderPreBlockers
mmsqe Aug 19, 2023
5a80397
fix doc
mmsqe Aug 19, 2023
b9d1447
fix test
mmsqe Aug 19, 2023
5306a6f
Apply suggestions from code review
mmsqe Aug 19, 2023
9fac2e9
rm dummy upgrade from begin blocker
mmsqe Aug 19, 2023
b5e9072
replace dep
mmsqe Aug 20, 2023
e9247db
decouple dep
mmsqe Aug 20, 2023
e40de51
use latest sdk ResponsePreBlock
mmsqe Aug 20, 2023
afbf503
add when dep is ready (to be reverted)
mmsqe Aug 20, 2023
069488d
replace dep
mmsqe Aug 21, 2023
91b8fb4
Revert "add when dep is ready (to be reverted)"
mmsqe Aug 21, 2023
f3d2aa6
Merge remote-tracking branch 'origin/main' into pre-begin
mmsqe Aug 21, 2023
67b41af
fix replace
mmsqe Aug 21, 2023
3ff3ca4
Merge remote-tracking branch 'origin/main' into pre-begin
mmsqe Aug 21, 2023
c2a4320
Apply suggestions from code review
mmsqe Aug 21, 2023
3ffb4e9
Apply suggestions from code review
mmsqe Aug 21, 2023
5b87a82
Merge remote-tracking branch 'origin/main' into pre-begin
mmsqe Aug 24, 2023
19b0153
Merge remote-tracking branch 'origin/main' into pre-begin
mmsqe Aug 26, 2023
c4cffdc
Merge remote-tracking branch 'origin/main' into pre-begin
mmsqe Aug 29, 2023
4fb0496
Merge remote-tracking branch 'origin/main' into pre-begin
mmsqe Aug 30, 2023
2a9966d
reset gas meter after update cp
mmsqe Aug 30, 2023
19901c9
Merge remote-tracking branch 'origin/main' into pre-begin
mmsqe Sep 6, 2023
f2ac765
Update docs/docs/build/building-modules/17-preblock.md
mmsqe Sep 6, 2023
7a7dbaa
Merge branch 'main' into pre-begin
mmsqe Sep 13, 2023
766c82d
Apply suggestions from code review
mmsqe Sep 13, 2023
95a19e0
Merge branch 'main' into pre-begin
mmsqe Sep 13, 2023
e55d9e5
Merge branch 'main' into pre-begin
mmsqe Sep 13, 2023
88b1801
Apply suggestions from code review
mmsqe Sep 13, 2023
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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Bug Fixes

* (types) [#16583](https://github.com/cosmos/cosmos-sdk/pull/16583), [#17372](https://github.com/cosmos/cosmos-sdk/pull/17372) Add `MigrationModuleManager` to handle migration of upgrade module before other modules, ensuring access to the updated context with consensus parameters within the same block that executes the migration.
* (types) [#16583](https://github.com/cosmos/cosmos-sdk/pull/16583), [#17372](https://github.com/cosmos/cosmos-sdk/pull/17372), [#17421](https://github.com/cosmos/cosmos-sdk/pull/17421) Introduce `PreBlock`, which runs before begin blocker other modules, and allows to modify consensus parameters, and the changes are visible to the following state machine logics.
* (baseapp) [#17518](https://github.com/cosmos/cosmos-sdk/pull/17518) Utilizing voting power from vote extensions (CometBFT) instead of the current bonded tokens (x/staking) to determine if a set of vote extensions are valid.
* (config) [#17649](https://github.com/cosmos/cosmos-sdk/pull/17649) Fix `mempool.max-txs` configuration is invalid in `app.config`.
* (mempool) [#17668](https://github.com/cosmos/cosmos-sdk/pull/17668) Fix: `PriorityNonceIterator.Next()` nil pointer ref for min priority at the end of iteration.
Expand Down
12 changes: 9 additions & 3 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,21 @@ allows an application to define handlers for these methods via `ExtendVoteHandle
and `VerifyVoteExtensionHandler` respectively. Please see [here](https://docs.cosmos.network/v0.50/building-apps/vote-extensions)
for more info.

#### Upgrade
#### Set PreBlocker

**Users using `depinject` / app v2 do not need any changes, this is abstracted for them.**

```diff
+ app.BaseApp.SetMigrationModuleManager(app.ModuleManager)
+ app.SetPreBlocker(app.PreBlocker)
```

BaseApp added `SetMigrationModuleManager` for apps to set their ModuleManager which implements `RunMigrationBeginBlock`. This is essential for BaseApp to run `BeginBlock` of upgrade module and inject `ConsensusParams` to context for `beginBlocker` during `beginBlock`.
```diff
+func (app *SimApp) PreBlocker(ctx sdk.Context, req abci.RequestBeginBlock) (sdk.ResponsePreBlock, error) {
+ return app.ModuleManager.PreBlock(ctx, req)
+}
```

BaseApp added `SetPreBlocker` for apps. This is essential for BaseApp to run `PreBlock` which runs before begin blocker other modules, and allows to modify consensus parameters, and the changes are visible to the following state machine logics.

#### Events

Expand Down
4 changes: 4 additions & 0 deletions baseapp/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,10 @@ func (app *BaseApp) FinalizeBlock(req *abci.RequestFinalizeBlock) (*abci.Respons
}
}

if err := app.preBlock(); err != nil {
return nil, err
}

Comment on lines 736 to +742
Copy link
Contributor

Choose a reason for hiding this comment

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

Change potentially affects state.

Call sequence:

(*github.com/cosmos/cosmos-sdk/baseapp.BaseApp).FinalizeBlock (baseapp/abci.go:669)

beginBlock, err := app.beginBlock(req)
if err != nil {
return nil, err
Expand Down
52 changes: 22 additions & 30 deletions baseapp/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,6 @@ type (
StoreLoader func(ms storetypes.CommitMultiStore) error
)

// MigrationModuleManager is the interface that a migration module manager should implement to handle
// the execution of migration logic during the beginning of a block.
type MigrationModuleManager interface {
RunMigrationBeginBlock(ctx sdk.Context) (bool, error)
}

const (
execModeCheck execMode = iota // Check a transaction
execModeReCheck // Recheck a (pending) transaction after a commit
Expand Down Expand Up @@ -81,6 +75,7 @@ type BaseApp struct {
postHandler sdk.PostHandler // post handler, optional, e.g. for tips

initChainer sdk.InitChainer // ABCI InitChain handler
preBlocker sdk.PreBlocker // logic to run before BeginBlocker
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved
beginBlocker sdk.BeginBlocker // (legacy ABCI) BeginBlock handler
endBlocker sdk.EndBlocker // (legacy ABCI) EndBlock handler
processProposal sdk.ProcessProposalHandler // ABCI ProcessProposal handler
Expand All @@ -98,9 +93,6 @@ type BaseApp struct {
// manages snapshots, i.e. dumps of app state at certain intervals
snapshotManager *snapshots.Manager

// manages migrate module
migrationModuleManager MigrationModuleManager

// volatile states:
//
// - checkState is set on InitChain and reset on Commit
Expand Down Expand Up @@ -283,11 +275,6 @@ func (app *BaseApp) SetMsgServiceRouter(msgServiceRouter *MsgServiceRouter) {
app.msgServiceRouter = msgServiceRouter
}

// SetMigrationModuleManager sets the MigrationModuleManager of a BaseApp.
func (app *BaseApp) SetMigrationModuleManager(migrationModuleManager MigrationModuleManager) {
app.migrationModuleManager = migrationModuleManager
}

// MountStores mounts all IAVL or DB stores to the provided keys in the BaseApp
// multistore.
func (app *BaseApp) MountStores(keys ...storetypes.StoreKey) {
Expand Down Expand Up @@ -682,29 +669,34 @@ func (app *BaseApp) cacheTxContext(ctx sdk.Context, txBytes []byte) (sdk.Context
return ctx.WithMultiStore(msCache), msCache
}

func (app *BaseApp) preBlock() error {
if app.preBlocker != nil {
ctx := app.finalizeBlockState.ctx
rsp, err := app.preBlocker(ctx)
if err != nil {
return err
}
// rsp.ConsensusParamsChanged is true from preBlocker means ConsensusParams in store get changed
// write the consensus parameters in store to context
if rsp.ConsensusParamsChanged {
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.ctx = ctx
}
}
Comment on lines +682 to +688
Copy link
Contributor

Choose a reason for hiding this comment

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

Change potentially affects state.

Call sequence:

(*github.com/cosmos/cosmos-sdk/baseapp.BaseApp).beginBlock (baseapp/baseapp.go:685)
(*github.com/cosmos/cosmos-sdk/baseapp.BaseApp).FinalizeBlock (baseapp/baseapp.go:669)

return nil
}

func (app *BaseApp) beginBlock(req *abci.RequestFinalizeBlock) (sdk.BeginBlock, error) {
var (
resp sdk.BeginBlock
err error
)

if app.beginBlocker != nil {
ctx := app.finalizeBlockState.ctx
if app.migrationModuleManager != nil {
if success, err := app.migrationModuleManager.RunMigrationBeginBlock(ctx); success {
cp := ctx.ConsensusParams()
// Manager skips this step if Block is non-nil since upgrade module is expected to set this params
// and consensus parameters should not be overwritten.
if cp.Block == nil {
if cp = app.GetConsensusParams(ctx); cp.Block != nil {
ctx = ctx.WithConsensusParams(cp)
}
}
} else if err != nil {
return sdk.BeginBlock{}, err
}
}
resp, err = app.beginBlocker(ctx)
resp, err = app.beginBlocker(app.finalizeBlockState.ctx)
if err != nil {
return resp, err
}
Expand Down
3 changes: 3 additions & 0 deletions baseapp/baseapp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,9 @@ func TestBaseAppOptionSeal(t *testing.T) {
require.Panics(t, func() {
suite.baseApp.SetInitChainer(nil)
})
require.Panics(t, func() {
suite.baseApp.SetPreBlocker(nil)
})
require.Panics(t, func() {
suite.baseApp.SetBeginBlocker(nil)
})
Expand Down
8 changes: 8 additions & 0 deletions baseapp/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,14 @@ func (app *BaseApp) SetInitChainer(initChainer sdk.InitChainer) {
app.initChainer = initChainer
}

func (app *BaseApp) SetPreBlocker(preBlocker sdk.PreBlocker) {
if app.sealed {
panic("SetPreBlocker() on sealed BaseApp")
}

app.preBlocker = preBlocker
}

func (app *BaseApp) SetBeginBlocker(beginBlocker sdk.BeginBlocker) {
if app.sealed {
panic("SetBeginBlocker() on sealed BaseApp")
Expand Down
11 changes: 11 additions & 0 deletions docs/architecture/adr-063-core-module-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,17 @@ type HasGenesis interface {
}
```

#### Pre Blockers

Modules that have functionality that runs before BeginBlock and should implement the has `HasPreBlocker` interfaces:

```go
type HasPreBlocker interface {
AppModule
PreBlock(context.Context) error
}
```

#### Begin and End Blockers

Modules that have functionality that runs before transactions (begin blockers) or after transactions
Expand Down
60 changes: 60 additions & 0 deletions docs/architecture/adr-068-preblock.md
julienrbrt marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# ADR 068: Preblock

## Changelog

* Sept 13, 2023: Initial Draft

## Status

DRAFT

## Abstract

Introduce `PreBlock`, which runs before begin blocker other modules, and allows to modify consensus parameters, and the changes are visible to the following state machine logics.

## Context
tac0turtle marked this conversation as resolved.
Show resolved Hide resolved

When upgrading to sdk 0.47, the storage format for consensus parameters changed, but in the migration block, `ctx.ConsensusParams()` is always `nil`, because it fails to load the old format using new code, it's supposed to be migrated by the `x/upgrade` module first, but unfortunately, the migration happens in `BeginBlocker` handler, which runs after the `ctx` is initialized.
When we try to solve this, we find the `x/upgrade` module can't modify the context to make the consensus parameters visible for the other modules, the context is passed by value, and sdk team want to keep it that way, that's good for isolations between modules.

## Alternatives

The first alternative solution introduced a `MigrateModuleManager`, which only includes the `x/upgrade` module right now, and baseapp will run their `BeginBlocker`s before the other modules, and reload context's consensus parameters in between.

## Decision

Suggested this new lifecycle method.

### `PreBlocker`

There are two semantics around the new lifecycle method:

- It runs before the `BeginBlocker` of all modules
- 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:
```
app.finalizeBlockState.ctx = app.finalizeBlockState.ctx.WithConsensusParams(app.GetConsensusParams())
```

The new ctx must be passed to all the other lifecycle methods.


## Consequences

### Backwards Compatibility

### Positive

### Negative

### Neutral

## Further Discussions

## Test Cases

## References
* [1] https://github.com/cosmos/cosmos-sdk/issues/16494
* [2] https://github.com/cosmos/cosmos-sdk/pull/16583
* [3] https://github.com/cosmos/cosmos-sdk/pull/17421
2 changes: 1 addition & 1 deletion docs/docs/build/building-apps/01-app-go-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ The `app_config.go` file is the single place to configure all modules parameters
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/simapp/app_config.go#L103-L167
```

3. Configure the modules defined in the `BeginBlocker` and `EndBlocker` and the `tx` module:
3. Configure the modules defined in the `PreBlocker`, `BeginBlocker` and `EndBlocker` and the `tx` module:

```go reference
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/simapp/app_config.go#L112-L129
Expand Down
12 changes: 9 additions & 3 deletions docs/docs/build/building-apps/03-app-upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,22 @@ the rest of the block as normal. Once 2/3 of the voting power has upgraded, the
resume the consensus mechanism. If the majority of operators add a custom `do-upgrade` script, this should
be a matter of minutes and not even require them to be awake at that time.

## Set Migration Module Manager
## Set PreBlocker

:::tip
Users using `depinject` / app v2 do not need any changes, this is abstracted for them.
:::

After app initiation, call `SetMigrationModuleManager` with ModuleManager to give BaseApp access to `RunMigrationBeginBlock`:
Call `SetPreBlocker` to run `PreBlock`:

```go
app.BaseApp.SetMigrationModuleManager(app.ModuleManager)
app.SetPreBlocker(app.PreBlocker)
```

```go
func (app *SimApp) PreBlocker(ctx sdk.Context, req abci.RequestBeginBlock) (sdk.ResponsePreBlock, error) {
return app.ModuleManager.PreBlock(ctx, req)
}
```

## Integrating With An App
Expand Down
Loading
Loading