github.com/Finschia/finschia-sdk@v0.48.1/x/upgrade/abci.go (about) 1 package upgrade 2 3 import ( 4 "fmt" 5 "time" 6 7 ocabci "github.com/Finschia/ostracon/abci/types" 8 9 "github.com/Finschia/finschia-sdk/telemetry" 10 sdk "github.com/Finschia/finschia-sdk/types" 11 "github.com/Finschia/finschia-sdk/x/upgrade/keeper" 12 "github.com/Finschia/finschia-sdk/x/upgrade/types" 13 ) 14 15 // BeginBlock will check if there is a scheduled plan and if it is ready to be executed. 16 // If the current height is in the provided set of heights to skip, it will skip and clear the upgrade plan. 17 // If it is ready, it will execute it if the handler is installed, and panic/abort otherwise. 18 // If the plan is not ready, it will ensure the handler is not registered too early (and abort otherwise). 19 // 20 // The purpose is to ensure the binary is switched EXACTLY at the desired block, and to allow 21 // a migration to be executed if needed upon this switch (migration defined in the new binary) 22 // skipUpgradeHeightArray is a set of block heights for which the upgrade must be skipped 23 func BeginBlocker(k keeper.Keeper, ctx sdk.Context, _ ocabci.RequestBeginBlock) { 24 defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker) 25 26 plan, found := k.GetUpgradePlan(ctx) 27 28 if !k.DowngradeVerified() { 29 k.SetDowngradeVerified(true) 30 lastAppliedPlan, _ := k.GetLastCompletedUpgrade(ctx) 31 // This check will make sure that we are using a valid binary. 32 // It'll panic in these cases if there is no upgrade handler registered for the last applied upgrade. 33 // 1. If there is no scheduled upgrade. 34 // 2. If the plan is not ready. 35 // 3. If the plan is ready and skip upgrade height is set for current height. 36 if !found || !plan.ShouldExecute(ctx) || (plan.ShouldExecute(ctx) && k.IsSkipHeight(ctx.BlockHeight())) { 37 if lastAppliedPlan != "" && !k.HasHandler(lastAppliedPlan) { 38 panic(fmt.Sprintf("Wrong app version %d, upgrade handler is missing for %s upgrade plan", ctx.ConsensusParams().Version.AppVersion, lastAppliedPlan)) 39 } 40 } 41 } 42 43 if !found { 44 return 45 } 46 47 // To make sure clear upgrade is executed at the same block 48 if plan.ShouldExecute(ctx) { 49 // If skip upgrade has been set for current height, we clear the upgrade plan 50 if k.IsSkipHeight(ctx.BlockHeight()) { 51 skipUpgradeMsg := fmt.Sprintf("UPGRADE \"%s\" SKIPPED at %d: %s", plan.Name, plan.Height, plan.Info) 52 ctx.Logger().Info(skipUpgradeMsg) 53 54 // Clear the upgrade plan at current height 55 k.ClearUpgradePlan(ctx) 56 return 57 } 58 59 if !k.HasHandler(plan.Name) { 60 // Write the upgrade info to disk. The UpgradeStoreLoader uses this info to perform or skip 61 // store migrations. 62 err := k.DumpUpgradeInfoWithInfoToDisk(ctx.BlockHeight(), plan.Name, plan.Info) //nolint:staticcheck 63 if err != nil { 64 panic(fmt.Errorf("unable to write upgrade info to filesystem: %s", err.Error())) 65 } 66 67 upgradeMsg := BuildUpgradeNeededMsg(plan) 68 // We don't have an upgrade handler for this upgrade name, meaning this software is out of date so shutdown 69 ctx.Logger().Error(upgradeMsg) 70 71 panic(upgradeMsg) 72 } 73 // We have an upgrade handler for this upgrade name, so apply the upgrade 74 ctx.Logger().Info(fmt.Sprintf("applying upgrade \"%s\" at %s", plan.Name, plan.DueAt())) 75 ctx = ctx.WithBlockGasMeter(sdk.NewInfiniteGasMeter()) 76 k.ApplyUpgrade(ctx, plan) 77 return 78 } 79 80 // if we have a pending upgrade, but it is not yet time, make sure we did not 81 // set the handler already 82 if k.HasHandler(plan.Name) { 83 downgradeMsg := fmt.Sprintf("BINARY UPDATED BEFORE TRIGGER! UPGRADE \"%s\" - in binary but not executed on chain", plan.Name) 84 ctx.Logger().Error(downgradeMsg) 85 panic(downgradeMsg) 86 } 87 } 88 89 // BuildUpgradeNeededMsg prints the message that notifies that an upgrade is needed. 90 func BuildUpgradeNeededMsg(plan types.Plan) string { 91 return fmt.Sprintf("UPGRADE \"%s\" NEEDED at %s: %s", plan.Name, plan.DueAt(), plan.Info) 92 }