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  }