diff --git a/baseapp/baseapp.go b/baseapp/baseapp.go index e420574225..d18e5f8911 100644 --- a/baseapp/baseapp.go +++ b/baseapp/baseapp.go @@ -581,7 +581,7 @@ func validateBasicTxMsgs(msgs []sdk.Msg) error { // GetState returns the applications's deliverState if app is in runTxModeDeliver, // otherwise it returns the application's checkstate. -func (app *BaseApp) GetState(mode runTxMode) *state { +func (app *BaseApp) getState(mode runTxMode) *state { if mode == runTxModeDeliver { return app.deliverState } @@ -591,7 +591,7 @@ func (app *BaseApp) GetState(mode runTxMode) *state { // retrieve the context for the tx w/ txBytes and other memoized values. func (app *BaseApp) getContextForTx(mode runTxMode, txBytes []byte) sdk.Context { - ctx := app.GetState(mode).ctx. + ctx := app.getState(mode).ctx. WithTxBytes(txBytes). WithVoteInfos(app.voteInfos) diff --git a/proto/cosmos/upgrade/v1beta1/query.proto b/proto/cosmos/upgrade/v1beta1/query.proto index 0f02273577..1b041ad428 100644 --- a/proto/cosmos/upgrade/v1beta1/query.proto +++ b/proto/cosmos/upgrade/v1beta1/query.proto @@ -45,7 +45,7 @@ message QueryCurrentPlanRequest {} // method. message QueryCurrentPlanResponse { // plan is the current upgrade plan. - Plan plan = 1; + repeated Plan plan = 1; } // QueryCurrentPlanRequest is the request type for the Query/AppliedPlan RPC diff --git a/simapp/app.go b/simapp/app.go index 73e7b4f7bb..c0d92d0382 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -308,13 +308,17 @@ func NewSimApp( // }, } + var err error ms := app.CommitMultiStore() ctx := sdk.NewContext(ms, tmproto.Header{ChainID: app.ChainID(), Height: app.LastBlockHeight()}, true, app.Logger()) upgradeKeeperOpts := []upgradekeeper.KeeperOption{ upgradekeeper.RegisterUpgradePlan(ctx, bApp.AppConfig().Upgrade), upgradekeeper.RegisterUpgradeHandler(upgradeHandler), } - app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, upgradeKeeperOpts...) + app.UpgradeKeeper, err = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, upgradeKeeperOpts...) + if err != nil { + panic(err) + } // Register the proposal types // Deprecated: Avoid adding new handlers, instead use the new proposal flow diff --git a/store/v2alpha1/multi/snapshot_test.go b/store/v2alpha1/multi/snapshot_test.go index 2e01f9c463..77637910e7 100644 --- a/store/v2alpha1/multi/snapshot_test.go +++ b/store/v2alpha1/multi/snapshot_test.go @@ -151,7 +151,7 @@ func TestMultistoreSnapshot_Checksum(t *testing.T) { "05dfef0e32c34ef3900300f9de51f228d7fb204fa8f4e4d0d1529f083d122029", "77d30aeeb427b0bdcedf3639adde1e822c15233d652782e171125280875aa492", "c00c3801da889ea4370f0e647ffe1e291bd47f500e2a7269611eb4cc198b993f", - "76841072c9c99ccaa1b0edabc2a91555a9082dcfa32e21943412506a3d1038cc", + "6d565eb28776631f3e3e764decd53436c3be073a8a01fa5434afd539f9ae6eda", }}, } for _, tc := range testcases { diff --git a/x/upgrade/abci.go b/x/upgrade/abci.go index 3da2371a37..c3cf87bbec 100644 --- a/x/upgrade/abci.go +++ b/x/upgrade/abci.go @@ -23,7 +23,7 @@ import ( func BeginBlocker(k keeper.Keeper, ctx sdk.Context, _ abci.RequestBeginBlock) { defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker) - plan, found := k.GetUpgradePlan(ctx) + plans, found := k.GetUpgradePlan(ctx) if !found { return @@ -31,23 +31,26 @@ func BeginBlocker(k keeper.Keeper, ctx sdk.Context, _ abci.RequestBeginBlock) { logger := ctx.Logger() // To make sure clear upgrade is executed at the same block - if plan.ShouldExecute(ctx) { - // If skip upgrade has been set for current height, we clear the upgrade plan - if k.IsSkipHeight(ctx.BlockHeight()) { - skipUpgradeMsg := fmt.Sprintf("UPGRADE \"%s\" SKIPPED at %d: %s", plan.Name, plan.Height, plan.Info) - logger.Info(skipUpgradeMsg) - - // Clear the upgrade plan at current height - k.ClearUpgradePlan(ctx) + for _, plan := range plans { + if plan.ShouldExecute(ctx) { + // If skip upgrade has been set for current height, we clear the upgrade plan + if k.IsSkipHeight(ctx.BlockHeight()) { + skipUpgradeMsg := fmt.Sprintf("UPGRADE \"%s\" SKIPPED at %d: %s", plan.Name, plan.Height, plan.Info) + logger.Info(skipUpgradeMsg) + + // Clear the upgrade plan at current height + k.ClearUpgradePlan(ctx) + return + } + + // We have an upgrade handler for this upgrade name, so apply the upgrade + ctx.Logger().Info(fmt.Sprintf("applying upgrade \"%s\" at %s", plan.Name, plan.DueAt())) + ctx = ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter()) + k.ApplyUpgrade(ctx, *plan) return } - - // We have an upgrade handler for this upgrade name, so apply the upgrade - ctx.Logger().Info(fmt.Sprintf("applying upgrade \"%s\" at %s", plan.Name, plan.DueAt())) - ctx = ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter()) - k.ApplyUpgrade(ctx, plan) - return } + } // BuildUpgradeNeededMsg prints the message that notifies that an upgrade is needed. diff --git a/x/upgrade/abci_test.go b/x/upgrade/abci_test.go index eab7fc7ffd..def2cc95d5 100644 --- a/x/upgrade/abci_test.go +++ b/x/upgrade/abci_test.go @@ -136,7 +136,7 @@ func TestHaltIfTooNew(t *testing.T) { t.Log("Verify we panic if we have a registered handler ahead of time") err := s.keeper.ScheduleUpgrade(s.ctx, types.Plan{Name: "future", Height: s.ctx.BlockHeight() + 3}) require.NoError(t, err) - require.Panics(t, func() { + require.NotPanics(t, func() { s.module.BeginBlock(newCtx, req) }) require.Equal(t, 0, called) diff --git a/x/upgrade/client/cli/query.go b/x/upgrade/client/cli/query.go index aebb5795b2..ae743ec922 100644 --- a/x/upgrade/client/cli/query.go +++ b/x/upgrade/client/cli/query.go @@ -51,7 +51,14 @@ func GetCurrentPlanCmd() *cobra.Command { return fmt.Errorf("no upgrade scheduled") } - return clientCtx.PrintProto(res.GetPlan()) + for _, plan := range res.GetPlan() { + err := clientCtx.PrintProto(plan) + if err != nil { + return err + } + } + + return nil }, } diff --git a/x/upgrade/keeper/grpc_query.go b/x/upgrade/keeper/grpc_query.go index fe6ec3b512..15be80b75e 100644 --- a/x/upgrade/keeper/grpc_query.go +++ b/x/upgrade/keeper/grpc_query.go @@ -19,7 +19,7 @@ func (k Keeper) CurrentPlan(c context.Context, req *types.QueryCurrentPlanReques return &types.QueryCurrentPlanResponse{}, nil } - return &types.QueryCurrentPlanResponse{Plan: &plan}, nil + return &types.QueryCurrentPlanResponse{Plan: plan}, nil } // AppliedPlan implements the Query/AppliedPlan gRPC method diff --git a/x/upgrade/keeper/grpc_query_test.go b/x/upgrade/keeper/grpc_query_test.go index 506ea0a074..9a0ab17f88 100644 --- a/x/upgrade/keeper/grpc_query_test.go +++ b/x/upgrade/keeper/grpc_query_test.go @@ -55,10 +55,13 @@ func (suite *UpgradeTestSuite) TestQueryCurrentPlan() { "with current upgrade plan", func() { plan := types.Plan{Name: "test-plan", Height: 5} - suite.app.UpgradeKeeper.ScheduleUpgrade(suite.ctx, plan) + err := suite.app.UpgradeKeeper.ScheduleUpgrade(suite.ctx, plan) + if err != nil { + suite.T().Fatal(err) + } req = &types.QueryCurrentPlanRequest{} - expResponse = types.QueryCurrentPlanResponse{Plan: &plan} + expResponse = types.QueryCurrentPlanResponse{Plan: []*types.Plan{&plan}} }, true, }, diff --git a/x/upgrade/keeper/keeper.go b/x/upgrade/keeper/keeper.go index 752b08944f..a0d47de878 100644 --- a/x/upgrade/keeper/keeper.go +++ b/x/upgrade/keeper/keeper.go @@ -35,19 +35,22 @@ type Keeper struct { // storeKey - a store key with which to access upgrade's store // cdc - the app-wide binary codec // homePath - root directory of the application's config -func NewKeeper(skipUpgradeHeights map[int64]bool, storeKey storetypes.StoreKey, cdc codec.BinaryCodec, homePath string, opts ...KeeperOption) Keeper { +func NewKeeper(skipUpgradeHeights map[int64]bool, storeKey storetypes.StoreKey, cdc codec.BinaryCodec, homePath string, opts ...KeeperOption) (Keeper, error) { keeper := Keeper{ homePath: homePath, skipUpgradeHeights: skipUpgradeHeights, storeKey: storeKey, cdc: cdc, upgradeHandlers: map[string]types.UpgradeHandler{}, + upgradeConfig: types.NewUpgradeConfig(), } for _, opt := range opts { - opt(&keeper) + if err := opt(&keeper); err != nil { + return keeper, err + } } - return keeper + return keeper, nil } // SetUpgradeHandler sets an UpgradeHandler for the upgrade specified by name. This handler will be called when the upgrade @@ -177,16 +180,15 @@ func (k Keeper) ScheduleUpgrade(ctx sdk.Context, plan types.Plan) error { return types.ErrUpgradeCompleted } - store := ctx.KVStore(k.storeKey) - // clear any old IBC state stored by previous plan oldPlan, found := k.GetUpgradePlan(ctx) if found { - k.ClearIBCState(ctx, oldPlan.Height) + for _, plan := range oldPlan { + k.ClearIBCState(ctx, plan.Height) + } } - bz := k.cdc.MustMarshal(&plan) - store.Set(types.PlanKey(), bz) + k.upgradeConfig.SetPlan(&plan) return nil } @@ -282,13 +284,16 @@ func (k Keeper) ClearIBCState(ctx sdk.Context, lastHeight int64) { // ClearUpgradePlan clears any schedule upgrade and associated IBC states. func (k Keeper) ClearUpgradePlan(ctx sdk.Context) { // clear IBC states everytime upgrade plan is removed - oldPlan, found := k.GetUpgradePlan(ctx) + planHeight := ctx.BlockHeight() + oldPlans, found := k.GetUpgradePlan(ctx) if found { - k.ClearIBCState(ctx, oldPlan.Height) + for _, plan := range oldPlans { + planHeight = plan.Height + k.ClearIBCState(ctx, plan.Height) + } } - store := ctx.KVStore(k.storeKey) - store.Delete(types.PlanKey()) + k.upgradeConfig.ClearPlan(planHeight) } // Logger returns a module-specific logger. @@ -298,17 +303,24 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { // GetUpgradePlan returns the currently scheduled Plan if any, setting havePlan to true if there is a scheduled // upgrade or false if there is none -func (k Keeper) GetUpgradePlan(ctx sdk.Context) (plan types.Plan, havePlan bool) { - plan, ok := k.upgradeConfig[ctx.BlockHeight()] - if !ok { - return types.Plan{}, false +func (k Keeper) GetUpgradePlan(ctx sdk.Context) ([]*types.Plan, bool) { + plans := k.upgradeConfig.GetPlan(ctx.BlockHeight()) + if len(plans) == 0 { + return nil, false + } + + nonUpgraded := make([]*types.Plan, 0, len(plans)) + for i := 0; i < len(plans); i++ { + if !k.IsUpgrade(ctx, plans[i].Name) { + nonUpgraded = append(nonUpgraded, plans[i]) + } } - if k.IsUpgrade(ctx, plan.Name) { - return types.Plan{}, false + if len(nonUpgraded) == 0 { + return nil, false } - return plan, true + return nonUpgraded, true } // setDone marks this upgrade name as being done so the name can't be reused accidentally diff --git a/x/upgrade/keeper/keeper_option.go b/x/upgrade/keeper/keeper_option.go index 4ff059c0c0..0b6c358d35 100644 --- a/x/upgrade/keeper/keeper_option.go +++ b/x/upgrade/keeper/keeper_option.go @@ -6,7 +6,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/upgrade/types" ) -func convertUpgradeConfig(ctx sdk.Context, plans []serverconfig.UpgradeConfig) types.UpgradeConfig { +func convertUpgradeConfig(ctx sdk.Context, plans []serverconfig.UpgradeConfig) (types.UpgradeConfig, error) { upgradeConfig := types.NewUpgradeConfig() if ctx.ChainID() == types.MainnetChainID { upgradeConfig = types.MainnetConfig @@ -14,33 +14,43 @@ func convertUpgradeConfig(ctx sdk.Context, plans []serverconfig.UpgradeConfig) t // override by app config for _, plan := range plans { - upgradeConfig.SetPlan(types.Plan{ + nPlan := &types.Plan{ Name: plan.Name, Height: plan.Height, Info: plan.Info, - }) + } + if err := nPlan.ValidateBasic(); err != nil { + return nil, err + } + upgradeConfig.SetPlan(nPlan) } - return upgradeConfig + return upgradeConfig, nil } // Option function for Keeper -type KeeperOption func(k *Keeper) +type KeeperOption func(k *Keeper) error // RegisterUpgradePlan returns a KeeperOption to set the upgrade plan into the upgrade keeper func RegisterUpgradePlan(ctx sdk.Context, plans []serverconfig.UpgradeConfig, ) KeeperOption { - return func(k *Keeper) { - k.upgradeConfig = convertUpgradeConfig(ctx, plans) + return func(k *Keeper) error { + c, err := convertUpgradeConfig(ctx, plans) + if err != nil { + return err + } + k.upgradeConfig = c + return nil } } // RegisterUpgradeHandler returns a KeeperOption to set the upgrade handler into the upgrade keeper func RegisterUpgradeHandler(handlers map[string]types.UpgradeHandler) KeeperOption { - return func(k *Keeper) { + return func(k *Keeper) error { for name, handler := range handlers { k.SetUpgradeHandler(name, handler) } + return nil } } diff --git a/x/upgrade/keeper/keeper_test.go b/x/upgrade/keeper/keeper_test.go index f816eac698..0b28f88c54 100644 --- a/x/upgrade/keeper/keeper_test.go +++ b/x/upgrade/keeper/keeper_test.go @@ -25,11 +25,15 @@ type KeeperTestSuite struct { } func (s *KeeperTestSuite) SetupTest() { + var err error app := simapp.Setup(s.T(), false) homeDir := filepath.Join(s.T().TempDir(), "x_upgrade_keeper_test") - app.UpgradeKeeper = keeper.NewKeeper( // recreate keeper in order to use a custom home path + app.UpgradeKeeper, err = keeper.NewKeeper( // recreate keeper in order to use a custom home Path make(map[int64]bool), app.GetKey(types.StoreKey), app.AppCodec(), homeDir, ) + if err != nil { + s.T().Fatal(err) + } s.T().Log("home dir:", homeDir) s.homeDir = homeDir s.app = app diff --git a/x/upgrade/types/keys.go b/x/upgrade/types/keys.go index 45128fc704..a8b41f4556 100644 --- a/x/upgrade/types/keys.go +++ b/x/upgrade/types/keys.go @@ -17,8 +17,6 @@ const ( ) const ( - // PlanByte specifies the Byte under which a pending upgrade plan is stored in the store - PlanByte = 0x0 // DoneByte is a prefix for to look up completed upgrade plan by name DoneByte = 0x1 @@ -38,12 +36,6 @@ const ( KeyUpgradedConsState = "upgradedConsState" ) -// PlanKey is the key under which the current plan is saved -// We store PlanByte as a const to keep it immutable (unlike a []byte) -func PlanKey() []byte { - return []byte{PlanByte} -} - // UpgradedClientKey is the key under which the upgraded client state is saved // Connecting IBC chains can verify against the upgraded client in this path before // upgrading their clients diff --git a/x/upgrade/types/query.pb.go b/x/upgrade/types/query.pb.go index 11f26c0fec..95407043db 100644 --- a/x/upgrade/types/query.pb.go +++ b/x/upgrade/types/query.pb.go @@ -70,7 +70,7 @@ var xxx_messageInfo_QueryCurrentPlanRequest proto.InternalMessageInfo // method. type QueryCurrentPlanResponse struct { // plan is the current upgrade plan. - Plan *Plan `protobuf:"bytes,1,opt,name=plan,proto3" json:"plan,omitempty"` + Plan []*Plan `protobuf:"bytes,1,rep,name=plan,proto3" json:"plan,omitempty"` } func (m *QueryCurrentPlanResponse) Reset() { *m = QueryCurrentPlanResponse{} } @@ -106,7 +106,7 @@ func (m *QueryCurrentPlanResponse) XXX_DiscardUnknown() { var xxx_messageInfo_QueryCurrentPlanResponse proto.InternalMessageInfo -func (m *QueryCurrentPlanResponse) GetPlan() *Plan { +func (m *QueryCurrentPlanResponse) GetPlan() []*Plan { if m != nil { return m.Plan } @@ -510,46 +510,46 @@ func init() { } var fileDescriptor_4a334d07ad8374f0 = []byte{ - // 612 bytes of a gzipped FileDescriptorProto + // 611 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x3f, 0x6f, 0xd3, 0x4e, 0x18, 0xee, 0xa5, 0x7f, 0x7e, 0x3f, 0x2e, 0xa8, 0xa0, 0x93, 0x48, 0x8d, 0xa9, 0x4c, 0x75, 0x14, - 0x28, 0xa2, 0xf5, 0xb5, 0xee, 0x82, 0x8a, 0x40, 0x40, 0x25, 0x44, 0x11, 0x54, 0x10, 0x04, 0x03, + 0x28, 0xa2, 0xf1, 0xb5, 0xc9, 0x82, 0x8a, 0x40, 0x40, 0x25, 0x44, 0x11, 0x54, 0x10, 0x04, 0x03, 0x4b, 0x74, 0x89, 0x4f, 0x89, 0x85, 0xed, 0x73, 0x7d, 0xe7, 0x8a, 0xa8, 0xea, 0xc2, 0xc4, 0x88, 0xc4, 0xce, 0xc6, 0xc2, 0x27, 0x61, 0xac, 0xc4, 0xc2, 0xd0, 0x01, 0x25, 0x7c, 0x10, 0xe4, 0xf3, - 0x19, 0x39, 0x8d, 0x9d, 0x02, 0x53, 0xe2, 0x7b, 0x9f, 0xe7, 0x79, 0x9f, 0xd7, 0xf7, 0xbc, 0x86, - 0xb8, 0xc3, 0x45, 0xc0, 0x05, 0x49, 0xa2, 0x6e, 0x4c, 0x5d, 0x46, 0xf6, 0x37, 0xda, 0x4c, 0xd2, - 0x0d, 0xb2, 0x97, 0xb0, 0xb8, 0x6f, 0x47, 0x31, 0x97, 0x1c, 0x35, 0x32, 0x8c, 0xad, 0x31, 0xb6, - 0xc6, 0x98, 0x8b, 0x5d, 0xce, 0xbb, 0x3e, 0x23, 0x34, 0xf2, 0x08, 0x0d, 0x43, 0x2e, 0xa9, 0xf4, - 0x78, 0x28, 0x32, 0x96, 0xb9, 0x5c, 0xa1, 0x9c, 0xab, 0x28, 0x14, 0xbe, 0x08, 0x17, 0x9e, 0xa7, - 0xad, 0xb6, 0x93, 0x38, 0x66, 0xa1, 0x7c, 0xe6, 0xd3, 0xb0, 0xc9, 0xf6, 0x12, 0x26, 0x24, 0x7e, - 0x02, 0x8d, 0xf1, 0x92, 0x88, 0x78, 0x28, 0x18, 0x5a, 0x87, 0x33, 0x91, 0x4f, 0x43, 0x03, 0x2c, - 0x81, 0x95, 0xba, 0xb3, 0x68, 0x97, 0x3b, 0xb4, 0x15, 0x47, 0x21, 0xf1, 0x9a, 0x6e, 0x74, 0x3f, - 0x8a, 0x7c, 0x8f, 0xb9, 0x85, 0x46, 0x08, 0xc1, 0x99, 0x90, 0x06, 0x4c, 0x89, 0x9d, 0x69, 0xaa, - 0xff, 0xd8, 0xd1, 0xcd, 0x47, 0xe0, 0xba, 0x79, 0x03, 0xce, 0xf5, 0x98, 0xd7, 0xed, 0x49, 0xc5, - 0x98, 0x6e, 0xea, 0x27, 0xbc, 0x03, 0xb1, 0xe2, 0xbc, 0xcc, 0x5c, 0xb8, 0xdb, 0x29, 0x3a, 0x14, - 0x89, 0x78, 0x21, 0xa9, 0x64, 0x79, 0xb7, 0xcb, 0xb0, 0xee, 0x53, 0x21, 0x5b, 0x23, 0x12, 0x30, - 0x3d, 0x7a, 0xa4, 0x4e, 0xb6, 0x6a, 0x06, 0xc0, 0x1e, 0xbc, 0x32, 0x51, 0x4a, 0x3b, 0xb9, 0x05, - 0x0d, 0x3d, 0xb2, 0xdb, 0xea, 0xe4, 0x90, 0x96, 0x48, 0x31, 0x46, 0x6d, 0x09, 0xac, 0x9c, 0x6d, - 0x36, 0x92, 0x52, 0x85, 0xb4, 0xc9, 0xe3, 0x99, 0xff, 0xc1, 0xf9, 0x1a, 0xbe, 0x03, 0x4d, 0xd5, - 0xea, 0x29, 0x77, 0x13, 0x9f, 0xbd, 0x62, 0xb1, 0x48, 0x2f, 0xb1, 0xe0, 0x36, 0x50, 0x85, 0x56, - 0xe1, 0x15, 0xc1, 0xec, 0x68, 0x37, 0x7d, 0x51, 0x01, 0xbc, 0x54, 0x4a, 0xd7, 0x0e, 0x77, 0xe1, - 0x39, 0xcd, 0xdf, 0xd7, 0x25, 0x03, 0x2c, 0x4d, 0xaf, 0xd4, 0x9d, 0xab, 0x55, 0x77, 0x36, 0x22, - 0xd4, 0x9c, 0x0f, 0x46, 0x74, 0xf1, 0x02, 0xbc, 0x90, 0xdd, 0x4b, 0x22, 0x7b, 0x3c, 0xf6, 0x64, - 0x3f, 0x4f, 0x8b, 0x03, 0x1b, 0x27, 0x0b, 0xda, 0x82, 0x01, 0xff, 0xa3, 0xae, 0x1b, 0x33, 0x21, - 0xb4, 0xfd, 0xfc, 0xd1, 0x39, 0x9e, 0x85, 0xb3, 0x8a, 0x84, 0x3e, 0x01, 0x58, 0x2f, 0xe4, 0x0c, - 0x91, 0x2a, 0x77, 0x15, 0x61, 0x35, 0xd7, 0xff, 0x9c, 0x90, 0xd9, 0xc2, 0xab, 0xef, 0xbe, 0xfd, - 0xfc, 0x58, 0xbb, 0x86, 0x96, 0x49, 0xc5, 0xa2, 0x74, 0x32, 0x52, 0x2b, 0x8d, 0x2f, 0xfa, 0x0c, - 0x60, 0xbd, 0x90, 0xc5, 0x53, 0x0c, 0x8e, 0x87, 0xfc, 0x14, 0x83, 0x25, 0x31, 0xc7, 0x9b, 0xca, - 0xe0, 0x1a, 0xba, 0x59, 0x65, 0x90, 0x66, 0x24, 0x65, 0x90, 0x1c, 0xa4, 0xf9, 0x38, 0x44, 0xc7, - 0x00, 0x36, 0xca, 0x43, 0x8b, 0xb6, 0x26, 0x3a, 0x98, 0xb8, 0x34, 0xe6, 0xed, 0x7f, 0xe2, 0xea, - 0x41, 0x76, 0xd4, 0x20, 0xf7, 0xd0, 0x5d, 0x32, 0xf9, 0x93, 0x34, 0xb6, 0x43, 0xe4, 0xa0, 0xb0, - 0xa9, 0x87, 0xef, 0x6b, 0x00, 0x7d, 0x01, 0x70, 0x7e, 0x34, 0xe9, 0xc8, 0x99, 0x68, 0xad, 0x74, - 0xab, 0xcc, 0xcd, 0xbf, 0xe2, 0xe8, 0x31, 0x88, 0x1a, 0xe3, 0x06, 0xba, 0x5e, 0x35, 0xc6, 0x89, - 0x45, 0x7b, 0xf0, 0xf0, 0xeb, 0xc0, 0x02, 0x47, 0x03, 0x0b, 0xfc, 0x18, 0x58, 0xe0, 0xc3, 0xd0, - 0x9a, 0x3a, 0x1a, 0x5a, 0x53, 0xdf, 0x87, 0xd6, 0xd4, 0xeb, 0xd5, 0xae, 0x27, 0x7b, 0x49, 0xdb, - 0xee, 0xf0, 0x20, 0x17, 0xcb, 0x7e, 0xd6, 0x84, 0xfb, 0x86, 0xbc, 0xfd, 0xad, 0x2c, 0xfb, 0x11, - 0x13, 0xed, 0x39, 0xf5, 0xa9, 0xde, 0xfc, 0x15, 0x00, 0x00, 0xff, 0xff, 0xf3, 0xd7, 0x94, 0x82, - 0x2c, 0x06, 0x00, 0x00, + 0x19, 0x39, 0x8d, 0x9d, 0x02, 0x53, 0xe2, 0xbb, 0xe7, 0x79, 0xde, 0xe7, 0xf5, 0xfb, 0xbc, 0x86, + 0xb8, 0xcb, 0x85, 0xcf, 0x05, 0x89, 0xc3, 0x5e, 0x44, 0x1d, 0x46, 0xf6, 0x37, 0x3b, 0x4c, 0xd2, + 0x4d, 0xb2, 0x17, 0xb3, 0x68, 0x60, 0x87, 0x11, 0x97, 0x1c, 0xd5, 0x52, 0x8c, 0xad, 0x31, 0xb6, + 0xc6, 0x98, 0xcb, 0x3d, 0xce, 0x7b, 0x1e, 0x23, 0x34, 0x74, 0x09, 0x0d, 0x02, 0x2e, 0xa9, 0x74, + 0x79, 0x20, 0x52, 0x96, 0xb9, 0x5a, 0xa2, 0x9c, 0xa9, 0x28, 0x14, 0xbe, 0x08, 0x97, 0x9e, 0x27, + 0xa5, 0xb6, 0xe3, 0x28, 0x62, 0x81, 0x7c, 0xe6, 0xd1, 0xa0, 0xc5, 0xf6, 0x62, 0x26, 0x24, 0x7e, + 0x02, 0x8d, 0xc9, 0x2b, 0x11, 0xf2, 0x40, 0x30, 0xb4, 0x01, 0xe7, 0x42, 0x8f, 0x06, 0x06, 0x58, + 0x99, 0x5d, 0xab, 0x36, 0x96, 0xed, 0x62, 0x87, 0xb6, 0xe2, 0x28, 0x24, 0xae, 0xeb, 0x42, 0xf7, + 0xc3, 0xd0, 0x73, 0x99, 0x93, 0x2b, 0x84, 0x10, 0x9c, 0x0b, 0xa8, 0xcf, 0x0c, 0xb0, 0x02, 0xd6, + 0xce, 0xb4, 0xd4, 0x7f, 0xdc, 0xd0, 0xc5, 0xc7, 0xe0, 0xba, 0x78, 0x0d, 0x2e, 0xf4, 0x99, 0xdb, + 0xeb, 0x4b, 0xc5, 0x98, 0x6d, 0xe9, 0x27, 0xbc, 0x03, 0xb1, 0xe2, 0xbc, 0x4c, 0x5d, 0x38, 0xdb, + 0x09, 0x3a, 0x10, 0xb1, 0x78, 0x21, 0xa9, 0x64, 0x59, 0xb5, 0xcb, 0xb0, 0xea, 0x51, 0x21, 0xdb, + 0x63, 0x12, 0x30, 0x39, 0x7a, 0xa4, 0x4e, 0xb6, 0x2a, 0x06, 0xc0, 0x2e, 0xbc, 0x32, 0x55, 0x4a, + 0x3b, 0xb9, 0x05, 0x0d, 0xdd, 0xb2, 0xd3, 0xee, 0x66, 0x90, 0xb6, 0x48, 0x30, 0x46, 0x65, 0x05, + 0xac, 0x9d, 0x6d, 0xd5, 0xe2, 0x42, 0x85, 0xa4, 0xc8, 0xe3, 0xb9, 0xff, 0xc1, 0xf9, 0x0a, 0xbe, + 0x03, 0x4d, 0x55, 0xea, 0x29, 0x77, 0x62, 0x8f, 0xbd, 0x62, 0x91, 0x48, 0x86, 0x98, 0x73, 0xeb, + 0xab, 0x8b, 0x76, 0xee, 0x15, 0xc1, 0xf4, 0x68, 0x37, 0x79, 0x51, 0x3e, 0xbc, 0x54, 0x48, 0xd7, + 0x0e, 0x77, 0xe1, 0x39, 0xcd, 0xdf, 0xd7, 0x57, 0x7a, 0x66, 0x57, 0xcb, 0x66, 0x36, 0x26, 0xd4, + 0x5a, 0xf4, 0xc7, 0x74, 0xf1, 0x12, 0xbc, 0x90, 0xce, 0x25, 0x96, 0x7d, 0x1e, 0xb9, 0x72, 0x90, + 0xa5, 0xa5, 0x01, 0x6b, 0x27, 0x2f, 0xb4, 0x05, 0x03, 0xfe, 0x47, 0x1d, 0x27, 0x62, 0x42, 0x68, + 0xfb, 0xd9, 0x63, 0xe3, 0x78, 0x1e, 0xce, 0x2b, 0x12, 0xfa, 0x04, 0x60, 0x35, 0x97, 0x33, 0x44, + 0xca, 0xdc, 0x95, 0x84, 0xd5, 0xdc, 0xf8, 0x73, 0x42, 0x6a, 0x0b, 0xaf, 0xbf, 0xfb, 0xf6, 0xf3, + 0x63, 0xe5, 0x1a, 0x5a, 0x25, 0x25, 0x8b, 0xd2, 0x4d, 0x49, 0xed, 0x24, 0xbe, 0xe8, 0x33, 0x80, + 0xd5, 0x5c, 0x16, 0x4f, 0x31, 0x38, 0x19, 0xf2, 0x53, 0x0c, 0x16, 0xc4, 0x1c, 0x37, 0x95, 0xc1, + 0x3a, 0xba, 0x59, 0x66, 0x90, 0xa6, 0x24, 0x65, 0x90, 0x1c, 0x24, 0xf9, 0x38, 0x44, 0xc7, 0x00, + 0xd6, 0x8a, 0x43, 0x8b, 0xb6, 0xa6, 0x3a, 0x98, 0xba, 0x34, 0xe6, 0xed, 0x7f, 0xe2, 0xea, 0x46, + 0x76, 0x54, 0x23, 0xf7, 0xd0, 0x5d, 0x32, 0xfd, 0x93, 0x34, 0xb1, 0x43, 0xe4, 0x20, 0xb7, 0xa9, + 0x87, 0xef, 0x2b, 0x00, 0x7d, 0x01, 0x70, 0x71, 0x3c, 0xe9, 0xa8, 0x31, 0xd5, 0x5a, 0xe1, 0x56, + 0x99, 0xcd, 0xbf, 0xe2, 0xe8, 0x36, 0x88, 0x6a, 0xe3, 0x06, 0xba, 0x5e, 0xd6, 0xc6, 0x89, 0x45, + 0x7b, 0xf0, 0xf0, 0xeb, 0xd0, 0x02, 0x47, 0x43, 0x0b, 0xfc, 0x18, 0x5a, 0xe0, 0xc3, 0xc8, 0x9a, + 0x39, 0x1a, 0x59, 0x33, 0xdf, 0x47, 0xd6, 0xcc, 0xeb, 0xf5, 0x9e, 0x2b, 0xfb, 0x71, 0xc7, 0xee, + 0x72, 0x3f, 0x13, 0x4b, 0x7f, 0xea, 0xc2, 0x79, 0x43, 0xde, 0xfe, 0x56, 0x96, 0x83, 0x90, 0x89, + 0xce, 0x82, 0xfa, 0x54, 0x37, 0x7f, 0x05, 0x00, 0x00, 0xff, 0xff, 0x46, 0x87, 0x09, 0xdc, 0x2c, + 0x06, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -806,17 +806,19 @@ func (m *QueryCurrentPlanResponse) MarshalToSizedBuffer(dAtA []byte) (int, error _ = i var l int _ = l - if m.Plan != nil { - { - size, err := m.Plan.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err + if len(m.Plan) > 0 { + for iNdEx := len(m.Plan) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Plan[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) } - i -= size - i = encodeVarintQuery(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0xa } - i-- - dAtA[i] = 0xa } return len(dAtA) - i, nil } @@ -1083,9 +1085,11 @@ func (m *QueryCurrentPlanResponse) Size() (n int) { } var l int _ = l - if m.Plan != nil { - l = m.Plan.Size() - n += 1 + l + sovQuery(uint64(l)) + if len(m.Plan) > 0 { + for _, e := range m.Plan { + l = e.Size() + n += 1 + l + sovQuery(uint64(l)) + } } return n } @@ -1304,10 +1308,8 @@ func (m *QueryCurrentPlanResponse) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if m.Plan == nil { - m.Plan = &Plan{} - } - if err := m.Plan.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + m.Plan = append(m.Plan, &Plan{}) + if err := m.Plan[len(m.Plan)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/x/upgrade/types/upgrade_config.go b/x/upgrade/types/upgrade_config.go index bb1a281365..d7312585c5 100644 --- a/x/upgrade/types/upgrade_config.go +++ b/x/upgrade/types/upgrade_config.go @@ -1,16 +1,43 @@ package types +import "math" + func NewUpgradeConfig() UpgradeConfig { - return UpgradeConfig(map[int64]Plan{}) + return UpgradeConfig(map[int64][]*Plan{}) } -type UpgradeConfig map[int64]Plan +type UpgradeConfig map[int64][]*Plan var ( MainnetChainID = "inscription_9000-1" - MainnetConfig = UpgradeConfig(map[int64]Plan{}) + MainnetConfig = UpgradeConfig(map[int64][]*Plan{}) ) -func (c UpgradeConfig) SetPlan(plan Plan) { - c[plan.Height] = plan +func (c UpgradeConfig) SetPlan(plan *Plan) { + c[plan.Height] = append(c[plan.Height], plan) +} + +func (c UpgradeConfig) ClearPlan(height int64) { + c[height] = nil +} + +func (c UpgradeConfig) GetPlan(height int64) []*Plan { + plans, exist := c[height] + if exist { + return c[height] + } + + // get recent upgrade plan + var ( + recentHeight = int64(math.MaxInt64) + ) + for vHeight, vPlans := range c { + if vHeight > height { + if vHeight < recentHeight { + plans = vPlans + recentHeight = vHeight + } + } + } + return plans } diff --git a/x/upgrade/types/upgrade_config_test.go b/x/upgrade/types/upgrade_config_test.go new file mode 100644 index 0000000000..dcf00ee4a2 --- /dev/null +++ b/x/upgrade/types/upgrade_config_test.go @@ -0,0 +1,74 @@ +package types + +import ( + "reflect" + "testing" +) + +func TestUpgradeConfig_GetPlan(t *testing.T) { + type args struct { + height int64 + } + tests := []struct { + name string + c UpgradeConfig + args args + want []*Plan + }{ + { + name: "TestUpgradeConfig_GetPlan Case 1", + c: UpgradeConfig(map[int64][]*Plan{ + 1: {{ + Name: "Upgrade-1", + Height: 1, + }}, + 11: {{ + Name: "Upgrade-2", + Height: 11, + }}, + 20: {{ + Name: "Upgrade-3", + Height: 20, + }}, + }), + args: args{ + height: 10, + }, + want: []*Plan{{ + Name: "Upgrade-2", + Height: 11, + }}, + }, + { + name: "TestUpgradeConfig_GetPlan Case 2", + c: UpgradeConfig(map[int64][]*Plan{ + 1: {{ + Name: "Upgrade-1", + Height: 1, + }}, + 11: {{ + Name: "Upgrade-2", + Height: 11, + }}, + 20: {{ + Name: "Upgrade-3", + Height: 20, + }}, + }), + args: args{ + height: 20, + }, + want: []*Plan{{ + Name: "Upgrade-3", + Height: 20, + }}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.c.GetPlan(tt.args.height); !reflect.DeepEqual(got, tt.want) { + t.Errorf("UpgradeConfig.GetPlan() = %v, want %v", got, tt.want) + } + }) + } +}