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: Changes to AppModuleGenesis for concurrent modules' genesis states unmarshaling #12295

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
65252d3
change AppModuleGenesis interface
catShaark Jun 17, 2022
de55fba
change AppModule in each module
catShaark Jun 17, 2022
cf8fe52
update mock test for module
catShaark Jun 17, 2022
db7c631
update TestInitGenesisOnMigration in app_test.go
catShaark Jun 17, 2022
2f39274
Merge branch 'main' into app-module-changes
catShaark Jun 17, 2022
7aa288f
update CHANGELOG.md
catShaark Jun 17, 2022
d801abc
Update types/module/module.go
catShaark Jun 20, 2022
c0b3620
update CHANGELOG.md
catShaark Jun 20, 2022
3fe60a8
update CHANGELOG.md
catShaark Jun 20, 2022
4f6178b
resolve conflict with main
catShaark Jun 20, 2022
cf63cf1
Merge branch 'main' into app-module-changes
catShaark Jun 20, 2022
acce5fa
add mutex to UnmarshalGenesis
catShaark Jun 22, 2022
8814533
resolve conflict with main
catShaark Jun 22, 2022
9bdec0c
Merge branch 'main' into app-module-changes
catShaark Jun 22, 2022
649748e
Update types/module/module.go
catShaark Jun 22, 2022
78ee2c2
update UnmarshalGenesis
catShaark Jun 22, 2022
aaf349c
Merge branch 'main' into app-module-changes
catShaark Jun 22, 2022
88025a9
typo
catShaark Jun 22, 2022
182a2d8
Merge branch 'main' into app-module-changes
catShaark Jun 22, 2022
fe07b6e
Merge branch 'main' into app-module-changes
tac0turtle Jun 23, 2022
d6be8b7
Merge branch 'main' into app-module-changes
catShaark Jun 27, 2022
248152a
Update types/module/module.go
catShaark Jun 27, 2022
b278e72
Merge branch 'main' into app-module-changes
catShaark Jun 27, 2022
5d0433f
Merge branch 'main' into app-module-changes
catShaark Jun 29, 2022
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* [#12089](https://github.com/cosmos/cosmos-sdk/pull/12089) Mark the `TipDecorator` as beta, don't include it in simapp by default.
* [#12153](https://github.com/cosmos/cosmos-sdk/pull/12153) Add a new `NewSimulationManagerFromAppModules` constructor, to simplify simulation wiring.
* [#12187](https://github.com/cosmos/cosmos-sdk/pull/12187) Add batch operation for x/nft module.
* [#12295](https://github.com/cosmos/cosmos-sdk/pull/12295) Change `AppModuleGenesis` interface to allow concurent modules' genesis states unmarshaling

### API Breaking Changes
alexanderbez marked this conversation as resolved.
Show resolved Hide resolved

Expand All @@ -56,7 +57,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (testutil) [#12233](https://github.com/cosmos/cosmos-sdk/pull/12233) Move `simapp.TestAddr` to `simtestutil.TestAddr` (`testutil/sims`)
* (x/staking) [#12102](https://github.com/cosmos/cosmos-sdk/pull/12102) Staking keeper now is passed by reference instead of copy. Keeper's SetHooks no longer returns keeper. It updates the keeper in place instead.
* (linting) [#12141](https://github.com/cosmos/cosmos-sdk/pull/12141) Fix usability related linting for database. This means removing the infix Prefix from `prefix.NewPrefixWriter` and such so that it is `prefix.NewWriter` and making `db.DBConnection` and such into `db.Connection`

* [#12295](https://github.com/cosmos/cosmos-sdk/pull/12295) Change `AppModuleGenesis` interface, include a new method `UnmarshalGenesis` and modify the method `InitGenesis`.

### Bug Fixes

Expand Down
3 changes: 2 additions & 1 deletion simapp/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,8 @@ func TestInitGenesisOnMigration(t *testing.T) {
mockModule := mocks.NewMockAppModule(mockCtrl)
mockDefaultGenesis := json.RawMessage(`{"key": "value"}`)
mockModule.EXPECT().DefaultGenesis(gomock.Eq(app.appCodec)).Times(1).Return(mockDefaultGenesis)
mockModule.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(app.appCodec), gomock.Eq(mockDefaultGenesis)).Times(1).Return(nil)
mockModule.EXPECT().UnmarshalGenesis(gomock.Eq(app.appCodec), gomock.Eq(mockDefaultGenesis)).Times(1).Return(nil)
mockModule.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Nil()).Times(1).Return(nil)
mockModule.EXPECT().ConsensusVersion().Times(1).Return(uint64(0))

app.ModuleManager.Modules["mock"] = mockModule
Expand Down
45 changes: 37 additions & 8 deletions tests/mocks/types_module_module.go

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

41 changes: 35 additions & 6 deletions types/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,14 @@ import (
"github.com/spf13/cobra"
abci "github.com/tendermint/tendermint/abci/types"

"sync"

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/gogo/protobuf/proto"
)

// AppModuleBasic is the standard form for basic non-dependant elements of an application module.
Expand Down Expand Up @@ -141,7 +144,8 @@ func (bm BasicManager) AddQueryCommands(rootQueryCmd *cobra.Command) {
type AppModuleGenesis interface {
AppModuleBasic

InitGenesis(sdk.Context, codec.JSONCodec, json.RawMessage) []abci.ValidatorUpdate
UnmarshalGenesis(codec.JSONCodec, json.RawMessage) proto.Message
InitGenesis(sdk.Context, proto.Message) []abci.ValidatorUpdate
ExportGenesis(sdk.Context, codec.JSONCodec) json.RawMessage
}

Expand Down Expand Up @@ -222,6 +226,7 @@ type Manager struct {
OrderBeginBlockers []string
OrderEndBlockers []string
OrderMigrations []string
mtx sync.Mutex
}

// NewManager creates a new Manager object
Expand All @@ -239,6 +244,7 @@ func NewManager(modules ...AppModule) *Manager {
OrderExportGenesis: modulesStr,
OrderBeginBlockers: modulesStr,
OrderEndBlockers: modulesStr,
mtx: sync.Mutex{},
}
}

Expand Down Expand Up @@ -299,19 +305,41 @@ func (m *Manager) RegisterServices(cfg Configurator) {
}
}

// InitGenesis performs init genesis functionality for modules. Exactly one
// module must return a non-empty validator set update to correctly initialize
// the chain.
func (m *Manager) UnmarshalGenesis(cdc codec.JSONCodec, genesisData map[string]json.RawMessage) map[string]proto.Message {
var wg sync.WaitGroup
genesisStates := map[string]proto.Message{}

for _, moduleName := range m.OrderInitGenesis {
if genesisData[moduleName] == nil {
continue
}
wg.Add(1)
go func(moduleName string) {
defer wg.Done()
moduleGenesis := m.Modules[moduleName].UnmarshalGenesis(cdc, genesisData[moduleName])
m.mtx.Lock()
genesisStates[moduleName] = moduleGenesis
m.mtx.Unlock()
}(moduleName)
Comment on lines +317 to +323

Check notice

Code scanning / CodeQL

Spawning a Go routine

Spawning a Go routine may be a possible source of non-determinism
}
wg.Wait()
return genesisStates
}

// InitGenesis performs init genesis functionality for modules
func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage) abci.ResponseInitChain {
var validatorUpdates []abci.ValidatorUpdate
ctx.Logger().Info("initializing blockchain state from genesis.json")

genesisStates := m.UnmarshalGenesis(cdc, genesisData)

for _, moduleName := range m.OrderInitGenesis {
if genesisData[moduleName] == nil {
continue
}
ctx.Logger().Debug("running initialization for module", "module", moduleName)

moduleValUpdates := m.Modules[moduleName].InitGenesis(ctx, cdc, genesisData[moduleName])
moduleValUpdates := m.Modules[moduleName].InitGenesis(ctx, genesisStates[moduleName])

// use these validator updates if provided, the module manager assumes
// only one module will update the validator set
Expand Down Expand Up @@ -447,7 +475,8 @@ func (m Manager) RunMigrations(ctx sdk.Context, cfg Configurator, fromVM Version
}
} else {
ctx.Logger().Info(fmt.Sprintf("adding a new module: %s", moduleName))
moduleValUpdates := module.InitGenesis(ctx, c.cdc, module.DefaultGenesis(c.cdc))
moduleDefaultGensisState := module.UnmarshalGenesis(c.cdc, module.DefaultGenesis(c.cdc))
moduleValUpdates := module.InitGenesis(ctx, moduleDefaultGensisState)
// The module manager assumes only one module will update the
// validator set, and it can't be a new module.
if len(moduleValUpdates) > 0 {
Expand Down
10 changes: 7 additions & 3 deletions types/module/module_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,16 +203,20 @@ func TestManager_InitGenesis(t *testing.T) {
genesisData := map[string]json.RawMessage{"module1": json.RawMessage(`{"key": "value"}`)}

// this should panic since the validator set is empty even after init genesis
mockAppModule1.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module1"])).Times(1).Return(nil)
mockAppModule1.EXPECT().UnmarshalGenesis(gomock.Eq(cdc), gomock.Eq(genesisData["module1"])).Times(1).Return(nil)
mockAppModule1.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Nil()).Times(1).Return(nil)
require.Panics(t, func() { mm.InitGenesis(ctx, cdc, genesisData) })

// test panic
genesisData = map[string]json.RawMessage{
"module1": json.RawMessage(`{"key": "value"}`),
"module2": json.RawMessage(`{"key": "value"}`),
}
mockAppModule1.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module1"])).Times(1).Return([]abci.ValidatorUpdate{{}})
mockAppModule2.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module2"])).Times(1).Return([]abci.ValidatorUpdate{{}})
mockAppModule1.EXPECT().UnmarshalGenesis(gomock.Eq(cdc), gomock.Eq(genesisData["module1"])).Times(1).Return(nil)
mockAppModule2.EXPECT().UnmarshalGenesis(gomock.Eq(cdc), gomock.Eq(genesisData["module2"])).Times(1).Return(nil)

mockAppModule1.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Nil()).Times(1).Return([]abci.ValidatorUpdate{{}})
mockAppModule2.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Nil()).Times(1).Return([]abci.ValidatorUpdate{{}})
require.Panics(t, func() { mm.InitGenesis(ctx, cdc, genesisData) })
}

Expand Down
12 changes: 9 additions & 3 deletions x/auth/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"math/rand"

"github.com/cosmos/cosmos-sdk/depinject"
"github.com/gogo/protobuf/proto"

gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime"

Expand Down Expand Up @@ -146,11 +147,16 @@ func (am AppModule) RegisterServices(cfg module.Configurator) {

// InitGenesis performs genesis initialization for the auth module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {
func (am AppModule) InitGenesis(ctx sdk.Context, genesisState proto.Message) []abci.ValidatorUpdate {
am.accountKeeper.InitGenesis(ctx, *genesisState.(*types.GenesisState))
return []abci.ValidatorUpdate{}
}

// UnmarshalGenesis unmarshals the genesis state for the auth module.
func (am AppModule) UnmarshalGenesis(cdc codec.JSONCodec, data json.RawMessage) proto.Message {
var genesisState types.GenesisState
cdc.MustUnmarshalJSON(data, &genesisState)
am.accountKeeper.InitGenesis(ctx, genesisState)
return []abci.ValidatorUpdate{}
return &genesisState
}

// ExportGenesis returns the exported genesis state as raw bytes for the auth
Expand Down
8 changes: 7 additions & 1 deletion x/auth/vesting/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package vesting
import (
"encoding/json"

"github.com/gogo/protobuf/proto"
gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cobra"
abci "github.com/tendermint/tendermint/abci/types"
Expand Down Expand Up @@ -112,10 +113,15 @@ func (am AppModule) LegacyQuerierHandler(_ *codec.LegacyAmino) sdk.Querier {
}

// InitGenesis performs a no-op.
func (am AppModule) InitGenesis(_ sdk.Context, _ codec.JSONCodec, _ json.RawMessage) []abci.ValidatorUpdate {
func (am AppModule) InitGenesis(_ sdk.Context, _ proto.Message) []abci.ValidatorUpdate {
return []abci.ValidatorUpdate{}
}

// UnmarshalGenesis performs a no-op.
func (am AppModule) UnmarshalGenesis(_ codec.JSONCodec, _ json.RawMessage) proto.Message {
return nil
}

// BeginBlock performs a no-op.
func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) {}

Expand Down
12 changes: 9 additions & 3 deletions x/authz/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"math/rand"

"github.com/gogo/protobuf/proto"
gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cobra"
abci "github.com/tendermint/tendermint/abci/types"
Expand Down Expand Up @@ -147,11 +148,16 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd

// InitGenesis performs genesis initialization for the authz module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {
func (am AppModule) InitGenesis(ctx sdk.Context, genesisState proto.Message) []abci.ValidatorUpdate {
am.keeper.InitGenesis(ctx, genesisState.(*authz.GenesisState))
return []abci.ValidatorUpdate{}
}

// UnmarshalGenesis unmarshals the genesis state for the authz module.
func (am AppModule) UnmarshalGenesis(cdc codec.JSONCodec, data json.RawMessage) proto.Message {
var genesisState authz.GenesisState
cdc.MustUnmarshalJSON(data, &genesisState)
am.keeper.InitGenesis(ctx, &genesisState)
return []abci.ValidatorUpdate{}
return &genesisState
}

// ExportGenesis returns the exported genesis state as raw bytes for the authz
Expand Down
17 changes: 9 additions & 8 deletions x/bank/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import (
"encoding/json"
"fmt"
"math/rand"
"time"

modulev1 "cosmossdk.io/api/cosmos/bank/module/v1"
"github.com/cosmos/cosmos-sdk/depinject"
store "github.com/cosmos/cosmos-sdk/store/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/gogo/protobuf/proto"
"github.com/tendermint/tendermint/crypto"

"cosmossdk.io/core/appmodule"
Expand All @@ -22,7 +22,6 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/runtime"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
simtypes "github.com/cosmos/cosmos-sdk/types/simulation"
Expand Down Expand Up @@ -152,14 +151,16 @@ func (am AppModule) LegacyQuerierHandler(legacyQuerierCdc *codec.LegacyAmino) sd

// InitGenesis performs genesis initialization for the bank module. It returns
// no validator updates.
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate {
start := time.Now()
func (am AppModule) InitGenesis(ctx sdk.Context, genesisState proto.Message) []abci.ValidatorUpdate {
am.keeper.InitGenesis(ctx, genesisState.(*types.GenesisState))
return []abci.ValidatorUpdate{}
}

// UnmarshalGenesis unmarshals the genesis state for the bank module.
func (am AppModule) UnmarshalGenesis(cdc codec.JSONCodec, data json.RawMessage) proto.Message {
var genesisState types.GenesisState
cdc.MustUnmarshalJSON(data, &genesisState)
telemetry.MeasureSince(start, "InitGenesis", "crisis", "unmarshal")

am.keeper.InitGenesis(ctx, &genesisState)
return []abci.ValidatorUpdate{}
return &genesisState
}

// ExportGenesis returns the exported genesis state as raw bytes for the bank
Expand Down
Loading