diff --git a/server/config/config.go b/server/config/config.go index c34408006..893ba6fdc 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -192,6 +192,15 @@ type StateSyncConfig struct { SnapshotDirectory string `mapstructure:"snapshot-directory"` } +// GenesisConfig defines the genesis export, validation, and import configuration +type GenesisConfig struct { + // StreamImport defines if the genesis.json is in stream form or not. + StreamImport bool `mapstructure:"stream-import"` + + // GenesisStreamFile sets the genesis json file from which to stream from + GenesisStreamFile string `mapstructure:"genesis-stream-file"` +} + // Config defines the server's top level configuration type Config struct { BaseConfig `mapstructure:",squash"` @@ -205,6 +214,7 @@ type Config struct { StateSync StateSyncConfig `mapstructure:"state-sync"` StateCommit config.StateCommitConfig `mapstructure:"state-commit"` StateStore config.StateStoreConfig `mapstructure:"state-store"` + Genesis GenesisConfig `mapstructure:genesis` } // SetMinGasPrices sets the validator's minimum gas prices. @@ -288,6 +298,10 @@ func DefaultConfig() *Config { }, StateCommit: config.DefaultStateCommitConfig(), StateStore: config.DefaultStateStoreConfig(), + Genesis: GenesisConfig{ + StreamImport: false, + GenesisStreamFile: "", + }, } } @@ -391,6 +405,10 @@ func GetConfig(v *viper.Viper) (Config, error) { PruneIntervalSeconds: v.GetInt("state-store.prune-interval-seconds"), ImportNumWorkers: v.GetInt("state-store.import-num-workers"), }, + Genesis: GenesisConfig{ + StreamImport: v.GetBool("genesis.stream-import"), + GenesisStreamFile: v.GetString("genesis.genesis-stream-file"), + }, }, nil } diff --git a/server/config/toml.go b/server/config/toml.go index 6e1addfc4..ec6d683a9 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -246,6 +246,20 @@ snapshot-keep-recent = {{ .StateSync.SnapshotKeepRecent }} # default is emtpy which will then store under the app home directory same as before. snapshot-directory = "{{ .StateSync.SnapshotDirectory }}" +############################################################################### +### Genesis Configuration ### +############################################################################### + + +# Genesis config allows configuring whether to stream from an genesis json file in streamed form +[genesis] + +# stream-import specifies whether to the stream the import from the genesis json file. The genesis +# file must be in stream form and exported in a streaming fashion. +stream-import = {{ .Genesis.StreamImport }} + +# genesis-stream-file specifies the path of the genesis json file to stream from. +genesis-stream-file = "{{ .Genesis.GenesisStreamFile }}" ` + config.DefaultConfigTemplate var configTemplate *template.Template diff --git a/server/export.go b/server/export.go index 3dc5b8eba..cf25eea42 100644 --- a/server/export.go +++ b/server/export.go @@ -7,8 +7,10 @@ import ( "fmt" "io/ioutil" "os" + "time" "github.com/spf13/cobra" + tmbytes "github.com/tendermint/tendermint/libs/bytes" tmtypes "github.com/tendermint/tendermint/types" "github.com/cosmos/cosmos-sdk/client/flags" @@ -17,11 +19,22 @@ import ( ) const ( + FlagIsStreaming = "streaming" + FlagStreamingFile = "streaming-file" FlagHeight = "height" FlagForZeroHeight = "for-zero-height" FlagJailAllowedAddrs = "jail-allowed-addrs" ) +type GenesisDocNoAppState struct { + GenesisTime time.Time `json:"genesis_time"` + ChainID string `json:"chain_id"` + InitialHeight int64 `json:"initial_height,string"` + ConsensusParams *tmtypes.ConsensusParams `json:"consensus_params,omitempty"` + Validators []tmtypes.GenesisValidator `json:"validators,omitempty"` + AppHash tmbytes.HexBytes `json:"app_hash"` +} + // ExportCmd dumps app state to JSON. func ExportCmd(appExporter types.AppExporter, defaultNodeHome string) *cobra.Command { cmd := &cobra.Command{ @@ -38,6 +51,20 @@ func ExportCmd(appExporter types.AppExporter, defaultNodeHome string) *cobra.Com return err } + isStreaming, err := cmd.Flags().GetBool(FlagIsStreaming) + if err != nil { + return err + } + + streamingFile, err := cmd.Flags().GetString(FlagStreamingFile) + if err != nil { + return err + } + + if isStreaming && streamingFile == "" { + return fmt.Errorf("file to export stream to not provided, please specify --streaming-file") + } + db, err := openDB(config.RootDir) if err != nil { return err @@ -67,7 +94,56 @@ func ExportCmd(appExporter types.AppExporter, defaultNodeHome string) *cobra.Com forZeroHeight, _ := cmd.Flags().GetBool(FlagForZeroHeight) jailAllowedAddrs, _ := cmd.Flags().GetStringSlice(FlagJailAllowedAddrs) - exported, err := appExporter(serverCtx.Logger, db, traceWriter, height, forZeroHeight, jailAllowedAddrs, serverCtx.Viper) + if isStreaming { + file, err := os.Create(streamingFile) + if err != nil { + return err + } + exported, err := appExporter(serverCtx.Logger, db, traceWriter, height, forZeroHeight, jailAllowedAddrs, serverCtx.Viper, file) + if err != nil { + return fmt.Errorf("error exporting state: %v", err) + } + + doc, err := tmtypes.GenesisDocFromFile(serverCtx.Config.GenesisFile()) + if err != nil { + return err + } + + genesisDocNoAppHash := GenesisDocNoAppState{ + GenesisTime: doc.GenesisTime, + ChainID: doc.ChainID, + AppHash: doc.AppHash, + InitialHeight: exported.Height, + ConsensusParams: &tmtypes.ConsensusParams{ + Block: tmtypes.BlockParams{ + MaxBytes: exported.ConsensusParams.Block.MaxBytes, + MaxGas: exported.ConsensusParams.Block.MaxGas, + }, + Evidence: tmtypes.EvidenceParams{ + MaxAgeNumBlocks: exported.ConsensusParams.Evidence.MaxAgeNumBlocks, + MaxAgeDuration: exported.ConsensusParams.Evidence.MaxAgeDuration, + MaxBytes: exported.ConsensusParams.Evidence.MaxBytes, + }, + Validator: tmtypes.ValidatorParams{ + PubKeyTypes: exported.ConsensusParams.Validator.PubKeyTypes, + }, + }, + Validators: exported.Validators, + } + + // NOTE: Tendermint uses a custom JSON decoder for GenesisDoc + // (except for stuff inside AppState). Inside AppState, we're free + // to encode as protobuf or amino. + encoded, err := json.Marshal(genesisDocNoAppHash) + if err != nil { + return err + } + + file.Write([]byte(fmt.Sprintf("%s", string(sdk.MustSortJSON(encoded))))) + return nil + } + + exported, err := appExporter(serverCtx.Logger, db, traceWriter, height, forZeroHeight, jailAllowedAddrs, serverCtx.Viper, nil) if err != nil { return fmt.Errorf("error exporting state: %v", err) } @@ -108,6 +184,8 @@ func ExportCmd(appExporter types.AppExporter, defaultNodeHome string) *cobra.Com }, } + cmd.Flags().Bool(FlagIsStreaming, false, "Whether to stream the export in chunks. Useful when genesis is extremely large and cannot fit into memory.") + cmd.Flags().String(FlagStreamingFile, "genesis-stream.json", "The file to export the streamed genesis to") cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory") cmd.Flags().Int64(FlagHeight, -1, "Export state from a particular height (-1 means latest height)") cmd.Flags().Bool(FlagForZeroHeight, false, "Export state to start at height zero (perform preproccessing)") diff --git a/server/export_test.go b/server/export_test.go index c59ca9b2b..e4d4964b5 100644 --- a/server/export_test.go +++ b/server/export_test.go @@ -147,7 +147,7 @@ func setupApp(t *testing.T, tempDir string) (*simapp.SimApp, context.Context, *t app.Commit(context.Background()) cmd := server.ExportCmd( - func(_ log.Logger, _ dbm.DB, _ io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string, appOptons types.AppOptions) (types.ExportedApp, error) { + func(_ log.Logger, _ dbm.DB, _ io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string, appOptons types.AppOptions, file *os.File) (types.ExportedApp, error) { encCfg := simapp.MakeTestEncodingConfig() var simApp *simapp.SimApp diff --git a/server/start.go b/server/start.go index aedc274e4..907c25c47 100644 --- a/server/start.go +++ b/server/start.go @@ -13,6 +13,7 @@ import ( clientconfig "github.com/cosmos/cosmos-sdk/client/config" + genesistypes "github.com/cosmos/cosmos-sdk/types/genesis" "github.com/spf13/cobra" abciclient "github.com/tendermint/tendermint/abci/client" "github.com/tendermint/tendermint/abci/server" @@ -170,11 +171,6 @@ is performed. Note, when enabled, gRPC will also be automatically enabled. serverCtx.Viper.Set(flags.FlagChainID, chainID) - genesisFile, _ := tmtypes.GenesisDocFromFile(serverCtx.Config.GenesisFile()) - if genesisFile.ChainID != clientCtx.ChainID { - panic(fmt.Sprintf("genesis file chain-id=%s does not equal config.toml chain-id=%s", genesisFile.ChainID, clientCtx.ChainID)) - } - if enableTracing, _ := cmd.Flags().GetBool(tracing.FlagTracing); !enableTracing { serverCtx.Logger.Info("--tracing not passed in, tracing is not enabled") tracerProviderOptions = []trace.TracerProviderOption{} @@ -197,6 +193,12 @@ is performed. Note, when enabled, gRPC will also be automatically enabled. if err != nil { return fmt.Errorf("failed to initialize telemetry: %w", err) } + if !config.Genesis.StreamImport { + genesisFile, _ := tmtypes.GenesisDocFromFile(serverCtx.Config.GenesisFile()) + if genesisFile.ChainID != clientCtx.ChainID { + panic(fmt.Sprintf("genesis file chain-id=%s does not equal config.toml chain-id=%s", genesisFile.ChainID, clientCtx.ChainID)) + } + } restartCoolDownDuration := time.Second * time.Duration(serverCtx.Config.SelfRemediation.RestartCooldownSeconds) // Set the first restart time to be now - restartCoolDownDuration so that the first restart can trigger whenever @@ -386,13 +388,27 @@ func startInProcess( config.GRPC.Enable = true } else { ctx.Logger.Info("starting node with ABCI Tendermint in-process") + var gen *tmtypes.GenesisDoc + if config.Genesis.StreamImport { + lines := genesistypes.IngestGenesisFileLineByLine(config.Genesis.GenesisStreamFile) + for line := range lines { + genDoc, err := tmtypes.GenesisDocFromJSON([]byte(line)) + if err != nil { + return err + } + if gen != nil { + return fmt.Errorf("error: multiple genesis docs found in stream") + } + gen = genDoc + } + } tmNode, err = node.New( goCtx, ctx.Config, ctx.Logger, restartCh, abciclient.NewLocalClient(ctx.Logger, app), - nil, + gen, tracerProviderOptions, nodeMetricsProvider, ) diff --git a/server/types/app.go b/server/types/app.go index c95a8b3a2..82ac40cb1 100644 --- a/server/types/app.go +++ b/server/types/app.go @@ -3,6 +3,7 @@ package types import ( "encoding/json" "io" + "os" "time" sdk "github.com/cosmos/cosmos-sdk/types" @@ -84,5 +85,6 @@ type ( // AppExporter is a function that dumps all app state to // JSON-serializable structure and returns the current validator set. - AppExporter func(log.Logger, dbm.DB, io.Writer, int64, bool, []string, AppOptions) (ExportedApp, error) + // If a file is specified, + AppExporter func(log.Logger, dbm.DB, io.Writer, int64, bool, []string, AppOptions, *os.File) (ExportedApp, error) ) diff --git a/simapp/app.go b/simapp/app.go index 521584fa4..dae4e9e0b 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -32,6 +32,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/streaming" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" + genesistypes "github.com/cosmos/cosmos-sdk/types/genesis" "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/utils" "github.com/cosmos/cosmos-sdk/version" @@ -594,7 +595,7 @@ func (app *SimApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci. panic(err) } app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap()) - return app.mm.InitGenesis(ctx, app.appCodec, genesisState) + return app.mm.InitGenesis(ctx, app.appCodec, genesisState, genesistypes.GenesisImportConfig{}) } // LoadHeight loads a particular height diff --git a/simapp/sim_test.go b/simapp/sim_test.go index 7c8670fbd..0baa7950f 100644 --- a/simapp/sim_test.go +++ b/simapp/sim_test.go @@ -18,6 +18,7 @@ import ( "github.com/cosmos/cosmos-sdk/simapp/helpers" "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/genesis" simtypes "github.com/cosmos/cosmos-sdk/types/simulation" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" @@ -155,7 +156,7 @@ func TestAppImportExport(t *testing.T) { ctxA := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) ctxB := newApp.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()}) - newApp.mm.InitGenesis(ctxB, app.AppCodec(), genesisState) + newApp.mm.InitGenesis(ctxB, app.AppCodec(), genesisState, genesis.GenesisImportConfig{}) newApp.StoreConsensusParams(ctxB, exported.ConsensusParams) fmt.Printf("comparing stores...\n") diff --git a/simapp/simd/cmd/root.go b/simapp/simd/cmd/root.go index 4b3f5dfee..40e9e7933 100644 --- a/simapp/simd/cmd/root.go +++ b/simapp/simd/cmd/root.go @@ -313,7 +313,7 @@ func (a appCreator) newApp(logger log.Logger, db dbm.DB, traceStore io.Writer, t // and exports state. func (a appCreator) appExport( logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string, - appOpts servertypes.AppOptions) (servertypes.ExportedApp, error) { + appOpts servertypes.AppOptions, file *os.File) (servertypes.ExportedApp, error) { var simApp *simapp.SimApp homePath, ok := appOpts.Get(flags.FlagHome).(string) diff --git a/tests/mocks/types_module_module.go b/tests/mocks/types_module_module.go index 9a7dd5572..32d136c4d 100644 --- a/tests/mocks/types_module_module.go +++ b/tests/mocks/types_module_module.go @@ -162,6 +162,20 @@ func (mr *MockAppModuleBasicMockRecorder) ValidateGenesis(arg0, arg1, arg2 inter return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesis", reflect.TypeOf((*MockAppModuleBasic)(nil).ValidateGenesis), arg0, arg1, arg2) } +// ValidateGenesisStream mocks base method. +func (m *MockAppModuleBasic) ValidateGenesisStream(arg0 codec.JSONCodec, arg1 client.TxEncodingConfig, arg2 <-chan json.RawMessage) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateGenesisStream", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateGenesisStream indicates an expected call of ValidateGenesisStream. +func (mr *MockAppModuleBasicMockRecorder) ValidateGenesisStream(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesisStream", reflect.TypeOf((*MockAppModuleBasic)(nil).ValidateGenesisStream), arg0, arg1, arg2) +} + // MockAppModuleGenesis is a mock of AppModuleGenesis interface. type MockAppModuleGenesis struct { ctrl *gomock.Controller @@ -213,6 +227,20 @@ func (mr *MockAppModuleGenesisMockRecorder) ExportGenesis(arg0, arg1 interface{} return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportGenesis", reflect.TypeOf((*MockAppModuleGenesis)(nil).ExportGenesis), arg0, arg1) } +// ExportGenesisStream mocks base method. +func (m *MockAppModuleGenesis) ExportGenesisStream(ctx types0.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExportGenesisStream", ctx, cdc) + ret0, _ := ret[0].(<-chan json.RawMessage) + return ret0 +} + +// ExportGenesisStream indicates an expected call of ExportGenesisStream. +func (mr *MockAppModuleGenesisMockRecorder) ExportGenesisStream(ctx, cdc interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportGenesisStream", reflect.TypeOf((*MockAppModuleGenesis)(nil).ExportGenesisStream), ctx, cdc) +} + // GetQueryCmd mocks base method. func (m *MockAppModuleGenesis) GetQueryCmd() *cobra.Command { m.ctrl.T.Helper() @@ -331,6 +359,20 @@ func (mr *MockAppModuleGenesisMockRecorder) ValidateGenesis(arg0, arg1, arg2 int return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesis", reflect.TypeOf((*MockAppModuleGenesis)(nil).ValidateGenesis), arg0, arg1, arg2) } +// ValidateGenesisStream mocks base method. +func (m *MockAppModuleGenesis) ValidateGenesisStream(arg0 codec.JSONCodec, arg1 client.TxEncodingConfig, arg2 <-chan json.RawMessage) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateGenesisStream", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateGenesisStream indicates an expected call of ValidateGenesisStream. +func (mr *MockAppModuleGenesisMockRecorder) ValidateGenesisStream(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesisStream", reflect.TypeOf((*MockAppModuleGenesis)(nil).ValidateGenesisStream), arg0, arg1, arg2) +} + // MockAppModule is a mock of AppModule interface. type MockAppModule struct { ctrl *gomock.Controller @@ -435,6 +477,20 @@ func (mr *MockAppModuleMockRecorder) ExportGenesis(arg0, arg1 interface{}) *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportGenesis", reflect.TypeOf((*MockAppModule)(nil).ExportGenesis), arg0, arg1) } +// ExportGenesisStream mocks base method. +func (m *MockAppModule) ExportGenesisStream(ctx types0.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExportGenesisStream", ctx, cdc) + ret0, _ := ret[0].(<-chan json.RawMessage) + return ret0 +} + +// ExportGenesisStream indicates an expected call of ExportGenesisStream. +func (mr *MockAppModuleMockRecorder) ExportGenesisStream(ctx, cdc interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportGenesisStream", reflect.TypeOf((*MockAppModule)(nil).ExportGenesisStream), ctx, cdc) +} + // GetQueryCmd mocks base method. func (m *MockAppModule) GetQueryCmd() *cobra.Command { m.ctrl.T.Helper() @@ -618,3 +674,886 @@ func (mr *MockAppModuleMockRecorder) ValidateGenesis(arg0, arg1, arg2 interface{ mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesis", reflect.TypeOf((*MockAppModule)(nil).ValidateGenesis), arg0, arg1, arg2) } + +// ValidateGenesisStream mocks base method. +func (m *MockAppModule) ValidateGenesisStream(arg0 codec.JSONCodec, arg1 client.TxEncodingConfig, arg2 <-chan json.RawMessage) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateGenesisStream", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateGenesisStream indicates an expected call of ValidateGenesisStream. +func (mr *MockAppModuleMockRecorder) ValidateGenesisStream(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesisStream", reflect.TypeOf((*MockAppModule)(nil).ValidateGenesisStream), arg0, arg1, arg2) +} + +// MockBeginBlockAppModule is a mock of BeginBlockAppModule interface. +type MockBeginBlockAppModule struct { + ctrl *gomock.Controller + recorder *MockBeginBlockAppModuleMockRecorder +} + +// MockBeginBlockAppModuleMockRecorder is the mock recorder for MockBeginBlockAppModule. +type MockBeginBlockAppModuleMockRecorder struct { + mock *MockBeginBlockAppModule +} + +// NewMockBeginBlockAppModule creates a new mock instance. +func NewMockBeginBlockAppModule(ctrl *gomock.Controller) *MockBeginBlockAppModule { + mock := &MockBeginBlockAppModule{ctrl: ctrl} + mock.recorder = &MockBeginBlockAppModuleMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBeginBlockAppModule) EXPECT() *MockBeginBlockAppModuleMockRecorder { + return m.recorder +} + +// BeginBlock mocks base method. +func (m *MockBeginBlockAppModule) BeginBlock(arg0 types0.Context, arg1 types1.RequestBeginBlock) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "BeginBlock", arg0, arg1) +} + +// BeginBlock indicates an expected call of BeginBlock. +func (mr *MockBeginBlockAppModuleMockRecorder) BeginBlock(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BeginBlock", reflect.TypeOf((*MockBeginBlockAppModule)(nil).BeginBlock), arg0, arg1) +} + +// ConsensusVersion mocks base method. +func (m *MockBeginBlockAppModule) ConsensusVersion() uint64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConsensusVersion") + ret0, _ := ret[0].(uint64) + return ret0 +} + +// ConsensusVersion indicates an expected call of ConsensusVersion. +func (mr *MockBeginBlockAppModuleMockRecorder) ConsensusVersion() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConsensusVersion", reflect.TypeOf((*MockBeginBlockAppModule)(nil).ConsensusVersion)) +} + +// DefaultGenesis mocks base method. +func (m *MockBeginBlockAppModule) DefaultGenesis(arg0 codec.JSONCodec) json.RawMessage { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DefaultGenesis", arg0) + ret0, _ := ret[0].(json.RawMessage) + return ret0 +} + +// DefaultGenesis indicates an expected call of DefaultGenesis. +func (mr *MockBeginBlockAppModuleMockRecorder) DefaultGenesis(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DefaultGenesis", reflect.TypeOf((*MockBeginBlockAppModule)(nil).DefaultGenesis), arg0) +} + +// ExportGenesis mocks base method. +func (m *MockBeginBlockAppModule) ExportGenesis(arg0 types0.Context, arg1 codec.JSONCodec) json.RawMessage { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExportGenesis", arg0, arg1) + ret0, _ := ret[0].(json.RawMessage) + return ret0 +} + +// ExportGenesis indicates an expected call of ExportGenesis. +func (mr *MockBeginBlockAppModuleMockRecorder) ExportGenesis(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportGenesis", reflect.TypeOf((*MockBeginBlockAppModule)(nil).ExportGenesis), arg0, arg1) +} + +// ExportGenesisStream mocks base method. +func (m *MockBeginBlockAppModule) ExportGenesisStream(ctx types0.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExportGenesisStream", ctx, cdc) + ret0, _ := ret[0].(<-chan json.RawMessage) + return ret0 +} + +// ExportGenesisStream indicates an expected call of ExportGenesisStream. +func (mr *MockBeginBlockAppModuleMockRecorder) ExportGenesisStream(ctx, cdc interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportGenesisStream", reflect.TypeOf((*MockBeginBlockAppModule)(nil).ExportGenesisStream), ctx, cdc) +} + +// GetQueryCmd mocks base method. +func (m *MockBeginBlockAppModule) GetQueryCmd() *cobra.Command { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetQueryCmd") + ret0, _ := ret[0].(*cobra.Command) + return ret0 +} + +// GetQueryCmd indicates an expected call of GetQueryCmd. +func (mr *MockBeginBlockAppModuleMockRecorder) GetQueryCmd() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetQueryCmd", reflect.TypeOf((*MockBeginBlockAppModule)(nil).GetQueryCmd)) +} + +// GetTxCmd mocks base method. +func (m *MockBeginBlockAppModule) GetTxCmd() *cobra.Command { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTxCmd") + ret0, _ := ret[0].(*cobra.Command) + return ret0 +} + +// GetTxCmd indicates an expected call of GetTxCmd. +func (mr *MockBeginBlockAppModuleMockRecorder) GetTxCmd() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTxCmd", reflect.TypeOf((*MockBeginBlockAppModule)(nil).GetTxCmd)) +} + +// InitGenesis mocks base method. +func (m *MockBeginBlockAppModule) InitGenesis(arg0 types0.Context, arg1 codec.JSONCodec, arg2 json.RawMessage) []types1.ValidatorUpdate { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "InitGenesis", arg0, arg1, arg2) + ret0, _ := ret[0].([]types1.ValidatorUpdate) + return ret0 +} + +// InitGenesis indicates an expected call of InitGenesis. +func (mr *MockBeginBlockAppModuleMockRecorder) InitGenesis(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitGenesis", reflect.TypeOf((*MockBeginBlockAppModule)(nil).InitGenesis), arg0, arg1, arg2) +} + +// LegacyQuerierHandler mocks base method. +func (m *MockBeginBlockAppModule) LegacyQuerierHandler(arg0 *codec.LegacyAmino) types0.Querier { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LegacyQuerierHandler", arg0) + ret0, _ := ret[0].(types0.Querier) + return ret0 +} + +// LegacyQuerierHandler indicates an expected call of LegacyQuerierHandler. +func (mr *MockBeginBlockAppModuleMockRecorder) LegacyQuerierHandler(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LegacyQuerierHandler", reflect.TypeOf((*MockBeginBlockAppModule)(nil).LegacyQuerierHandler), arg0) +} + +// Name mocks base method. +func (m *MockBeginBlockAppModule) Name() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Name") + ret0, _ := ret[0].(string) + return ret0 +} + +// Name indicates an expected call of Name. +func (mr *MockBeginBlockAppModuleMockRecorder) Name() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockBeginBlockAppModule)(nil).Name)) +} + +// QuerierRoute mocks base method. +func (m *MockBeginBlockAppModule) QuerierRoute() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QuerierRoute") + ret0, _ := ret[0].(string) + return ret0 +} + +// QuerierRoute indicates an expected call of QuerierRoute. +func (mr *MockBeginBlockAppModuleMockRecorder) QuerierRoute() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QuerierRoute", reflect.TypeOf((*MockBeginBlockAppModule)(nil).QuerierRoute)) +} + +// RegisterGRPCGatewayRoutes mocks base method. +func (m *MockBeginBlockAppModule) RegisterGRPCGatewayRoutes(arg0 client.Context, arg1 *runtime.ServeMux) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterGRPCGatewayRoutes", arg0, arg1) +} + +// RegisterGRPCGatewayRoutes indicates an expected call of RegisterGRPCGatewayRoutes. +func (mr *MockBeginBlockAppModuleMockRecorder) RegisterGRPCGatewayRoutes(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterGRPCGatewayRoutes", reflect.TypeOf((*MockBeginBlockAppModule)(nil).RegisterGRPCGatewayRoutes), arg0, arg1) +} + +// RegisterInterfaces mocks base method. +func (m *MockBeginBlockAppModule) RegisterInterfaces(arg0 types.InterfaceRegistry) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterInterfaces", arg0) +} + +// RegisterInterfaces indicates an expected call of RegisterInterfaces. +func (mr *MockBeginBlockAppModuleMockRecorder) RegisterInterfaces(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterInterfaces", reflect.TypeOf((*MockBeginBlockAppModule)(nil).RegisterInterfaces), arg0) +} + +// RegisterInvariants mocks base method. +func (m *MockBeginBlockAppModule) RegisterInvariants(arg0 types0.InvariantRegistry) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterInvariants", arg0) +} + +// RegisterInvariants indicates an expected call of RegisterInvariants. +func (mr *MockBeginBlockAppModuleMockRecorder) RegisterInvariants(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterInvariants", reflect.TypeOf((*MockBeginBlockAppModule)(nil).RegisterInvariants), arg0) +} + +// RegisterLegacyAminoCodec mocks base method. +func (m *MockBeginBlockAppModule) RegisterLegacyAminoCodec(arg0 *codec.LegacyAmino) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterLegacyAminoCodec", arg0) +} + +// RegisterLegacyAminoCodec indicates an expected call of RegisterLegacyAminoCodec. +func (mr *MockBeginBlockAppModuleMockRecorder) RegisterLegacyAminoCodec(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterLegacyAminoCodec", reflect.TypeOf((*MockBeginBlockAppModule)(nil).RegisterLegacyAminoCodec), arg0) +} + +// RegisterRESTRoutes mocks base method. +func (m *MockBeginBlockAppModule) RegisterRESTRoutes(arg0 client.Context, arg1 *mux.Router) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterRESTRoutes", arg0, arg1) +} + +// RegisterRESTRoutes indicates an expected call of RegisterRESTRoutes. +func (mr *MockBeginBlockAppModuleMockRecorder) RegisterRESTRoutes(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterRESTRoutes", reflect.TypeOf((*MockBeginBlockAppModule)(nil).RegisterRESTRoutes), arg0, arg1) +} + +// RegisterServices mocks base method. +func (m *MockBeginBlockAppModule) RegisterServices(arg0 module.Configurator) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterServices", arg0) +} + +// RegisterServices indicates an expected call of RegisterServices. +func (mr *MockBeginBlockAppModuleMockRecorder) RegisterServices(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterServices", reflect.TypeOf((*MockBeginBlockAppModule)(nil).RegisterServices), arg0) +} + +// Route mocks base method. +func (m *MockBeginBlockAppModule) Route() types0.Route { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Route") + ret0, _ := ret[0].(types0.Route) + return ret0 +} + +// Route indicates an expected call of Route. +func (mr *MockBeginBlockAppModuleMockRecorder) Route() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Route", reflect.TypeOf((*MockBeginBlockAppModule)(nil).Route)) +} + +// ValidateGenesis mocks base method. +func (m *MockBeginBlockAppModule) ValidateGenesis(arg0 codec.JSONCodec, arg1 client.TxEncodingConfig, arg2 json.RawMessage) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateGenesis", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateGenesis indicates an expected call of ValidateGenesis. +func (mr *MockBeginBlockAppModuleMockRecorder) ValidateGenesis(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesis", reflect.TypeOf((*MockBeginBlockAppModule)(nil).ValidateGenesis), arg0, arg1, arg2) +} + +// ValidateGenesisStream mocks base method. +func (m *MockBeginBlockAppModule) ValidateGenesisStream(arg0 codec.JSONCodec, arg1 client.TxEncodingConfig, arg2 <-chan json.RawMessage) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateGenesisStream", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateGenesisStream indicates an expected call of ValidateGenesisStream. +func (mr *MockBeginBlockAppModuleMockRecorder) ValidateGenesisStream(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesisStream", reflect.TypeOf((*MockBeginBlockAppModule)(nil).ValidateGenesisStream), arg0, arg1, arg2) +} + +// MockMidBlockAppModule is a mock of MidBlockAppModule interface. +type MockMidBlockAppModule struct { + ctrl *gomock.Controller + recorder *MockMidBlockAppModuleMockRecorder +} + +// MockMidBlockAppModuleMockRecorder is the mock recorder for MockMidBlockAppModule. +type MockMidBlockAppModuleMockRecorder struct { + mock *MockMidBlockAppModule +} + +// NewMockMidBlockAppModule creates a new mock instance. +func NewMockMidBlockAppModule(ctrl *gomock.Controller) *MockMidBlockAppModule { + mock := &MockMidBlockAppModule{ctrl: ctrl} + mock.recorder = &MockMidBlockAppModuleMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockMidBlockAppModule) EXPECT() *MockMidBlockAppModuleMockRecorder { + return m.recorder +} + +// ConsensusVersion mocks base method. +func (m *MockMidBlockAppModule) ConsensusVersion() uint64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConsensusVersion") + ret0, _ := ret[0].(uint64) + return ret0 +} + +// ConsensusVersion indicates an expected call of ConsensusVersion. +func (mr *MockMidBlockAppModuleMockRecorder) ConsensusVersion() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConsensusVersion", reflect.TypeOf((*MockMidBlockAppModule)(nil).ConsensusVersion)) +} + +// DefaultGenesis mocks base method. +func (m *MockMidBlockAppModule) DefaultGenesis(arg0 codec.JSONCodec) json.RawMessage { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DefaultGenesis", arg0) + ret0, _ := ret[0].(json.RawMessage) + return ret0 +} + +// DefaultGenesis indicates an expected call of DefaultGenesis. +func (mr *MockMidBlockAppModuleMockRecorder) DefaultGenesis(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DefaultGenesis", reflect.TypeOf((*MockMidBlockAppModule)(nil).DefaultGenesis), arg0) +} + +// ExportGenesis mocks base method. +func (m *MockMidBlockAppModule) ExportGenesis(arg0 types0.Context, arg1 codec.JSONCodec) json.RawMessage { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExportGenesis", arg0, arg1) + ret0, _ := ret[0].(json.RawMessage) + return ret0 +} + +// ExportGenesis indicates an expected call of ExportGenesis. +func (mr *MockMidBlockAppModuleMockRecorder) ExportGenesis(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportGenesis", reflect.TypeOf((*MockMidBlockAppModule)(nil).ExportGenesis), arg0, arg1) +} + +// ExportGenesisStream mocks base method. +func (m *MockMidBlockAppModule) ExportGenesisStream(ctx types0.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExportGenesisStream", ctx, cdc) + ret0, _ := ret[0].(<-chan json.RawMessage) + return ret0 +} + +// ExportGenesisStream indicates an expected call of ExportGenesisStream. +func (mr *MockMidBlockAppModuleMockRecorder) ExportGenesisStream(ctx, cdc interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportGenesisStream", reflect.TypeOf((*MockMidBlockAppModule)(nil).ExportGenesisStream), ctx, cdc) +} + +// GetQueryCmd mocks base method. +func (m *MockMidBlockAppModule) GetQueryCmd() *cobra.Command { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetQueryCmd") + ret0, _ := ret[0].(*cobra.Command) + return ret0 +} + +// GetQueryCmd indicates an expected call of GetQueryCmd. +func (mr *MockMidBlockAppModuleMockRecorder) GetQueryCmd() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetQueryCmd", reflect.TypeOf((*MockMidBlockAppModule)(nil).GetQueryCmd)) +} + +// GetTxCmd mocks base method. +func (m *MockMidBlockAppModule) GetTxCmd() *cobra.Command { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTxCmd") + ret0, _ := ret[0].(*cobra.Command) + return ret0 +} + +// GetTxCmd indicates an expected call of GetTxCmd. +func (mr *MockMidBlockAppModuleMockRecorder) GetTxCmd() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTxCmd", reflect.TypeOf((*MockMidBlockAppModule)(nil).GetTxCmd)) +} + +// InitGenesis mocks base method. +func (m *MockMidBlockAppModule) InitGenesis(arg0 types0.Context, arg1 codec.JSONCodec, arg2 json.RawMessage) []types1.ValidatorUpdate { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "InitGenesis", arg0, arg1, arg2) + ret0, _ := ret[0].([]types1.ValidatorUpdate) + return ret0 +} + +// InitGenesis indicates an expected call of InitGenesis. +func (mr *MockMidBlockAppModuleMockRecorder) InitGenesis(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitGenesis", reflect.TypeOf((*MockMidBlockAppModule)(nil).InitGenesis), arg0, arg1, arg2) +} + +// LegacyQuerierHandler mocks base method. +func (m *MockMidBlockAppModule) LegacyQuerierHandler(arg0 *codec.LegacyAmino) types0.Querier { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LegacyQuerierHandler", arg0) + ret0, _ := ret[0].(types0.Querier) + return ret0 +} + +// LegacyQuerierHandler indicates an expected call of LegacyQuerierHandler. +func (mr *MockMidBlockAppModuleMockRecorder) LegacyQuerierHandler(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LegacyQuerierHandler", reflect.TypeOf((*MockMidBlockAppModule)(nil).LegacyQuerierHandler), arg0) +} + +// MidBlock mocks base method. +func (m *MockMidBlockAppModule) MidBlock(arg0 types0.Context, arg1 int64) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "MidBlock", arg0, arg1) +} + +// MidBlock indicates an expected call of MidBlock. +func (mr *MockMidBlockAppModuleMockRecorder) MidBlock(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MidBlock", reflect.TypeOf((*MockMidBlockAppModule)(nil).MidBlock), arg0, arg1) +} + +// Name mocks base method. +func (m *MockMidBlockAppModule) Name() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Name") + ret0, _ := ret[0].(string) + return ret0 +} + +// Name indicates an expected call of Name. +func (mr *MockMidBlockAppModuleMockRecorder) Name() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockMidBlockAppModule)(nil).Name)) +} + +// QuerierRoute mocks base method. +func (m *MockMidBlockAppModule) QuerierRoute() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QuerierRoute") + ret0, _ := ret[0].(string) + return ret0 +} + +// QuerierRoute indicates an expected call of QuerierRoute. +func (mr *MockMidBlockAppModuleMockRecorder) QuerierRoute() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QuerierRoute", reflect.TypeOf((*MockMidBlockAppModule)(nil).QuerierRoute)) +} + +// RegisterGRPCGatewayRoutes mocks base method. +func (m *MockMidBlockAppModule) RegisterGRPCGatewayRoutes(arg0 client.Context, arg1 *runtime.ServeMux) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterGRPCGatewayRoutes", arg0, arg1) +} + +// RegisterGRPCGatewayRoutes indicates an expected call of RegisterGRPCGatewayRoutes. +func (mr *MockMidBlockAppModuleMockRecorder) RegisterGRPCGatewayRoutes(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterGRPCGatewayRoutes", reflect.TypeOf((*MockMidBlockAppModule)(nil).RegisterGRPCGatewayRoutes), arg0, arg1) +} + +// RegisterInterfaces mocks base method. +func (m *MockMidBlockAppModule) RegisterInterfaces(arg0 types.InterfaceRegistry) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterInterfaces", arg0) +} + +// RegisterInterfaces indicates an expected call of RegisterInterfaces. +func (mr *MockMidBlockAppModuleMockRecorder) RegisterInterfaces(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterInterfaces", reflect.TypeOf((*MockMidBlockAppModule)(nil).RegisterInterfaces), arg0) +} + +// RegisterInvariants mocks base method. +func (m *MockMidBlockAppModule) RegisterInvariants(arg0 types0.InvariantRegistry) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterInvariants", arg0) +} + +// RegisterInvariants indicates an expected call of RegisterInvariants. +func (mr *MockMidBlockAppModuleMockRecorder) RegisterInvariants(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterInvariants", reflect.TypeOf((*MockMidBlockAppModule)(nil).RegisterInvariants), arg0) +} + +// RegisterLegacyAminoCodec mocks base method. +func (m *MockMidBlockAppModule) RegisterLegacyAminoCodec(arg0 *codec.LegacyAmino) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterLegacyAminoCodec", arg0) +} + +// RegisterLegacyAminoCodec indicates an expected call of RegisterLegacyAminoCodec. +func (mr *MockMidBlockAppModuleMockRecorder) RegisterLegacyAminoCodec(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterLegacyAminoCodec", reflect.TypeOf((*MockMidBlockAppModule)(nil).RegisterLegacyAminoCodec), arg0) +} + +// RegisterRESTRoutes mocks base method. +func (m *MockMidBlockAppModule) RegisterRESTRoutes(arg0 client.Context, arg1 *mux.Router) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterRESTRoutes", arg0, arg1) +} + +// RegisterRESTRoutes indicates an expected call of RegisterRESTRoutes. +func (mr *MockMidBlockAppModuleMockRecorder) RegisterRESTRoutes(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterRESTRoutes", reflect.TypeOf((*MockMidBlockAppModule)(nil).RegisterRESTRoutes), arg0, arg1) +} + +// RegisterServices mocks base method. +func (m *MockMidBlockAppModule) RegisterServices(arg0 module.Configurator) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterServices", arg0) +} + +// RegisterServices indicates an expected call of RegisterServices. +func (mr *MockMidBlockAppModuleMockRecorder) RegisterServices(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterServices", reflect.TypeOf((*MockMidBlockAppModule)(nil).RegisterServices), arg0) +} + +// Route mocks base method. +func (m *MockMidBlockAppModule) Route() types0.Route { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Route") + ret0, _ := ret[0].(types0.Route) + return ret0 +} + +// Route indicates an expected call of Route. +func (mr *MockMidBlockAppModuleMockRecorder) Route() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Route", reflect.TypeOf((*MockMidBlockAppModule)(nil).Route)) +} + +// ValidateGenesis mocks base method. +func (m *MockMidBlockAppModule) ValidateGenesis(arg0 codec.JSONCodec, arg1 client.TxEncodingConfig, arg2 json.RawMessage) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateGenesis", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateGenesis indicates an expected call of ValidateGenesis. +func (mr *MockMidBlockAppModuleMockRecorder) ValidateGenesis(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesis", reflect.TypeOf((*MockMidBlockAppModule)(nil).ValidateGenesis), arg0, arg1, arg2) +} + +// ValidateGenesisStream mocks base method. +func (m *MockMidBlockAppModule) ValidateGenesisStream(arg0 codec.JSONCodec, arg1 client.TxEncodingConfig, arg2 <-chan json.RawMessage) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateGenesisStream", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateGenesisStream indicates an expected call of ValidateGenesisStream. +func (mr *MockMidBlockAppModuleMockRecorder) ValidateGenesisStream(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesisStream", reflect.TypeOf((*MockMidBlockAppModule)(nil).ValidateGenesisStream), arg0, arg1, arg2) +} + +// MockEndBlockAppModule is a mock of EndBlockAppModule interface. +type MockEndBlockAppModule struct { + ctrl *gomock.Controller + recorder *MockEndBlockAppModuleMockRecorder +} + +// MockEndBlockAppModuleMockRecorder is the mock recorder for MockEndBlockAppModule. +type MockEndBlockAppModuleMockRecorder struct { + mock *MockEndBlockAppModule +} + +// NewMockEndBlockAppModule creates a new mock instance. +func NewMockEndBlockAppModule(ctrl *gomock.Controller) *MockEndBlockAppModule { + mock := &MockEndBlockAppModule{ctrl: ctrl} + mock.recorder = &MockEndBlockAppModuleMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockEndBlockAppModule) EXPECT() *MockEndBlockAppModuleMockRecorder { + return m.recorder +} + +// ConsensusVersion mocks base method. +func (m *MockEndBlockAppModule) ConsensusVersion() uint64 { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ConsensusVersion") + ret0, _ := ret[0].(uint64) + return ret0 +} + +// ConsensusVersion indicates an expected call of ConsensusVersion. +func (mr *MockEndBlockAppModuleMockRecorder) ConsensusVersion() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConsensusVersion", reflect.TypeOf((*MockEndBlockAppModule)(nil).ConsensusVersion)) +} + +// DefaultGenesis mocks base method. +func (m *MockEndBlockAppModule) DefaultGenesis(arg0 codec.JSONCodec) json.RawMessage { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DefaultGenesis", arg0) + ret0, _ := ret[0].(json.RawMessage) + return ret0 +} + +// DefaultGenesis indicates an expected call of DefaultGenesis. +func (mr *MockEndBlockAppModuleMockRecorder) DefaultGenesis(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DefaultGenesis", reflect.TypeOf((*MockEndBlockAppModule)(nil).DefaultGenesis), arg0) +} + +// EndBlock mocks base method. +func (m *MockEndBlockAppModule) EndBlock(arg0 types0.Context, arg1 types1.RequestEndBlock) []types1.ValidatorUpdate { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EndBlock", arg0, arg1) + ret0, _ := ret[0].([]types1.ValidatorUpdate) + return ret0 +} + +// EndBlock indicates an expected call of EndBlock. +func (mr *MockEndBlockAppModuleMockRecorder) EndBlock(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EndBlock", reflect.TypeOf((*MockEndBlockAppModule)(nil).EndBlock), arg0, arg1) +} + +// ExportGenesis mocks base method. +func (m *MockEndBlockAppModule) ExportGenesis(arg0 types0.Context, arg1 codec.JSONCodec) json.RawMessage { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExportGenesis", arg0, arg1) + ret0, _ := ret[0].(json.RawMessage) + return ret0 +} + +// ExportGenesis indicates an expected call of ExportGenesis. +func (mr *MockEndBlockAppModuleMockRecorder) ExportGenesis(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportGenesis", reflect.TypeOf((*MockEndBlockAppModule)(nil).ExportGenesis), arg0, arg1) +} + +// ExportGenesisStream mocks base method. +func (m *MockEndBlockAppModule) ExportGenesisStream(ctx types0.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExportGenesisStream", ctx, cdc) + ret0, _ := ret[0].(<-chan json.RawMessage) + return ret0 +} + +// ExportGenesisStream indicates an expected call of ExportGenesisStream. +func (mr *MockEndBlockAppModuleMockRecorder) ExportGenesisStream(ctx, cdc interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExportGenesisStream", reflect.TypeOf((*MockEndBlockAppModule)(nil).ExportGenesisStream), ctx, cdc) +} + +// GetQueryCmd mocks base method. +func (m *MockEndBlockAppModule) GetQueryCmd() *cobra.Command { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetQueryCmd") + ret0, _ := ret[0].(*cobra.Command) + return ret0 +} + +// GetQueryCmd indicates an expected call of GetQueryCmd. +func (mr *MockEndBlockAppModuleMockRecorder) GetQueryCmd() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetQueryCmd", reflect.TypeOf((*MockEndBlockAppModule)(nil).GetQueryCmd)) +} + +// GetTxCmd mocks base method. +func (m *MockEndBlockAppModule) GetTxCmd() *cobra.Command { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTxCmd") + ret0, _ := ret[0].(*cobra.Command) + return ret0 +} + +// GetTxCmd indicates an expected call of GetTxCmd. +func (mr *MockEndBlockAppModuleMockRecorder) GetTxCmd() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTxCmd", reflect.TypeOf((*MockEndBlockAppModule)(nil).GetTxCmd)) +} + +// InitGenesis mocks base method. +func (m *MockEndBlockAppModule) InitGenesis(arg0 types0.Context, arg1 codec.JSONCodec, arg2 json.RawMessage) []types1.ValidatorUpdate { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "InitGenesis", arg0, arg1, arg2) + ret0, _ := ret[0].([]types1.ValidatorUpdate) + return ret0 +} + +// InitGenesis indicates an expected call of InitGenesis. +func (mr *MockEndBlockAppModuleMockRecorder) InitGenesis(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitGenesis", reflect.TypeOf((*MockEndBlockAppModule)(nil).InitGenesis), arg0, arg1, arg2) +} + +// LegacyQuerierHandler mocks base method. +func (m *MockEndBlockAppModule) LegacyQuerierHandler(arg0 *codec.LegacyAmino) types0.Querier { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LegacyQuerierHandler", arg0) + ret0, _ := ret[0].(types0.Querier) + return ret0 +} + +// LegacyQuerierHandler indicates an expected call of LegacyQuerierHandler. +func (mr *MockEndBlockAppModuleMockRecorder) LegacyQuerierHandler(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LegacyQuerierHandler", reflect.TypeOf((*MockEndBlockAppModule)(nil).LegacyQuerierHandler), arg0) +} + +// Name mocks base method. +func (m *MockEndBlockAppModule) Name() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Name") + ret0, _ := ret[0].(string) + return ret0 +} + +// Name indicates an expected call of Name. +func (mr *MockEndBlockAppModuleMockRecorder) Name() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockEndBlockAppModule)(nil).Name)) +} + +// QuerierRoute mocks base method. +func (m *MockEndBlockAppModule) QuerierRoute() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "QuerierRoute") + ret0, _ := ret[0].(string) + return ret0 +} + +// QuerierRoute indicates an expected call of QuerierRoute. +func (mr *MockEndBlockAppModuleMockRecorder) QuerierRoute() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QuerierRoute", reflect.TypeOf((*MockEndBlockAppModule)(nil).QuerierRoute)) +} + +// RegisterGRPCGatewayRoutes mocks base method. +func (m *MockEndBlockAppModule) RegisterGRPCGatewayRoutes(arg0 client.Context, arg1 *runtime.ServeMux) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterGRPCGatewayRoutes", arg0, arg1) +} + +// RegisterGRPCGatewayRoutes indicates an expected call of RegisterGRPCGatewayRoutes. +func (mr *MockEndBlockAppModuleMockRecorder) RegisterGRPCGatewayRoutes(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterGRPCGatewayRoutes", reflect.TypeOf((*MockEndBlockAppModule)(nil).RegisterGRPCGatewayRoutes), arg0, arg1) +} + +// RegisterInterfaces mocks base method. +func (m *MockEndBlockAppModule) RegisterInterfaces(arg0 types.InterfaceRegistry) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterInterfaces", arg0) +} + +// RegisterInterfaces indicates an expected call of RegisterInterfaces. +func (mr *MockEndBlockAppModuleMockRecorder) RegisterInterfaces(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterInterfaces", reflect.TypeOf((*MockEndBlockAppModule)(nil).RegisterInterfaces), arg0) +} + +// RegisterInvariants mocks base method. +func (m *MockEndBlockAppModule) RegisterInvariants(arg0 types0.InvariantRegistry) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterInvariants", arg0) +} + +// RegisterInvariants indicates an expected call of RegisterInvariants. +func (mr *MockEndBlockAppModuleMockRecorder) RegisterInvariants(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterInvariants", reflect.TypeOf((*MockEndBlockAppModule)(nil).RegisterInvariants), arg0) +} + +// RegisterLegacyAminoCodec mocks base method. +func (m *MockEndBlockAppModule) RegisterLegacyAminoCodec(arg0 *codec.LegacyAmino) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterLegacyAminoCodec", arg0) +} + +// RegisterLegacyAminoCodec indicates an expected call of RegisterLegacyAminoCodec. +func (mr *MockEndBlockAppModuleMockRecorder) RegisterLegacyAminoCodec(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterLegacyAminoCodec", reflect.TypeOf((*MockEndBlockAppModule)(nil).RegisterLegacyAminoCodec), arg0) +} + +// RegisterRESTRoutes mocks base method. +func (m *MockEndBlockAppModule) RegisterRESTRoutes(arg0 client.Context, arg1 *mux.Router) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterRESTRoutes", arg0, arg1) +} + +// RegisterRESTRoutes indicates an expected call of RegisterRESTRoutes. +func (mr *MockEndBlockAppModuleMockRecorder) RegisterRESTRoutes(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterRESTRoutes", reflect.TypeOf((*MockEndBlockAppModule)(nil).RegisterRESTRoutes), arg0, arg1) +} + +// RegisterServices mocks base method. +func (m *MockEndBlockAppModule) RegisterServices(arg0 module.Configurator) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RegisterServices", arg0) +} + +// RegisterServices indicates an expected call of RegisterServices. +func (mr *MockEndBlockAppModuleMockRecorder) RegisterServices(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterServices", reflect.TypeOf((*MockEndBlockAppModule)(nil).RegisterServices), arg0) +} + +// Route mocks base method. +func (m *MockEndBlockAppModule) Route() types0.Route { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Route") + ret0, _ := ret[0].(types0.Route) + return ret0 +} + +// Route indicates an expected call of Route. +func (mr *MockEndBlockAppModuleMockRecorder) Route() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Route", reflect.TypeOf((*MockEndBlockAppModule)(nil).Route)) +} + +// ValidateGenesis mocks base method. +func (m *MockEndBlockAppModule) ValidateGenesis(arg0 codec.JSONCodec, arg1 client.TxEncodingConfig, arg2 json.RawMessage) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateGenesis", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateGenesis indicates an expected call of ValidateGenesis. +func (mr *MockEndBlockAppModuleMockRecorder) ValidateGenesis(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesis", reflect.TypeOf((*MockEndBlockAppModule)(nil).ValidateGenesis), arg0, arg1, arg2) +} + +// ValidateGenesisStream mocks base method. +func (m *MockEndBlockAppModule) ValidateGenesisStream(arg0 codec.JSONCodec, arg1 client.TxEncodingConfig, arg2 <-chan json.RawMessage) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ValidateGenesisStream", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// ValidateGenesisStream indicates an expected call of ValidateGenesisStream. +func (mr *MockEndBlockAppModuleMockRecorder) ValidateGenesisStream(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateGenesisStream", reflect.TypeOf((*MockEndBlockAppModule)(nil).ValidateGenesisStream), arg0, arg1, arg2) +} diff --git a/types/genesis/genesis.go b/types/genesis/genesis.go new file mode 100644 index 000000000..d7bc04f1c --- /dev/null +++ b/types/genesis/genesis.go @@ -0,0 +1,68 @@ +package genesis + +import ( + "bufio" + "bytes" + "fmt" + "io" + "os" + "strings" +) + +type GenesisImportConfig struct { + StreamGenesisImport bool + GenesisStreamFile string +} + +const bufferSize = 100000 + +func IngestGenesisFileLineByLine(filename string) <-chan string { + lines := make(chan string) + + go func() { + defer close(lines) + + file, err := os.Open(filename) + if err != nil { + fmt.Println("Error opening file:", err) + return + } + defer file.Close() + + reader := bufio.NewReader(file) + + buffer := make([]byte, bufferSize) + lineBuf := new(strings.Builder) + + for { + bytesRead, err := reader.Read(buffer) + if err != nil && err != io.EOF { + fmt.Println("Error reading file:", err) + return + } + + chunk := buffer[:bytesRead] + for len(chunk) > 0 { + i := bytes.IndexByte(chunk, '\n') + if i >= 0 { + lineBuf.Write(chunk[:i]) + lines <- lineBuf.String() + lineBuf.Reset() + chunk = chunk[i+1:] + } else { + lineBuf.Write(chunk) + break + } + } + + if err == io.EOF { + if lineBuf.Len() > 0 { + lines <- lineBuf.String() + } + break + } + } + }() + + return lines +} diff --git a/types/module/module.go b/types/module/module.go index b4eecec86..f7e305453 100644 --- a/types/module/module.go +++ b/types/module/module.go @@ -45,6 +45,7 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + genesistypes "github.com/cosmos/cosmos-sdk/types/genesis" ) // AppModuleBasic is the standard form for basic non-dependant elements of an application module. @@ -55,6 +56,7 @@ type AppModuleBasic interface { DefaultGenesis(codec.JSONCodec) json.RawMessage ValidateGenesis(codec.JSONCodec, client.TxEncodingConfig, json.RawMessage) error + ValidateGenesisStream(codec.JSONCodec, client.TxEncodingConfig, <-chan json.RawMessage) error // client functionality RegisterRESTRoutes(client.Context, *mux.Router) @@ -110,6 +112,32 @@ func (bm BasicManager) ValidateGenesis(cdc codec.JSONCodec, txEncCfg client.TxEn return nil } +// ValidateGenesisStream performs genesis state validation on all modules in a streaming fashion. +func (bm BasicManager) ValidateGenesisStream(cdc codec.JSONCodec, txEncCfg client.TxEncodingConfig, moduleName string, genesisCh <-chan json.RawMessage, doneCh <-chan struct{}, errCh chan<- error) { + moduleGenesisCh := make(chan json.RawMessage) + moduleDoneCh := make(chan struct{}) + + var err error + + go func() { + err = bm[moduleName].ValidateGenesisStream(cdc, txEncCfg, moduleGenesisCh) + if err != nil { + errCh <- err + } + moduleDoneCh <- struct{}{} + }() + + for { + select { + case <-doneCh: + close(moduleGenesisCh) + return + case genesisChunk := <-genesisCh: + moduleGenesisCh <- genesisChunk + } + } +} + // RegisterRESTRoutes registers all module rest routes func (bm BasicManager) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { for _, b := range bm { @@ -154,6 +182,7 @@ type AppModuleGenesis interface { InitGenesis(sdk.Context, codec.JSONCodec, json.RawMessage) []abci.ValidatorUpdate ExportGenesis(sdk.Context, codec.JSONCodec) json.RawMessage + ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage } // AppModule is the standard form for an application module @@ -330,23 +359,80 @@ func (m *Manager) RegisterServices(cfg Configurator) { } } +type AppState struct { + Module string `json:"module"` + Data json.RawMessage `json:"data"` +} + +type ModuleState struct { + AppState AppState `json:"app_state"` +} + +func parseModule(jsonStr string) (*ModuleState, error) { + var module ModuleState + err := json.Unmarshal([]byte(jsonStr), &module) + if err != nil { + return nil, err + } + if module.AppState.Module == "" { + return nil, fmt.Errorf("module name is empty") + } + return &module, nil +} + // InitGenesis performs init genesis functionality for modules -func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage) abci.ResponseInitChain { +func (m *Manager) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, genesisData map[string]json.RawMessage, genesisImportConfig genesistypes.GenesisImportConfig) abci.ResponseInitChain { var validatorUpdates []abci.ValidatorUpdate - for _, moduleName := range m.OrderInitGenesis { - if genesisData[moduleName] == nil { - continue + if genesisImportConfig.StreamGenesisImport { + lines := genesistypes.IngestGenesisFileLineByLine(genesisImportConfig.GenesisStreamFile) + errCh := make(chan error, 1) + seenModules := make(map[string]bool) + var moduleName string + go func() { + for line := range lines { + moduleState, err := parseModule(line) + if err != nil { + moduleName = "genesisDoc" + } else { + moduleName = moduleState.AppState.Module + } + if moduleName == "genesisDoc" { + continue + } + if seenModules[moduleName] { + errCh <- fmt.Errorf("module %s seen twice in genesis file", moduleName) + return + } + moduleValUpdates := m.Modules[moduleName].InitGenesis(ctx, cdc, moduleState.AppState.Data) + if len(moduleValUpdates) > 0 { + if len(validatorUpdates) > 0 { + panic("validator InitGenesis updates already set by a previous module") + } + validatorUpdates = moduleValUpdates + } + } + errCh <- nil + }() + err := <-errCh + if err != nil { + panic(err) } + } else { + for _, moduleName := range m.OrderInitGenesis { + if genesisData[moduleName] == nil { + continue + } - moduleValUpdates := m.Modules[moduleName].InitGenesis(ctx, cdc, genesisData[moduleName]) + moduleValUpdates := m.Modules[moduleName].InitGenesis(ctx, cdc, genesisData[moduleName]) - // use these validator updates if provided, the module manager assumes - // only one module will update the validator set - if len(moduleValUpdates) > 0 { - if len(validatorUpdates) > 0 { - panic("validator InitGenesis updates already set by a previous module") + // use these validator updates if provided, the module manager assumes + // only one module will update the validator set + if len(moduleValUpdates) > 0 { + if len(validatorUpdates) > 0 { + panic("validator InitGenesis updates already set by a previous module") + } + validatorUpdates = moduleValUpdates } - validatorUpdates = moduleValUpdates } } @@ -365,6 +451,22 @@ func (m *Manager) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) map[string return genesisData } +func (m *Manager) ProcessGenesisPerModule(ctx sdk.Context, cdc codec.JSONCodec, process func(string, json.RawMessage) error) error { + // It's important that we use OrderInitGenesis here instead of OrderExportGenesis because the order of exporting + // doesn't matter much but the order of importing does due to invariant checks and how we are streaming the genesis + // file here + for _, moduleName := range m.OrderInitGenesis { + ch := m.Modules[moduleName].ExportGenesisStream(ctx, cdc) + for msg := range ch { + err := process(moduleName, msg) + if err != nil { + return err + } + } + } + return nil +} + // assertNoForgottenModules checks that we didn't forget any modules in the // SetOrder* functions. func (m *Manager) assertNoForgottenModules(setOrderFnName string, moduleNames []string) { diff --git a/types/module/module_test.go b/types/module/module_test.go index fab8c7049..41ff61186 100644 --- a/types/module/module_test.go +++ b/types/module/module_test.go @@ -3,9 +3,10 @@ package module_test import ( "encoding/json" "errors" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "testing" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/codec/types" "github.com/golang/mock/gomock" @@ -18,6 +19,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/tests/mocks" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/genesis" "github.com/cosmos/cosmos-sdk/types/module" ) @@ -210,7 +212,7 @@ func TestManager_InitGenesis(t *testing.T) { genesisData := map[string]json.RawMessage{"module1": json.RawMessage(`{"key": "value"}`)} mockAppModule1.EXPECT().InitGenesis(gomock.Eq(ctx), gomock.Eq(cdc), gomock.Eq(genesisData["module1"])).Times(1).Return(nil) - require.Equal(t, abci.ResponseInitChain{Validators: []abci.ValidatorUpdate(nil)}, mm.InitGenesis(ctx, cdc, genesisData)) + require.Equal(t, abci.ResponseInitChain{Validators: []abci.ValidatorUpdate(nil)}, mm.InitGenesis(ctx, cdc, genesisData, genesis.GenesisImportConfig{})) // test panic genesisData = map[string]json.RawMessage{ @@ -218,7 +220,7 @@ func TestManager_InitGenesis(t *testing.T) { "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{{}}) - require.Panics(t, func() { mm.InitGenesis(ctx, cdc, genesisData) }) + require.Panics(t, func() { mm.InitGenesis(ctx, cdc, genesisData, genesis.GenesisImportConfig{}) }) } func TestManager_ExportGenesis(t *testing.T) { diff --git a/x/accesscontrol/module.go b/x/accesscontrol/module.go index 922c6a091..6ee494b42 100644 --- a/x/accesscontrol/module.go +++ b/x/accesscontrol/module.go @@ -68,6 +68,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod return data.Params.Validate() } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the accesscontrol module. func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) {} @@ -151,6 +161,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(genState) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 2 } diff --git a/x/auth/module.go b/x/auth/module.go index ef2d1f2e2..35289a2e0 100644 --- a/x/auth/module.go +++ b/x/auth/module.go @@ -60,6 +60,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod return types.ValidateGenesis(data) } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the auth module. func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { rest.RegisterRoutes(clientCtx, rtr, types.StoreKey) @@ -156,6 +166,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(gs) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 3 } diff --git a/x/auth/vesting/module.go b/x/auth/vesting/module.go index 78296fdd6..b50fb1c6e 100644 --- a/x/auth/vesting/module.go +++ b/x/auth/vesting/module.go @@ -54,6 +54,16 @@ func (AppModuleBasic) ValidateGenesis(_ codec.JSONCodec, _ client.TxEncodingConf return nil } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers module's REST handlers. Currently, this is a no-op. func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {} @@ -120,5 +130,14 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONCodec) json.RawMe return am.DefaultGenesis(cdc) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/authz/module/module.go b/x/authz/module/module.go index 2c652e1d8..da2b54b9b 100644 --- a/x/authz/module/module.go +++ b/x/authz/module/module.go @@ -70,6 +70,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config sdkclient.TxEn return authz.ValidateGenesis(data) } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config sdkclient.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the authz module. func (AppModuleBasic) RegisterRESTRoutes(clientCtx sdkclient.Context, r *mux.Router) { } @@ -150,6 +160,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(gs) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/bank/module.go b/x/bank/module.go index 000c72070..4a9aabe50 100644 --- a/x/bank/module.go +++ b/x/bank/module.go @@ -66,6 +66,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingCo return data.Validate() } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the bank module. func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { rest.RegisterHandlers(clientCtx, rtr) @@ -160,6 +170,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(gs) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 2 } diff --git a/x/bank/types/genesis.go b/x/bank/types/genesis.go index 68419eaab..5a4b981f5 100644 --- a/x/bank/types/genesis.go +++ b/x/bank/types/genesis.go @@ -15,23 +15,10 @@ func (gs GenesisState) Validate() error { return err } - seenBalances := make(map[string]bool) seenMetadatas := make(map[string]bool) - - totalSupply := sdk.Coins{} - - for _, balance := range gs.Balances { - if seenBalances[balance.Address] { - return fmt.Errorf("duplicate balance for address %s", balance.Address) - } - - if err := balance.Validate(); err != nil { - return err - } - - seenBalances[balance.Address] = true - - totalSupply = totalSupply.Add(balance.Coins...) + totalSupply, err := getTotalSupply(&gs) + if err != nil { + return err } for _, metadata := range gs.DenomMetadata { @@ -61,6 +48,48 @@ func (gs GenesisState) Validate() error { return nil } +func getTotalSupply(genState *GenesisState) (sdk.Coins, error) { + totalSupply := sdk.Coins{} + totalWeiBalance := sdk.ZeroInt() + + genState.Balances = SanitizeGenesisBalances(genState.Balances) + seenBalances := make(map[string]bool) + for _, balance := range genState.Balances { + if seenBalances[balance.Address] { + return nil, fmt.Errorf("duplicate balance for address %s", balance.Address) + } + seenBalances[balance.Address] = true + coins := balance.Coins + err := balance.Validate() + if err != nil { + return nil, err + } + totalSupply = totalSupply.Add(coins...) + } + for _, weiBalance := range genState.WeiBalances { + totalWeiBalance = totalWeiBalance.Add(weiBalance.Amount) + } + weiInUsei, weiRemainder := SplitUseiWeiAmount(totalWeiBalance) + if !weiRemainder.IsZero() { + return nil, fmt.Errorf("non-zero wei remainder %s", weiRemainder) + } + baseDenom, err := sdk.GetBaseDenom() + if err != nil { + if !weiInUsei.IsZero() { + return nil, fmt.Errorf("base denom is not registered %s yet there exists wei balance %s", err, weiInUsei) + } + } else { + totalSupply = totalSupply.Add(sdk.NewCoin(baseDenom, weiInUsei)) + } + return totalSupply, nil +} + +var OneUseiInWei sdk.Int = sdk.NewInt(1_000_000_000_000) + +func SplitUseiWeiAmount(amt sdk.Int) (sdk.Int, sdk.Int) { + return amt.Quo(OneUseiInWei), amt.Mod(OneUseiInWei) +} + // NewGenesisState creates a new genesis state. func NewGenesisState(params Params, balances []Balance, supply sdk.Coins, denomMetaData []Metadata, weiBalances []WeiBalance) *GenesisState { return &GenesisState{ diff --git a/x/bank/types/metadata.go b/x/bank/types/metadata.go index 9583b85ce..a6df1bf42 100644 --- a/x/bank/types/metadata.go +++ b/x/bank/types/metadata.go @@ -9,12 +9,12 @@ import ( ) // Validate performs a basic validation of the coin metadata fields. It checks: -// - Name and Symbol are not blank -// - Base and Display denominations are valid coin denominations -// - Base and Display denominations are present in the DenomUnit slice -// - Base denomination has exponent 0 -// - Denomination units are sorted in ascending order -// - Denomination units not duplicated +// - Name and Symbol are not blank +// - Base and Display denominations are valid coin denominations +// - Base and Display denominations are present in the DenomUnit slice +// - Base denomination has exponent 0 +// - Denomination units are sorted in ascending order +// - Denomination units not duplicated func (m Metadata) Validate() error { if strings.TrimSpace(m.Name) == "" { return errors.New("name field cannot be blank") diff --git a/x/capability/module.go b/x/capability/module.go index d448f0db4..c64d55d65 100644 --- a/x/capability/module.go +++ b/x/capability/module.go @@ -68,6 +68,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod return genState.Validate() } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the capability module's REST service handlers. func (a AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {} @@ -138,6 +148,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(genState) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/crisis/module.go b/x/crisis/module.go index 445ef6860..42c39ca31 100644 --- a/x/crisis/module.go +++ b/x/crisis/module.go @@ -60,6 +60,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod return types.ValidateGenesis(&data) } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers no REST routes for the crisis module. func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {} @@ -156,6 +166,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(gs) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/distribution/keeper/store.go b/x/distribution/keeper/store.go index 0203ee13f..48b6ea9a0 100644 --- a/x/distribution/keeper/store.go +++ b/x/distribution/keeper/store.go @@ -1,6 +1,7 @@ package keeper import ( + gogotypes "github.com/gogo/protobuf/types" sdk "github.com/cosmos/cosmos-sdk/types" diff --git a/x/distribution/module.go b/x/distribution/module.go index bb958b2c6..2fcc4601b 100644 --- a/x/distribution/module.go +++ b/x/distribution/module.go @@ -62,6 +62,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config sdkclient.TxEn return types.ValidateGenesis(&data) } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config sdkclient.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the distribution module. func (AppModuleBasic) RegisterRESTRoutes(clientCtx sdkclient.Context, rtr *mux.Router) { rest.RegisterHandlers(clientCtx, rtr) @@ -161,6 +171,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(gs) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 2 } diff --git a/x/evidence/module.go b/x/evidence/module.go index f7ce284b1..76abae56d 100644 --- a/x/evidence/module.go +++ b/x/evidence/module.go @@ -74,6 +74,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod return gs.Validate() } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the evidence module's REST service handlers. func (a AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { evidenceRESTHandlers := make([]rest.EvidenceRESTHandler, len(a.evidenceHandlers)) @@ -175,6 +185,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(ExportGenesis(ctx, am.keeper)) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/feegrant/module/module.go b/x/feegrant/module/module.go index 421ecfca1..fd7556142 100644 --- a/x/feegrant/module/module.go +++ b/x/feegrant/module/module.go @@ -11,6 +11,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" + "github.com/cosmos/cosmos-sdk/client" sdkclient "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -81,6 +82,16 @@ func (a AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config sdkclient.Tx return feegrant.ValidateGenesis(data) } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the feegrant module. func (AppModuleBasic) RegisterRESTRoutes(ctx sdkclient.Context, rtr *mux.Router) {} @@ -170,6 +181,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(gs) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/genutil/client/cli/validate_genesis.go b/x/genutil/client/cli/validate_genesis.go index 6c8e27dda..d28669577 100644 --- a/x/genutil/client/cli/validate_genesis.go +++ b/x/genutil/client/cli/validate_genesis.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" + genesistypes "github.com/cosmos/cosmos-sdk/types/genesis" "github.com/spf13/cobra" tmtypes "github.com/tendermint/tendermint/types" @@ -12,11 +13,14 @@ import ( "github.com/cosmos/cosmos-sdk/types/module" ) -const chainUpgradeGuide = "https://docs.cosmos.network/master/migrations/chain-upgrade-guide-040.html" +const ( + chainUpgradeGuide = "https://docs.cosmos.network/master/migrations/chain-upgrade-guide-040.html" + flagStreaming = "streaming" +) // ValidateGenesisCmd takes a genesis file, and makes sure that it is valid. func ValidateGenesisCmd(mbm module.BasicManager) *cobra.Command { - return &cobra.Command{ + cmd := &cobra.Command{ Use: "validate-genesis [file]", Args: cobra.RangeArgs(0, 1), Short: "validates the genesis file at the default location or at the location passed as an arg", @@ -26,6 +30,15 @@ func ValidateGenesisCmd(mbm module.BasicManager) *cobra.Command { cdc := clientCtx.Codec + isStream, err := cmd.Flags().GetBool(flagStreaming) + if err != nil { + panic(err) + } + + if isStream { + return validateGenesisStream(mbm, cmd, args) + } + // Load default if passed no args, otherwise load passed file var genesis string if len(args) == 0 { @@ -52,6 +65,96 @@ func ValidateGenesisCmd(mbm module.BasicManager) *cobra.Command { return nil }, } + cmd.Flags().Bool(flagStreaming, false, "turn on streaming mode with this flag") + return cmd +} + +type AppState struct { + Module string `json:"module"` + Data json.RawMessage `json:"data"` +} + +type ModuleState struct { + AppState AppState `json:"app_state"` +} + +func parseModule(jsonStr string) (*ModuleState, error) { + var module ModuleState + err := json.Unmarshal([]byte(jsonStr), &module) + if err != nil { + return nil, err + } + if module.AppState.Module == "" { + return nil, fmt.Errorf("module name is empty") + } + return &module, nil +} + +func validateGenesisStream(mbm module.BasicManager, cmd *cobra.Command, args []string) error { + serverCtx := server.GetServerContextFromCmd(cmd) + clientCtx := client.GetClientContextFromCmd(cmd) + + cdc := clientCtx.Codec + + // Load default if passed no args, otherwise load passed file + var genesis string + if len(args) == 0 { + genesis = serverCtx.Config.GenesisFile() + } else { + genesis = args[0] + } + + lines := genesistypes.IngestGenesisFileLineByLine(genesis) + + genesisCh := make(chan json.RawMessage) + doneCh := make(chan struct{}) + errCh := make(chan error, 1) + seenModules := make(map[string]bool) + prevModule := "" + var moduleName string + var genDoc *tmtypes.GenesisDoc + go func() { + for line := range lines { + moduleState, err := parseModule(line) + // determine module name or genesisDoc + if err != nil { + genDoc, err = tmtypes.GenesisDocFromJSON([]byte(line)) + if err != nil { + errCh <- fmt.Errorf("error unmarshalling genesis doc %s: %s", genesis, err.Error()) + return + } + moduleName = "genesisDoc" + } else { + moduleName = moduleState.AppState.Module + } + if seenModules[moduleName] { + errCh <- fmt.Errorf("module %s seen twice in genesis file", moduleName) + return + } + if prevModule != moduleName { // new module + if prevModule != "" && prevModule != "genesisDoc" { + doneCh <- struct{}{} + } + seenModules[prevModule] = true + if moduleName != "genesisDoc" { + go mbm.ValidateGenesisStream(cdc, clientCtx.TxConfig, moduleName, genesisCh, doneCh, errCh) + genesisCh <- moduleState.AppState.Data + } else { + err = genDoc.ValidateAndComplete() + if err != nil { + errCh <- fmt.Errorf("error validating genesis doc %s: %s", genesis, err.Error()) + } + } + } else { // same module + genesisCh <- moduleState.AppState.Data + } + prevModule = moduleName + } + fmt.Printf("File at %s is a valid genesis file\n", genesis) + errCh <- nil + }() + err := <-errCh + return err } // validateGenDoc reads a genesis file and validates that it is a correct diff --git a/x/genutil/module.go b/x/genutil/module.go index 4b8bcc72e..3cacfb6a2 100644 --- a/x/genutil/module.go +++ b/x/genutil/module.go @@ -53,6 +53,16 @@ func (b AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, txEncodingConfig cl return types.ValidateGenesis(&data, txEncodingConfig.TxJSONDecoder()) } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the genutil module. func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {} @@ -109,5 +119,24 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONCodec) json.RawMe return am.DefaultGenesis(cdc) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + +func (am AppModule) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/gov/module.go b/x/gov/module.go index be43b06ba..be10664ef 100644 --- a/x/gov/module.go +++ b/x/gov/module.go @@ -72,6 +72,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod return types.ValidateGenesis(&data) } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the gov module. func (a AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { proposalRESTHandlers := make([]rest.ProposalRESTHandler, 0, len(a.proposalHandlers)) @@ -183,6 +193,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(gs) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 3 } diff --git a/x/mint/module.go b/x/mint/module.go index 3cd0337ec..849368026 100644 --- a/x/mint/module.go +++ b/x/mint/module.go @@ -64,6 +64,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod return types.ValidateGenesis(data) } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the mint module. func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { rest.RegisterRoutes(clientCtx, rtr) @@ -144,6 +154,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(gs) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/params/module.go b/x/params/module.go index 4d41565db..a0332470e 100644 --- a/x/params/module.go +++ b/x/params/module.go @@ -60,6 +60,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod return data.Validate() } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the params module. func (AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {} @@ -110,6 +120,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(gs) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + func (AppModule) Route() sdk.Route { return sdk.Route{} } // GenerateGenesisState performs a no-op. diff --git a/x/slashing/module.go b/x/slashing/module.go index 05b67abe0..5600ae563 100644 --- a/x/slashing/module.go +++ b/x/slashing/module.go @@ -70,6 +70,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod return types.ValidateGenesis(data) } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the slashing module. func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { rest.RegisterHandlers(clientCtx, rtr) @@ -161,6 +171,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(gs) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 4 } diff --git a/x/staking/module.go b/x/staking/module.go index 3892a8aa9..c5b81823d 100644 --- a/x/staking/module.go +++ b/x/staking/module.go @@ -69,6 +69,16 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod return ValidateGenesis(&data) } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // RegisterRESTRoutes registers the REST routes for the staking module. func (AppModuleBasic) RegisterRESTRoutes(clientCtx client.Context, rtr *mux.Router) { rest.RegisterHandlers(clientCtx, rtr) @@ -160,6 +170,15 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw return cdc.MustMarshalJSON(gs) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 2 } diff --git a/x/upgrade/module.go b/x/upgrade/module.go index cb1dc05c6..3a8b79652 100644 --- a/x/upgrade/module.go +++ b/x/upgrade/module.go @@ -115,11 +115,30 @@ func (AppModuleBasic) ValidateGenesis(_ codec.JSONCodec, config client.TxEncodin return nil } +func (am AppModuleBasic) ValidateGenesisStream(cdc codec.JSONCodec, config client.TxEncodingConfig, genesisCh <-chan json.RawMessage) error { + for genesis := range genesisCh { + err := am.ValidateGenesis(cdc, config, genesis) + if err != nil { + return err + } + } + return nil +} + // ExportGenesis is always empty, as InitGenesis does nothing either func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONCodec) json.RawMessage { return am.DefaultGenesis(cdc) } +func (am AppModule) ExportGenesisStream(ctx sdk.Context, cdc codec.JSONCodec) <-chan json.RawMessage { + ch := make(chan json.RawMessage) + go func() { + ch <- am.ExportGenesis(ctx, cdc) + close(ch) + }() + return ch +} + // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 }