diff --git a/app/app.go b/app/app.go index d3f0544c..10b232fa 100644 --- a/app/app.go +++ b/app/app.go @@ -1,12 +1,13 @@ package app import ( + "fmt" "io" + "slices" "github.com/celestiaorg/celestia-app/v2/app/module" "github.com/celestiaorg/celestia-app/v2/app/posthandler" "github.com/celestiaorg/celestia-app/v2/x/minfee" - "github.com/celestiaorg/celestia-app/v2/x/mint" mintkeeper "github.com/celestiaorg/celestia-app/v2/x/mint/keeper" minttypes "github.com/celestiaorg/celestia-app/v2/x/mint/types" "github.com/cosmos/cosmos-sdk/baseapp" @@ -22,19 +23,12 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkmodule "github.com/cosmos/cosmos-sdk/types/module" "github.com/cosmos/cosmos-sdk/version" - "github.com/cosmos/cosmos-sdk/x/auth" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/cosmos/cosmos-sdk/x/auth/vesting" - vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" - "github.com/cosmos/cosmos-sdk/x/authz" authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" - authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" - "github.com/cosmos/cosmos-sdk/x/bank" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/cosmos/cosmos-sdk/x/capability" capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" "github.com/cosmos/cosmos-sdk/x/crisis" @@ -43,27 +37,19 @@ import ( distr "github.com/cosmos/cosmos-sdk/x/distribution" distrkeeper "github.com/cosmos/cosmos-sdk/x/distribution/keeper" distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" - "github.com/cosmos/cosmos-sdk/x/evidence" evidencekeeper "github.com/cosmos/cosmos-sdk/x/evidence/keeper" evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" "github.com/cosmos/cosmos-sdk/x/feegrant" feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper" - feegrantmodule "github.com/cosmos/cosmos-sdk/x/feegrant/module" - "github.com/cosmos/cosmos-sdk/x/genutil" - genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" - "github.com/cosmos/cosmos-sdk/x/gov" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" govv1beta2 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" oldgovtypes "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" - "github.com/cosmos/cosmos-sdk/x/params" paramskeeper "github.com/cosmos/cosmos-sdk/x/params/keeper" paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" paramproposal "github.com/cosmos/cosmos-sdk/x/params/types/proposal" - "github.com/cosmos/cosmos-sdk/x/slashing" slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper" slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" - "github.com/cosmos/cosmos-sdk/x/staking" stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" @@ -71,7 +57,6 @@ import ( "github.com/cosmos/ibc-go/v6/modules/apps/transfer" ibctransferkeeper "github.com/cosmos/ibc-go/v6/modules/apps/transfer/keeper" ibctransfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types" - ibc "github.com/cosmos/ibc-go/v6/modules/core" ibcclienttypes "github.com/cosmos/ibc-go/v6/modules/core/02-client/types" ibcporttypes "github.com/cosmos/ibc-go/v6/modules/core/05-port/types" ibchost "github.com/cosmos/ibc-go/v6/modules/core/24-host" @@ -88,13 +73,11 @@ import ( appv1 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v1" appv2 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v2" "github.com/celestiaorg/celestia-app/v2/pkg/proof" - "github.com/celestiaorg/celestia-app/v2/x/blob" blobkeeper "github.com/celestiaorg/celestia-app/v2/x/blob/keeper" blobtypes "github.com/celestiaorg/celestia-app/v2/x/blob/types" "github.com/celestiaorg/celestia-app/v2/x/paramfilter" "github.com/celestiaorg/celestia-app/v2/x/tokenfilter" - "github.com/celestiaorg/celestia-app/v2/x/blobstream" blobstreamkeeper "github.com/celestiaorg/celestia-app/v2/x/blobstream/keeper" blobstreamtypes "github.com/celestiaorg/celestia-app/v2/x/blobstream/types" "github.com/celestiaorg/celestia-app/v2/x/signal" @@ -105,59 +88,23 @@ import ( packetforwardkeeper "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v6/packetforward/keeper" packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v6/packetforward/types" - ica "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts" icahost "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/host" icahostkeeper "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/host/keeper" icahosttypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/host/types" icatypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/types" ) -var ( - // ModuleBasics defines the module BasicManager is in charge of setting up basic, - // non-dependant module elements, such as codec registration - // and genesis verification. - ModuleBasics = sdkmodule.NewBasicManager( - auth.AppModuleBasic{}, - genutil.AppModuleBasic{}, - bankModule{}, - capability.AppModuleBasic{}, - stakingModule{}, - mintModule{}, - distributionModule{}, - newGovModule(), - params.AppModuleBasic{}, - crisisModule{}, - slashingModule{}, - authzmodule.AppModuleBasic{}, - feegrantmodule.AppModuleBasic{}, - ibcModule{}, - evidence.AppModuleBasic{}, - transfer.AppModuleBasic{}, - vesting.AppModuleBasic{}, - blob.AppModuleBasic{}, - blobstream.AppModuleBasic{}, - signal.AppModuleBasic{}, - minfee.AppModuleBasic{}, - packetforward.AppModuleBasic{}, - icaModule{}, - ) - - // ModuleEncodingRegisters keeps track of all the module methods needed to - // register interfaces and specific type to encoding config - ModuleEncodingRegisters = extractRegisters(ModuleBasics) - - // maccPerms is short for module account permissions. - maccPerms = map[string][]string{ - authtypes.FeeCollectorName: nil, - distrtypes.ModuleName: nil, - govtypes.ModuleName: {authtypes.Burner}, - minttypes.ModuleName: {authtypes.Minter}, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - icatypes.ModuleName: nil, - } -) +// maccPerms is short for module account permissions. +var maccPerms = map[string][]string{ + authtypes.FeeCollectorName: nil, + distrtypes.ModuleName: nil, + govtypes.ModuleName: {authtypes.Burner}, + minttypes.ModuleName: {authtypes.Minter}, + stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + icatypes.ModuleName: nil, +} const ( v1 = appv1.Version @@ -181,29 +128,31 @@ type App struct { invCheckPeriod uint // keys to access the substores - keys map[string]*storetypes.KVStoreKey - tkeys map[string]*storetypes.TransientStoreKey - memKeys map[string]*storetypes.MemoryStoreKey + keyVersions map[uint64][]string + keys map[string]*storetypes.KVStoreKey + tkeys map[string]*storetypes.TransientStoreKey + memKeys map[string]*storetypes.MemoryStoreKey // keepers - AccountKeeper authkeeper.AccountKeeper - BankKeeper bankkeeper.Keeper - AuthzKeeper authzkeeper.Keeper - CapabilityKeeper *capabilitykeeper.Keeper - StakingKeeper stakingkeeper.Keeper - SlashingKeeper slashingkeeper.Keeper - MintKeeper mintkeeper.Keeper - DistrKeeper distrkeeper.Keeper - GovKeeper govkeeper.Keeper - CrisisKeeper crisiskeeper.Keeper - UpgradeKeeper upgradekeeper.Keeper // This is included purely for the IBC Keeper. It is not used for upgrading - SignalKeeper signal.Keeper - ParamsKeeper paramskeeper.Keeper - IBCKeeper *ibckeeper.Keeper // IBCKeeper must be a pointer in the app, so we can SetRouter on it correctly - EvidenceKeeper evidencekeeper.Keeper - TransferKeeper ibctransferkeeper.Keeper - FeeGrantKeeper feegrantkeeper.Keeper - ICAHostKeeper icahostkeeper.Keeper + AccountKeeper authkeeper.AccountKeeper + BankKeeper bankkeeper.Keeper + AuthzKeeper authzkeeper.Keeper + CapabilityKeeper *capabilitykeeper.Keeper + StakingKeeper stakingkeeper.Keeper + SlashingKeeper slashingkeeper.Keeper + MintKeeper mintkeeper.Keeper + DistrKeeper distrkeeper.Keeper + GovKeeper govkeeper.Keeper + CrisisKeeper crisiskeeper.Keeper + UpgradeKeeper upgradekeeper.Keeper // This is included purely for the IBC Keeper. It is not used for upgrading + SignalKeeper signal.Keeper + ParamsKeeper paramskeeper.Keeper + IBCKeeper *ibckeeper.Keeper // IBCKeeper must be a pointer in the app, so we can SetRouter on it correctly + EvidenceKeeper evidencekeeper.Keeper + TransferKeeper ibctransferkeeper.Keeper + FeeGrantKeeper feegrantkeeper.Keeper + ICAHostKeeper icahostkeeper.Keeper + PacketForwardKeeper *packetforwardkeeper.Keeper ScopedIBCKeeper capabilitykeeper.ScopedKeeper // This keeper is public for test purposes ScopedTransferKeeper capabilitykeeper.ScopedKeeper // This keeper is public for test purposes @@ -218,8 +167,6 @@ type App struct { upgradeHeight int64 // used to define what messages are accepted for a given app version MsgGateKeeper *ante.MsgVersioningGateKeeper - - PacketForwardKeeper *packetforwardkeeper.Keeper } // New returns a reference to an initialized celestia app. @@ -231,7 +178,6 @@ func New( logger log.Logger, db dbm.DB, traceStore io.Writer, - loadLatest bool, invCheckPeriod uint, encodingConfig encoding.Config, upgradeHeight int64, @@ -247,18 +193,7 @@ func New( bApp.SetVersion(version.Version) bApp.SetInterfaceRegistry(interfaceRegistry) - keys := sdk.NewKVStoreKeys( - authtypes.StoreKey, authzkeeper.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, - minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, - govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, - evidencetypes.StoreKey, capabilitytypes.StoreKey, - blobstreamtypes.StoreKey, - ibctransfertypes.StoreKey, - ibchost.StoreKey, - packetforwardtypes.StoreKey, - icahosttypes.StoreKey, - signaltypes.StoreKey, - ) + keys := sdk.NewKVStoreKeys(allStoreKeys()...) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) memKeys := sdk.NewMemoryStoreKeys(capabilitytypes.MemStoreKey) @@ -268,6 +203,7 @@ func New( interfaceRegistry: interfaceRegistry, txConfig: encodingConfig.TxConfig, invCheckPeriod: invCheckPeriod, + keyVersions: versionedStoreKeys(), keys: keys, tkeys: tkeys, memKeys: memKeys, @@ -436,195 +372,14 @@ func New( // we prefer to be more strict in what arguments the modules expect. skipGenesisInvariants := cast.ToBool(appOpts.Get(crisis.FlagSkipGenesisInvariants)) - // NOTE: Any module instantiated in the module manager that is later modified - // must be passed by reference here. - var err error - app.mm, err = module.NewManager([]module.VersionedModule{ - { - Module: genutil.NewAppModule(app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx, encodingConfig.TxConfig), - FromVersion: v1, ToVersion: v2, - }, - { - Module: auth.NewAppModule(appCodec, app.AccountKeeper, nil), - FromVersion: v1, ToVersion: v2, - }, - { - Module: vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: bank.NewAppModule(appCodec, app.BankKeeper, app.AccountKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: capability.NewAppModule(appCodec, *app.CapabilityKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: feegrantmodule.NewAppModule(appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), - FromVersion: v1, ToVersion: v2, - }, - { - Module: crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants), - FromVersion: v1, ToVersion: v2, - }, - { - Module: gov.NewAppModule(appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: mint.NewAppModule(appCodec, app.MintKeeper, app.AccountKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: slashing.NewAppModule(appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: distr.NewAppModule(appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: staking.NewAppModule(appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: evidence.NewAppModule(app.EvidenceKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), - FromVersion: v1, ToVersion: v2, - }, - { - Module: ibc.NewAppModule(app.IBCKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: params.NewAppModule(app.ParamsKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: transfer.NewAppModule(app.TransferKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: blob.NewAppModule(appCodec, app.BlobKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: blobstream.NewAppModule(appCodec, app.BlobstreamKeeper), - FromVersion: v1, ToVersion: v2, - }, - { - Module: signal.NewAppModule(app.SignalKeeper), - FromVersion: v2, ToVersion: v2, - }, - { - Module: minfee.NewAppModule(app.ParamsKeeper), - FromVersion: v2, ToVersion: v2, - }, - { - Module: packetforward.NewAppModule(app.PacketForwardKeeper), - FromVersion: v2, ToVersion: v2, - }, - { - Module: ica.NewAppModule(nil, &app.ICAHostKeeper), - FromVersion: v2, ToVersion: v2, - }, - }) + // NOTE: Modules can't be modified or else must be passed by reference to the module manager + err := app.setupModuleManager(skipGenesisInvariants) if err != nil { panic(err) } - // During begin block slashing happens after distr.BeginBlocker so that - // there is nothing left over in the validator fee pool, so as to keep the - // CanWithdrawInvariant invariant. - // NOTE: staking module is required if HistoricalEntries param > 0 - app.mm.SetOrderBeginBlockers( - capabilitytypes.ModuleName, - minttypes.ModuleName, - distrtypes.ModuleName, - slashingtypes.ModuleName, - evidencetypes.ModuleName, - stakingtypes.ModuleName, - ibchost.ModuleName, - ibctransfertypes.ModuleName, - feegrant.ModuleName, - authtypes.ModuleName, - banktypes.ModuleName, - crisistypes.ModuleName, - govtypes.ModuleName, - genutiltypes.ModuleName, - blobtypes.ModuleName, - blobstreamtypes.ModuleName, - paramstypes.ModuleName, - authz.ModuleName, - vestingtypes.ModuleName, - signaltypes.ModuleName, - minfee.ModuleName, - icatypes.ModuleName, - packetforwardtypes.ModuleName, - ) - - app.mm.SetOrderEndBlockers( - crisistypes.ModuleName, - govtypes.ModuleName, - stakingtypes.ModuleName, - capabilitytypes.ModuleName, - minttypes.ModuleName, - distrtypes.ModuleName, - slashingtypes.ModuleName, - evidencetypes.ModuleName, - ibchost.ModuleName, - ibctransfertypes.ModuleName, - feegrant.ModuleName, - authtypes.ModuleName, - banktypes.ModuleName, - genutiltypes.ModuleName, - blobtypes.ModuleName, - blobstreamtypes.ModuleName, - paramstypes.ModuleName, - authz.ModuleName, - vestingtypes.ModuleName, - signaltypes.ModuleName, - minfee.ModuleName, - packetforwardtypes.ModuleName, - icatypes.ModuleName, - ) - - // NOTE: The genutils module must occur after staking so that pools are - // properly initialized with tokens from genesis accounts. - // NOTE: Capability module must occur first so that it can initialize any capabilities - // so that other modules that want to create or claim capabilities afterwards in InitChain - // can do so safely. - // NOTE: The minfee module must occur before genutil so DeliverTx can - // successfully pass the fee checking logic - app.mm.SetOrderInitGenesis( - capabilitytypes.ModuleName, - authtypes.ModuleName, - banktypes.ModuleName, - distrtypes.ModuleName, - stakingtypes.ModuleName, - slashingtypes.ModuleName, - govtypes.ModuleName, - minttypes.ModuleName, - crisistypes.ModuleName, - ibchost.ModuleName, - minfee.ModuleName, - genutiltypes.ModuleName, - evidencetypes.ModuleName, - ibctransfertypes.ModuleName, - blobtypes.ModuleName, - blobstreamtypes.ModuleName, - vestingtypes.ModuleName, - feegrant.ModuleName, - paramstypes.ModuleName, - authz.ModuleName, - signaltypes.ModuleName, - packetforwardtypes.ModuleName, - icatypes.ModuleName, - ) + // order begin block, end block and init genesis + app.setModuleOrder() app.QueryRouter().AddRoute(proof.TxInclusionQueryPath, proof.QueryTxInclusionProof) app.QueryRouter().AddRoute(proof.ShareInclusionQueryPath, proof.QueryShareInclusionProof) @@ -639,8 +394,8 @@ func New( app.MsgGateKeeper = ante.NewMsgVersioningGateKeeper(app.configurator.GetAcceptedMessages()) app.MsgServiceRouter().SetCircuit(app.MsgGateKeeper) - // initialize stores - app.MountKVStores(keys) + // Initialize the KV stores for the base modules (e.g. params). The base modules will be included in every app version. + app.MountKVStores(app.baseKeys()) app.MountTransientStores(tkeys) app.MountMemoryStores(memKeys) @@ -661,10 +416,16 @@ func New( )) app.SetPostHandler(posthandler.New()) - if loadLatest { - if err := app.LoadLatestVersion(); err != nil { - tmos.Exit(err.Error()) - } + app.SetMigrateStoreFn(app.migrateCommitStore) + app.SetMigrateModuleFn(app.migrateModules) + + // assert that keys are present for all supported versions + app.assertAllKeysArePresent() + + // we don't seal the store until the app version has been initailised + // this will just initialize the base keys (i.e. the param store) + if err := app.CommitMultiStore().LoadLatestVersion(); err != nil { + tmos.Exit(err.Error()) } return app @@ -686,42 +447,66 @@ func (app *App) EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo if currentVersion == v1 { // check that we are at the height before the upgrade if req.Height == app.upgradeHeight-1 { - if err := app.Upgrade(ctx, currentVersion, currentVersion+1); err != nil { - panic(err) - } + app.SetInitialAppVersionInConsensusParams(ctx, v2) + app.SetAppVersion(ctx, v2) } // from v2 to v3 and onwards we use a signalling mechanism } else if shouldUpgrade, newVersion := app.SignalKeeper.ShouldUpgrade(); shouldUpgrade { // Version changes must be increasing. Downgrades are not permitted if newVersion > currentVersion { - if err := app.Upgrade(ctx, currentVersion, newVersion); err != nil { - panic(err) - } + app.SetAppVersion(ctx, newVersion) + app.SignalKeeper.ResetTally(ctx) } } return res } -func (app *App) Upgrade(ctx sdk.Context, fromVersion, toVersion uint64) error { - if err := app.mm.RunMigrations(ctx, app.configurator, fromVersion, toVersion); err != nil { - return err +// migrateCommitStore tells the baseapp during a version upgrade, which stores to add and which +// stores to remove +func (app *App) migrateCommitStore(fromVersion, toVersion uint64) (baseapp.StoreMigrations, error) { + oldStoreKeys := app.keyVersions[fromVersion] + newStoreKeys := app.keyVersions[toVersion] + result := baseapp.StoreMigrations{ + Added: make(map[string]*storetypes.KVStoreKey), + Deleted: make(map[string]*storetypes.KVStoreKey), + } + for _, oldKey := range oldStoreKeys { + if !slices.Contains(newStoreKeys, oldKey) { + result.Deleted[oldKey] = app.keys[oldKey] + } } - if toVersion == v2 { - // we need to set the app version in the param store for the first time - app.SetInitialAppVersionInConsensusParams(ctx, toVersion) + for _, newKey := range newStoreKeys { + if !slices.Contains(oldStoreKeys, newKey) { + result.Added[newKey] = app.keys[newKey] + } } - app.SetAppVersion(ctx, toVersion) - app.SignalKeeper.ResetTally(ctx) - return nil + return result, nil } -// InitChainer application update at chain initialization -func (app *App) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { - var genesisState GenesisState - if err := tmjson.Unmarshal(req.AppStateBytes, &genesisState); err != nil { - panic(err) +// migrateModules performs migrations on existing modules that have registered migrations +// between versions and initializes the state of new modules for the specified app version. +func (app *App) migrateModules(ctx sdk.Context, fromVersion, toVersion uint64) error { + return app.mm.RunMigrations(ctx, app.configurator, fromVersion, toVersion) +} + +// We wrap Info around baseapp so we can take the app version and +// setup the multicommit store. +func (app *App) Info(req abci.RequestInfo) abci.ResponseInfo { + resp := app.BaseApp.Info(req) + // mount the stores for the provided app version + if resp.AppVersion > 0 && !app.IsSealed() { + app.MountKVStores(app.versionedKeys(resp.AppVersion)) + if err := app.LoadLatestVersion(); err != nil { + panic(fmt.Sprintf("loading latest version: %s", err.Error())) + } } - // genesis must always contain the consensus params. The validator set howerver is derived from the + return resp +} + +// We wrap InitChain around baseapp so we can take the app version and +// setup the multicommit store. +func (app *App) InitChain(req abci.RequestInitChain) (res abci.ResponseInitChain) { + // genesis must always contain the consensus params. The validator set however is derived from the // initial genesis state. The genesis must always contain a non zero app version which is the initial // version that the chain starts on if req.ConsensusParams == nil || req.ConsensusParams.Version == nil { @@ -730,6 +515,26 @@ func (app *App) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.Res if req.ConsensusParams.Version.AppVersion == 0 { panic("app version 0 is not accepted. Please set an app version in the genesis") } + + // mount the stores for the provided app version if it has not already been mounted + if app.AppVersion() == 0 && !app.IsSealed() { + app.MountKVStores(app.versionedKeys(req.ConsensusParams.Version.AppVersion)) + if err := app.LoadLatestVersion(); err != nil { + panic(fmt.Sprintf("loading latest version: %s", err.Error())) + } + } + + return app.BaseApp.InitChain(req) +} + +// InitChainer application update at chain initialization +func (app *App) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain { + var genesisState GenesisState + if err := tmjson.Unmarshal(req.AppStateBytes, &genesisState); err != nil { + panic(err) + } + + app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap(req.ConsensusParams.Version.AppVersion)) return app.mm.InitGenesis(ctx, app.appCodec, genesisState, req.ConsensusParams.Version.AppVersion) } @@ -744,6 +549,28 @@ func (app *App) SupportedVersions() []uint64 { return app.mm.SupportedVersions() } +// versionedKeys returns the keys for the kv stores for a given app version +func (app *App) versionedKeys(appVersion uint64) map[string]*storetypes.KVStoreKey { + output := make(map[string]*storetypes.KVStoreKey) + if keys, exists := app.keyVersions[appVersion]; exists { + for _, moduleName := range keys { + if key, exists := app.keys[moduleName]; exists { + output[moduleName] = key + } + } + } + return output +} + +// baseKeys returns the base keys that are mounted to every version +func (app *App) baseKeys() map[string]*storetypes.KVStoreKey { + return map[string]*storetypes.KVStoreKey{ + // we need to know the app version to know what stores to mount + // thus the paramstore must always be a store that is mounted + paramstypes.StoreKey: app.keys[paramstypes.StoreKey], + } +} + // ModuleAccountAddrs returns all the app's module account addresses. func (app *App) ModuleAccountAddrs() map[string]bool { modAccAddrs := make(map[string]bool) @@ -899,16 +726,13 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino // extractRegisters isolates the encoding module registers from the module // manager, and appends any solo registers. -func extractRegisters(m sdkmodule.BasicManager, soloRegisters ...encoding.ModuleRegister) []encoding.ModuleRegister { +func extractRegisters(m sdkmodule.BasicManager) []encoding.ModuleRegister { // TODO: might be able to use some standard generics in go 1.18 - s := make([]encoding.ModuleRegister, len(m)+len(soloRegisters)) + s := make([]encoding.ModuleRegister, len(m)) i := 0 for _, v := range m { s[i] = v i++ } - for i, v := range soloRegisters { - s[i+len(m)] = v - } return s } diff --git a/app/app_test.go b/app/app_test.go index 10fae524..b83a0f9c 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -14,13 +14,12 @@ func TestNew(t *testing.T) { logger := log.NewNopLogger() db := tmdb.NewMemDB() traceStore := &NoopWriter{} - loadLatest := true invCheckPeriod := uint(1) encodingConfig := encoding.MakeConfig(app.ModuleEncodingRegisters...) upgradeHeight := int64(0) appOptions := NoopAppOptions{} - got := app.New(logger, db, traceStore, loadLatest, invCheckPeriod, encodingConfig, upgradeHeight, appOptions) + got := app.New(logger, db, traceStore, invCheckPeriod, encodingConfig, upgradeHeight, appOptions) t.Run("initializes ICAHostKeeper", func(t *testing.T) { assert.NotNil(t, got.ICAHostKeeper) diff --git a/app/module/module.go b/app/module/module.go index ce782e77..ac986533 100644 --- a/app/module/module.go +++ b/app/module/module.go @@ -223,9 +223,6 @@ func (m *Manager) assertNoForgottenModules(setOrderFnName string, moduleNames [] // MigrationHandler is the migration function that each module registers. type MigrationHandler func(sdk.Context) error -// VersionMap is a map of moduleName -> version -type VersionMap map[string]uint64 - // RunMigrations performs in-place store migrations for all modules. This // function MUST be called when the state machine changes appVersion func (m Manager) RunMigrations(ctx sdk.Context, cfg sdkmodule.Configurator, fromVersion, toVersion uint64) error { @@ -335,6 +332,22 @@ func (m *Manager) EndBlock(ctx sdk.Context, req abci.RequestEndBlock) abci.Respo } } +// GetVersionMap gets consensus version from all modules +func (m *Manager) GetVersionMap(version uint64) sdkmodule.VersionMap { + vermap := make(sdkmodule.VersionMap) + if version > m.lastVersion || version < m.firstVersion { + return vermap + } + + for _, v := range m.versionedModules[version] { + version := v.ConsensusVersion() + name := v.Name() + vermap[name] = version + } + + return vermap +} + // ModuleNames returns list of all module names, without any particular order. func (m *Manager) ModuleNames(version uint64) []string { modules, ok := m.versionedModules[version] @@ -351,6 +364,7 @@ func (m *Manager) ModuleNames(version uint64) []string { return ms } +// SupportedVersions returns all the supported versions for the module manager func (m *Manager) SupportedVersions() []uint64 { output := make([]uint64, 0, m.lastVersion-m.firstVersion+1) for version := m.firstVersion; version <= m.lastVersion; version++ { @@ -385,6 +399,17 @@ func (m *Manager) checkUpgradeSchedule() error { return nil } +// assertMatchingModules performs a sanity check that the basic module manager +// contains all the same modules present in the module manager +func (m *Manager) AssertMatchingModules(basicModuleManager sdkmodule.BasicManager) error { + for _, module := range m.allModules { + if _, exists := basicModuleManager[module.Name()]; !exists { + return fmt.Errorf("module %s not found in basic module manager", module.Name()) + } + } + return nil +} + // DefaultMigrationsOrder returns a default migrations order: ascending alphabetical by module name, // except x/auth which will run last, see: // https://github.com/cosmos/cosmos-sdk/issues/10591 diff --git a/app/modules.go b/app/modules.go new file mode 100644 index 00000000..210d0f75 --- /dev/null +++ b/app/modules.go @@ -0,0 +1,373 @@ +package app + +import ( + "fmt" + + "github.com/celestiaorg/celestia-app/v2/app/module" + "github.com/celestiaorg/celestia-app/v2/x/blob" + blobtypes "github.com/celestiaorg/celestia-app/v2/x/blob/types" + "github.com/celestiaorg/celestia-app/v2/x/blobstream" + blobstreamtypes "github.com/celestiaorg/celestia-app/v2/x/blobstream/types" + "github.com/celestiaorg/celestia-app/v2/x/minfee" + "github.com/celestiaorg/celestia-app/v2/x/mint" + minttypes "github.com/celestiaorg/celestia-app/v2/x/mint/types" + "github.com/celestiaorg/celestia-app/v2/x/signal" + signaltypes "github.com/celestiaorg/celestia-app/v2/x/signal/types" + sdkmodule "github.com/cosmos/cosmos-sdk/types/module" + "github.com/cosmos/cosmos-sdk/x/auth" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/cosmos-sdk/x/auth/vesting" + vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + "github.com/cosmos/cosmos-sdk/x/authz" + authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper" + authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module" + "github.com/cosmos/cosmos-sdk/x/bank" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/capability" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + "github.com/cosmos/cosmos-sdk/x/crisis" + crisistypes "github.com/cosmos/cosmos-sdk/x/crisis/types" + distr "github.com/cosmos/cosmos-sdk/x/distribution" + distrtypes "github.com/cosmos/cosmos-sdk/x/distribution/types" + "github.com/cosmos/cosmos-sdk/x/evidence" + evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types" + "github.com/cosmos/cosmos-sdk/x/feegrant" + feegrantmodule "github.com/cosmos/cosmos-sdk/x/feegrant/module" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + "github.com/cosmos/cosmos-sdk/x/gov" + govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" + "github.com/cosmos/cosmos-sdk/x/params" + paramstypes "github.com/cosmos/cosmos-sdk/x/params/types" + "github.com/cosmos/cosmos-sdk/x/slashing" + slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types" + "github.com/cosmos/cosmos-sdk/x/staking" + stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v6/packetforward" + packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v6/packetforward/types" + ica "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts" + icahosttypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/host/types" + icatypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/types" + "github.com/cosmos/ibc-go/v6/modules/apps/transfer" + ibctransfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types" + ibc "github.com/cosmos/ibc-go/v6/modules/core" + ibchost "github.com/cosmos/ibc-go/v6/modules/core/24-host" +) + +var ( + // ModuleBasics defines the module BasicManager is in charge of setting up basic, + // non-dependant module elements, such as codec registration + // and genesis verification. + ModuleBasics = sdkmodule.NewBasicManager( + auth.AppModuleBasic{}, + genutil.AppModuleBasic{}, + bankModule{}, + capability.AppModuleBasic{}, + stakingModule{}, + mintModule{}, + distributionModule{}, + newGovModule(), + params.AppModuleBasic{}, + crisisModule{}, + slashingModule{}, + authzmodule.AppModuleBasic{}, + feegrantmodule.AppModuleBasic{}, + ibcModule{}, + evidence.AppModuleBasic{}, + transfer.AppModuleBasic{}, + vesting.AppModuleBasic{}, + blob.AppModuleBasic{}, + blobstream.AppModuleBasic{}, + signal.AppModuleBasic{}, + minfee.AppModuleBasic{}, + packetforward.AppModuleBasic{}, + icaModule{}, + ) + + // ModuleEncodingRegisters keeps track of all the module methods needed to + // register interfaces and specific type to encoding config + ModuleEncodingRegisters = extractRegisters(ModuleBasics) +) + +func (app *App) setupModuleManager(skipGenesisInvariants bool) error { + var err error + app.mm, err = module.NewManager([]module.VersionedModule{ + { + Module: genutil.NewAppModule(app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx, app.txConfig), + FromVersion: v1, ToVersion: v2, + }, + { + Module: auth.NewAppModule(app.appCodec, app.AccountKeeper, nil), + FromVersion: v1, ToVersion: v2, + }, + { + Module: vesting.NewAppModule(app.AccountKeeper, app.BankKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: bank.NewAppModule(app.appCodec, app.BankKeeper, app.AccountKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: capability.NewAppModule(app.appCodec, *app.CapabilityKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: feegrantmodule.NewAppModule(app.appCodec, app.AccountKeeper, app.BankKeeper, app.FeeGrantKeeper, app.interfaceRegistry), + FromVersion: v1, ToVersion: v2, + }, + { + Module: crisis.NewAppModule(&app.CrisisKeeper, skipGenesisInvariants), + FromVersion: v1, ToVersion: v2, + }, + { + Module: gov.NewAppModule(app.appCodec, app.GovKeeper, app.AccountKeeper, app.BankKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: mint.NewAppModule(app.appCodec, app.MintKeeper, app.AccountKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: slashing.NewAppModule(app.appCodec, app.SlashingKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: distr.NewAppModule(app.appCodec, app.DistrKeeper, app.AccountKeeper, app.BankKeeper, app.StakingKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: staking.NewAppModule(app.appCodec, app.StakingKeeper, app.AccountKeeper, app.BankKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: evidence.NewAppModule(app.EvidenceKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: authzmodule.NewAppModule(app.appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), + FromVersion: v1, ToVersion: v2, + }, + { + Module: ibc.NewAppModule(app.IBCKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: params.NewAppModule(app.ParamsKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: transfer.NewAppModule(app.TransferKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: blob.NewAppModule(app.appCodec, app.BlobKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: blobstream.NewAppModule(app.appCodec, app.BlobstreamKeeper), + FromVersion: v1, ToVersion: v2, + }, + { + Module: signal.NewAppModule(app.SignalKeeper), + FromVersion: v2, ToVersion: v2, + }, + { + Module: minfee.NewAppModule(app.ParamsKeeper), + FromVersion: v2, ToVersion: v2, + }, + { + Module: packetforward.NewAppModule(app.PacketForwardKeeper), + FromVersion: v2, ToVersion: v2, + }, + { + Module: ica.NewAppModule(nil, &app.ICAHostKeeper), + FromVersion: v2, ToVersion: v2, + }, + }) + if err != nil { + return err + } + return app.mm.AssertMatchingModules(ModuleBasics) +} + +func (app *App) setModuleOrder() { + // During begin block slashing happens after distr.BeginBlocker so that + // there is nothing left over in the validator fee pool, so as to keep the + // CanWithdrawInvariant invariant. + // NOTE: staking module is required if HistoricalEntries param > 0 + app.mm.SetOrderBeginBlockers( + capabilitytypes.ModuleName, + minttypes.ModuleName, + distrtypes.ModuleName, + slashingtypes.ModuleName, + evidencetypes.ModuleName, + stakingtypes.ModuleName, + ibchost.ModuleName, + ibctransfertypes.ModuleName, + feegrant.ModuleName, + authtypes.ModuleName, + banktypes.ModuleName, + crisistypes.ModuleName, + govtypes.ModuleName, + genutiltypes.ModuleName, + blobtypes.ModuleName, + blobstreamtypes.ModuleName, + paramstypes.ModuleName, + authz.ModuleName, + vestingtypes.ModuleName, + signaltypes.ModuleName, + minfee.ModuleName, + icatypes.ModuleName, + packetforwardtypes.ModuleName, + ) + + app.mm.SetOrderEndBlockers( + crisistypes.ModuleName, + govtypes.ModuleName, + stakingtypes.ModuleName, + capabilitytypes.ModuleName, + minttypes.ModuleName, + distrtypes.ModuleName, + slashingtypes.ModuleName, + evidencetypes.ModuleName, + ibchost.ModuleName, + ibctransfertypes.ModuleName, + feegrant.ModuleName, + authtypes.ModuleName, + banktypes.ModuleName, + genutiltypes.ModuleName, + blobtypes.ModuleName, + blobstreamtypes.ModuleName, + paramstypes.ModuleName, + authz.ModuleName, + vestingtypes.ModuleName, + signaltypes.ModuleName, + minfee.ModuleName, + packetforwardtypes.ModuleName, + icatypes.ModuleName, + ) + + // NOTE: The genutils module must occur after staking so that pools are + // properly initialized with tokens from genesis accounts. + // NOTE: Capability module must occur first so that it can initialize any capabilities + // so that other modules that want to create or claim capabilities afterwards in InitChain + // can do so safely. + // NOTE: The minfee module must occur before genutil so DeliverTx can + // successfully pass the fee checking logic + app.mm.SetOrderInitGenesis( + capabilitytypes.ModuleName, + authtypes.ModuleName, + banktypes.ModuleName, + distrtypes.ModuleName, + stakingtypes.ModuleName, + slashingtypes.ModuleName, + govtypes.ModuleName, + minttypes.ModuleName, + crisistypes.ModuleName, + ibchost.ModuleName, + minfee.ModuleName, + genutiltypes.ModuleName, + evidencetypes.ModuleName, + ibctransfertypes.ModuleName, + blobtypes.ModuleName, + blobstreamtypes.ModuleName, + vestingtypes.ModuleName, + feegrant.ModuleName, + paramstypes.ModuleName, + authz.ModuleName, + signaltypes.ModuleName, + packetforwardtypes.ModuleName, + icatypes.ModuleName, + ) +} + +func allStoreKeys() []string { + return []string{ + authtypes.StoreKey, authzkeeper.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, + minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, + govtypes.StoreKey, paramstypes.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, + evidencetypes.StoreKey, capabilitytypes.StoreKey, + blobstreamtypes.StoreKey, + ibctransfertypes.StoreKey, + ibchost.StoreKey, + packetforwardtypes.StoreKey, + icahosttypes.StoreKey, + signaltypes.StoreKey, + blobtypes.StoreKey, + } +} + +// versionedStoreKeys returns the store keys for each app version +// ... I wish there was an easier way than this (like using the modules which are already versioned) +func versionedStoreKeys() map[uint64][]string { + return map[uint64][]string{ + 1: { + authtypes.StoreKey, + authzkeeper.StoreKey, + banktypes.StoreKey, + stakingtypes.StoreKey, + minttypes.StoreKey, + distrtypes.StoreKey, + slashingtypes.StoreKey, + govtypes.StoreKey, + upgradetypes.StoreKey, + feegrant.StoreKey, + evidencetypes.StoreKey, + capabilitytypes.StoreKey, + blobstreamtypes.StoreKey, + ibctransfertypes.StoreKey, + ibchost.StoreKey, + blobtypes.StoreKey, + }, + 2: { + authtypes.StoreKey, + authzkeeper.StoreKey, + banktypes.StoreKey, + stakingtypes.StoreKey, + minttypes.StoreKey, + distrtypes.StoreKey, + slashingtypes.StoreKey, + govtypes.StoreKey, + upgradetypes.StoreKey, + feegrant.StoreKey, + evidencetypes.StoreKey, + capabilitytypes.StoreKey, + blobstreamtypes.StoreKey, + ibctransfertypes.StoreKey, + ibchost.StoreKey, + packetforwardtypes.StoreKey, + icahosttypes.StoreKey, + signaltypes.StoreKey, + }, + } +} + +// assertAllKeysArePresent performs a couple sanity checks on startup to ensure each versions key names have +// a key and that all versions supported by the module manager have a respective versioned key +func (app *App) assertAllKeysArePresent() { + supportedAppVersions := app.SupportedVersions() + supportedVersionsMap := make(map[uint64]bool, len(supportedAppVersions)) + for _, version := range supportedAppVersions { + supportedVersionsMap[version] = false + } + + for appVersion, keys := range app.keyVersions { + if _, exists := supportedVersionsMap[appVersion]; exists { + supportedVersionsMap[appVersion] = true + } else { + panic(fmt.Sprintf("keys %v for app version %d are not supported by the module manager", keys, appVersion)) + } + for _, key := range keys { + if _, ok := app.keys[key]; !ok { + panic(fmt.Sprintf("key %s is not present", key)) + } + } + } + for appVersion, supported := range supportedVersionsMap { + if !supported { + panic(fmt.Sprintf("app version %d is supported by the module manager but has no keys", appVersion)) + } + } +} diff --git a/app/test/ica_upgrade_test.go b/app/test/ica_upgrade_test.go index 5a1fc8e0..6a86ba42 100644 --- a/app/test/ica_upgrade_test.go +++ b/app/test/ica_upgrade_test.go @@ -1,30 +1,21 @@ package app_test import ( - "encoding/json" "testing" - "time" - "github.com/celestiaorg/celestia-app/v2/app" - "github.com/celestiaorg/celestia-app/v2/app/encoding" - v1 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v1" - v2 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v2" "github.com/celestiaorg/celestia-app/v2/test/util" - "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/x/params/types/proposal" icahosttypes "github.com/cosmos/ibc-go/v6/modules/apps/27-interchain-accounts/host/types" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" version "github.com/tendermint/tendermint/proto/tendermint/version" - dbm "github.com/tendermint/tm-db" ) // TestICA verifies that the ICA module's params are overridden during an // upgrade from v1 -> v2. func TestICA(t *testing.T) { - testApp, _ := setupTestApp(t, 3) + testApp, _ := util.SetupTestAppWithUpgradeHeight(t, 3) ctx := testApp.NewContext(true, tmproto.Header{ Version: version.Consensus{ App: 1, @@ -57,46 +48,3 @@ func TestICA(t *testing.T) { require.NoError(t, err) require.Equal(t, "true", got.Param.Value) } - -func setupTestApp(t *testing.T, upgradeHeight int64) (*app.App, keyring.Keyring) { - t.Helper() - - db := dbm.NewMemDB() - chainID := "test_chain" - encCfg := encoding.MakeConfig(app.ModuleEncodingRegisters...) - testApp := app.New(log.NewNopLogger(), db, nil, true, 0, encCfg, upgradeHeight, util.EmptyAppOptions{}) - genesisState, _, kr := util.GenesisStateWithSingleValidator(testApp, "account") - stateBytes, err := json.MarshalIndent(genesisState, "", " ") - require.NoError(t, err) - infoResp := testApp.Info(abci.RequestInfo{}) - require.EqualValues(t, 0, infoResp.AppVersion) - cp := app.DefaultInitialConsensusParams() - abciParams := &abci.ConsensusParams{ - Block: &abci.BlockParams{ - MaxBytes: cp.Block.MaxBytes, - MaxGas: cp.Block.MaxGas, - }, - Evidence: &cp.Evidence, - Validator: &cp.Validator, - Version: &cp.Version, - } - - _ = testApp.InitChain( - abci.RequestInitChain{ - Time: time.Now(), - Validators: []abci.ValidatorUpdate{}, - ConsensusParams: abciParams, - AppStateBytes: stateBytes, - ChainId: chainID, - }, - ) - - // assert that the chain starts with version provided in genesis - infoResp = testApp.Info(abci.RequestInfo{}) - require.EqualValues(t, app.DefaultInitialConsensusParams().Version.AppVersion, infoResp.AppVersion) - - _ = testApp.Commit() - supportedVersions := []uint64{v1.Version, v2.Version} - require.Equal(t, supportedVersions, testApp.SupportedVersions()) - return testApp, kr -} diff --git a/app/test/upgrade_test.go b/app/test/upgrade_test.go index 4cea5212..441586c9 100644 --- a/app/test/upgrade_test.go +++ b/app/test/upgrade_test.go @@ -5,6 +5,7 @@ import ( v1 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v1" v2 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v2" + "github.com/celestiaorg/celestia-app/v2/test/util" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -12,7 +13,7 @@ import ( ) func TestUpgradeAppVersion(t *testing.T) { - testApp, _ := setupTestApp(t, 3) + testApp, _ := util.SetupTestAppWithUpgradeHeight(t, 3) supportedVersions := []uint64{v1.Version, v2.Version} diff --git a/cmd/celestia-appd/cmd/root.go b/cmd/celestia-appd/cmd/root.go index 3dbcc66f..61dc7e32 100644 --- a/cmd/celestia-appd/cmd/root.go +++ b/cmd/celestia-appd/cmd/root.go @@ -236,7 +236,7 @@ func NewAppServer(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts se } return app.New( - logger, db, traceStore, true, + logger, db, traceStore, cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)), encoding.MakeConfig(app.ModuleEncodingRegisters...), // Ideally, we would reuse the one created by NewRootCmd. cast.ToInt64(appOpts.Get(UpgradeHeightFlag)), @@ -262,13 +262,13 @@ func createAppAndExport( encCfg.Codec = codec.NewProtoCodec(encCfg.InterfaceRegistry) var capp *app.App if height != -1 { - capp = app.New(logger, db, traceStore, false, uint(1), encCfg, 0, appOpts) + capp = app.New(logger, db, traceStore, uint(1), encCfg, 0, appOpts) if err := capp.LoadHeight(height); err != nil { return servertypes.ExportedApp{}, err } } else { - capp = app.New(logger, db, traceStore, true, uint(1), encCfg, 0, appOpts) + capp = app.New(logger, db, traceStore, uint(1), encCfg, 0, appOpts) } return capp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList) diff --git a/go.mod b/go.mod index c130d8f3..6558e177 100644 --- a/go.mod +++ b/go.mod @@ -257,7 +257,7 @@ require ( ) replace ( - github.com/cosmos/cosmos-sdk => github.com/celestiaorg/cosmos-sdk v1.20.2-sdk-v0.46.16 + github.com/cosmos/cosmos-sdk => github.com/celestiaorg/cosmos-sdk v1.21.0-sdk-v0.46.16 // Pin to ledger-cosmos-go v0.12.4 to avoid a breaking change introduced in v0.13.0 // The following replace statement can be removed when we upgrade to cosmos-sdk >= v0.50.0 github.com/cosmos/ledger-cosmos-go => github.com/cosmos/ledger-cosmos-go v0.12.4 diff --git a/go.sum b/go.sum index 93125984..829e457d 100644 --- a/go.sum +++ b/go.sum @@ -326,8 +326,8 @@ github.com/celestiaorg/blobstream-contracts/v3 v3.1.0 h1:h1Y4V3EMQ2mFmNtWt2sIhZI github.com/celestiaorg/blobstream-contracts/v3 v3.1.0/go.mod h1:x4DKyfKOSv1ZJM9NwV+Pw01kH2CD7N5zTFclXIVJ6GQ= github.com/celestiaorg/celestia-core v1.35.0-tm-v0.34.29 h1:sXERzNXgyHyqTKNQx4S29C/NMDzgav62DaQDNF49HUQ= github.com/celestiaorg/celestia-core v1.35.0-tm-v0.34.29/go.mod h1:weZR4wYx1Vcw3g1Jc5G8VipG4M+KUDSqeIzyyWszmsQ= -github.com/celestiaorg/cosmos-sdk v1.20.2-sdk-v0.46.16 h1:EmzwDx64oG8eKZPar50VCkpzxDNqjjtt7rOBJsMQY8E= -github.com/celestiaorg/cosmos-sdk v1.20.2-sdk-v0.46.16/go.mod h1:AmuR63HTlX8vNV3+NGWNPIZa95J1UweTUmWDHSdTGj0= +github.com/celestiaorg/cosmos-sdk v1.21.0-sdk-v0.46.16 h1:P44npoIUuortDf0nQSUpTwO8zsWoHufbDD/doU+CtxY= +github.com/celestiaorg/cosmos-sdk v1.21.0-sdk-v0.46.16/go.mod h1:AmuR63HTlX8vNV3+NGWNPIZa95J1UweTUmWDHSdTGj0= github.com/celestiaorg/go-square v1.0.1 h1:LEG1zrw4i03VBMElQF8GAbKYgh1bT1uGzWxasU2ePuo= github.com/celestiaorg/go-square v1.0.1/go.mod h1:XMv5SGCeGSkynW2OOsedugaW/rQlvzxGzWGxTKsyYOU= github.com/celestiaorg/go-square/merkle v0.0.0-20240117232118-fd78256df076 h1:PYInrsYzrDIsZW9Yb86OTi2aEKuPcpgJt6Mc0Jlc/yg= diff --git a/test/packetforward/packetforward_upgrade_test.go b/test/packetforward/packetforward_upgrade_test.go index d35f1057..45e5de59 100644 --- a/test/packetforward/packetforward_upgrade_test.go +++ b/test/packetforward/packetforward_upgrade_test.go @@ -1,31 +1,24 @@ package packetforward_test import ( - "encoding/json" "strings" "testing" - "time" - "github.com/celestiaorg/celestia-app/v2/app" - "github.com/celestiaorg/celestia-app/v2/app/encoding" v1 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v1" v2 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v2" "github.com/celestiaorg/celestia-app/v2/test/util" - "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/x/params/types/proposal" packetforwardtypes "github.com/cosmos/ibc-apps/middleware/packet-forward-middleware/v6/packetforward/types" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" - "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" version "github.com/tendermint/tendermint/proto/tendermint/version" - dbm "github.com/tendermint/tm-db" ) // TestPacketForwardMiddlewareAgainstAppUpgrades verifies that the PFM module's params are overridden during an // upgrade from v1 -> v2. func TestPacketForwardMiddlewareAgainstAppUpgrades(t *testing.T) { - testApp, _ := setupTestApp(t, 3) + testApp, _ := util.SetupTestAppWithUpgradeHeight(t, 3) supportedVersions := []uint64{v1.Version, v2.Version} require.Equal(t, supportedVersions, testApp.SupportedVersions()) @@ -74,44 +67,3 @@ func TestPacketForwardMiddlewareAgainstAppUpgrades(t *testing.T) { require.NoError(t, err) require.Equal(t, "0.000000000000000000", strings.Trim(got.Param.Value, "\"")) } - -func setupTestApp(t *testing.T, upgradeHeight int64) (*app.App, keyring.Keyring) { - t.Helper() - - db := dbm.NewMemDB() - chainID := "test_chain" - encCfg := encoding.MakeConfig(app.ModuleEncodingRegisters...) - testApp := app.New(log.NewNopLogger(), db, nil, true, 0, encCfg, upgradeHeight, util.EmptyAppOptions{}) - genesisState, _, kr := util.GenesisStateWithSingleValidator(testApp, "account") - stateBytes, err := json.MarshalIndent(genesisState, "", " ") - require.NoError(t, err) - infoResp := testApp.Info(abci.RequestInfo{}) - require.EqualValues(t, 0, infoResp.AppVersion) - cp := app.DefaultInitialConsensusParams() - abciParams := &abci.ConsensusParams{ - Block: &abci.BlockParams{ - MaxBytes: cp.Block.MaxBytes, - MaxGas: cp.Block.MaxGas, - }, - Evidence: &cp.Evidence, - Validator: &cp.Validator, - Version: &cp.Version, - } - - _ = testApp.InitChain( - abci.RequestInitChain{ - Time: time.Now(), - Validators: []abci.ValidatorUpdate{}, - ConsensusParams: abciParams, - AppStateBytes: stateBytes, - ChainId: chainID, - }, - ) - - // assert that the chain starts with version provided in genesis - infoResp = testApp.Info(abci.RequestInfo{}) - require.EqualValues(t, app.DefaultInitialConsensusParams().Version.AppVersion, infoResp.AppVersion) - - _ = testApp.Commit() - return testApp, kr -} diff --git a/test/testground/go.mod b/test/testground/go.mod index 294efae0..9bb25f03 100644 --- a/test/testground/go.mod +++ b/test/testground/go.mod @@ -222,7 +222,7 @@ require ( ) replace ( - github.com/cosmos/cosmos-sdk => github.com/celestiaorg/cosmos-sdk v1.20.2-sdk-v0.46.16 + github.com/cosmos/cosmos-sdk => github.com/celestiaorg/cosmos-sdk v1.21.0-sdk-v0.46.16 github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.9.0 github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 diff --git a/test/testground/go.sum b/test/testground/go.sum index fbe539fd..77f3db8d 100644 --- a/test/testground/go.sum +++ b/test/testground/go.sum @@ -340,8 +340,8 @@ github.com/celestiaorg/celestia-app v1.0.0-rc0.0.20240304150808-f0a1f87c0253 h1: github.com/celestiaorg/celestia-app v1.0.0-rc0.0.20240304150808-f0a1f87c0253/go.mod h1:z3gMQZkUUe2MYrQQGnrYy+gDP0QpX0f5EPWtVNM0u/E= github.com/celestiaorg/celestia-core v1.35.0-tm-v0.34.29 h1:sXERzNXgyHyqTKNQx4S29C/NMDzgav62DaQDNF49HUQ= github.com/celestiaorg/celestia-core v1.35.0-tm-v0.34.29/go.mod h1:weZR4wYx1Vcw3g1Jc5G8VipG4M+KUDSqeIzyyWszmsQ= -github.com/celestiaorg/cosmos-sdk v1.20.2-sdk-v0.46.16 h1:EmzwDx64oG8eKZPar50VCkpzxDNqjjtt7rOBJsMQY8E= -github.com/celestiaorg/cosmos-sdk v1.20.2-sdk-v0.46.16/go.mod h1:AmuR63HTlX8vNV3+NGWNPIZa95J1UweTUmWDHSdTGj0= +github.com/celestiaorg/cosmos-sdk v1.21.0-sdk-v0.46.16 h1:P44npoIUuortDf0nQSUpTwO8zsWoHufbDD/doU+CtxY= +github.com/celestiaorg/cosmos-sdk v1.21.0-sdk-v0.46.16/go.mod h1:AmuR63HTlX8vNV3+NGWNPIZa95J1UweTUmWDHSdTGj0= github.com/celestiaorg/go-square v1.0.1 h1:LEG1zrw4i03VBMElQF8GAbKYgh1bT1uGzWxasU2ePuo= github.com/celestiaorg/go-square v1.0.1/go.mod h1:XMv5SGCeGSkynW2OOsedugaW/rQlvzxGzWGxTKsyYOU= github.com/celestiaorg/go-square/merkle v0.0.0-20240117232118-fd78256df076 h1:PYInrsYzrDIsZW9Yb86OTi2aEKuPcpgJt6Mc0Jlc/yg= diff --git a/test/tokenfilter/setup.go b/test/tokenfilter/setup.go index a9000042..aea94a1f 100644 --- a/test/tokenfilter/setup.go +++ b/test/tokenfilter/setup.go @@ -146,7 +146,7 @@ func SetupWithGenesisValSet(t testing.TB, valSet *tmtypes.ValidatorSet, genAccs encCdc := encoding.MakeConfig(app.ModuleEncodingRegisters...) genesisState := app.NewDefaultGenesisState(encCdc.Codec) app := app.New( - log.NewNopLogger(), db, nil, true, 5, encCdc, 0, simapp.EmptyAppOptions{}, + log.NewNopLogger(), db, nil, 5, encCdc, 0, simapp.EmptyAppOptions{}, ) // set genesis accounts diff --git a/test/util/malicious/app.go b/test/util/malicious/app.go index fdd0263a..9212e966 100644 --- a/test/util/malicious/app.go +++ b/test/util/malicious/app.go @@ -51,13 +51,12 @@ func New( logger log.Logger, db dbm.DB, traceStore io.Writer, - loadLatest bool, invCheckPeriod uint, encodingConfig encoding.Config, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp), ) *App { - goodApp := app.New(logger, db, traceStore, loadLatest, invCheckPeriod, encodingConfig, 0, appOpts, baseAppOptions...) + goodApp := app.New(logger, db, traceStore, invCheckPeriod, encodingConfig, 0, appOpts, baseAppOptions...) badApp := &App{App: goodApp} // set the malicious prepare proposal handler if it is set in the app options diff --git a/test/util/malicious/test_app.go b/test/util/malicious/test_app.go index 24b3f652..35943f61 100644 --- a/test/util/malicious/test_app.go +++ b/test/util/malicious/test_app.go @@ -77,7 +77,7 @@ func NewAppServer(logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts se } return New( - logger, db, traceStore, true, + logger, db, traceStore, cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)), encoding.MakeConfig(app.ModuleEncodingRegisters...), // Ideally, we would reuse the one created by NewRootCmd. appOpts, diff --git a/test/util/test_app.go b/test/util/test_app.go index 59b7f3cb..765b53d3 100644 --- a/test/util/test_app.go +++ b/test/util/test_app.go @@ -3,11 +3,14 @@ package util import ( "encoding/json" "fmt" + "testing" "time" "github.com/celestiaorg/celestia-app/v2/app" "github.com/celestiaorg/celestia-app/v2/app/encoding" "github.com/celestiaorg/celestia-app/v2/pkg/appconsts" + v1 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v1" + v2 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v2" "github.com/celestiaorg/celestia-app/v2/test/util/testfactory" "github.com/celestiaorg/celestia-app/v2/test/util/testnode" "github.com/cosmos/cosmos-sdk/codec" @@ -22,6 +25,7 @@ import ( authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/spf13/cast" + "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -79,7 +83,7 @@ func NewTestAppWithGenesisSet(cparams *tmproto.ConsensusParams, genAccounts ...s encCfg := encoding.MakeConfig(app.ModuleEncodingRegisters...) testApp := app.New( - log.NewNopLogger(), db, nil, true, + log.NewNopLogger(), db, nil, cast.ToUint(emptyOpts.Get(server.FlagInvCheckPeriod)), encCfg, 0, @@ -107,6 +111,8 @@ func NewTestAppWithGenesisSet(cparams *tmproto.ConsensusParams, genAccounts ...s genesisTime := time.Date(2023, 1, 1, 1, 1, 1, 1, time.UTC).UTC() + _ = testApp.Info(abci.RequestInfo{}) + // init chain will set the validator set and initialize the genesis accounts testApp.InitChain( abci.RequestInitChain{ @@ -293,3 +299,46 @@ func genesisStateWithValSet( func NewDefaultGenesisState(cdc codec.JSONCodec) app.GenesisState { return app.ModuleBasics.DefaultGenesis(cdc) } + +func SetupTestAppWithUpgradeHeight(t *testing.T, upgradeHeight int64) (*app.App, keyring.Keyring) { + t.Helper() + + db := dbm.NewMemDB() + chainID := "test_chain" + encCfg := encoding.MakeConfig(app.ModuleEncodingRegisters...) + testApp := app.New(log.NewNopLogger(), db, nil, 0, encCfg, upgradeHeight, EmptyAppOptions{}) + genesisState, _, kr := GenesisStateWithSingleValidator(testApp, "account") + stateBytes, err := json.MarshalIndent(genesisState, "", " ") + require.NoError(t, err) + infoResp := testApp.Info(abci.RequestInfo{}) + require.EqualValues(t, 0, infoResp.AppVersion) + cp := app.DefaultInitialConsensusParams() + abciParams := &abci.ConsensusParams{ + Block: &abci.BlockParams{ + MaxBytes: cp.Block.MaxBytes, + MaxGas: cp.Block.MaxGas, + }, + Evidence: &cp.Evidence, + Validator: &cp.Validator, + Version: &cp.Version, + } + + _ = testApp.InitChain( + abci.RequestInitChain{ + Time: time.Now(), + Validators: []abci.ValidatorUpdate{}, + ConsensusParams: abciParams, + AppStateBytes: stateBytes, + ChainId: chainID, + }, + ) + + // assert that the chain starts with version provided in genesis + infoResp = testApp.Info(abci.RequestInfo{}) + require.EqualValues(t, app.DefaultInitialConsensusParams().Version.AppVersion, infoResp.AppVersion) + + _ = testApp.Commit() + supportedVersions := []uint64{v1.Version, v2.Version} + require.Equal(t, supportedVersions, testApp.SupportedVersions()) + return testApp, kr +} diff --git a/x/minfee/upgrade_test.go b/x/minfee/upgrade_test.go index 7ce3566f..3fb5c02c 100644 --- a/x/minfee/upgrade_test.go +++ b/x/minfee/upgrade_test.go @@ -89,7 +89,7 @@ func setupTestApp(t *testing.T, upgradeHeight int64) (*app.App, keyring.Keyring) db := dbm.NewMemDB() chainID := "test_chain" encCfg := encoding.MakeConfig(app.ModuleEncodingRegisters...) - testApp := app.New(log.NewNopLogger(), db, nil, true, 0, encCfg, upgradeHeight, util.EmptyAppOptions{}) + testApp := app.New(log.NewNopLogger(), db, nil, 0, encCfg, upgradeHeight, util.EmptyAppOptions{}) genesisState, _, kr := util.GenesisStateWithSingleValidator(testApp, "account")