2019-11-08 06:40:56 -08:00
|
|
|
package upgrade
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2020-07-17 08:34:37 -07:00
|
|
|
"time"
|
2020-01-16 13:46:51 -08:00
|
|
|
|
2019-11-08 06:40:56 -08:00
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
|
|
|
2020-06-18 11:12:44 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/telemetry"
|
2019-11-08 06:40:56 -08:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2020-06-10 11:54:15 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/upgrade/keeper"
|
2020-06-18 11:12:44 -07:00
|
|
|
"github.com/cosmos/cosmos-sdk/x/upgrade/types"
|
2020-11-24 03:45:33 -08:00
|
|
|
|
|
|
|
ibctmtypes "github.com/cosmos/cosmos-sdk/x/ibc/light-clients/07-tendermint/types"
|
2019-11-08 06:40:56 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
// BeginBlock will check if there is a scheduled plan and if it is ready to be executed.
|
2020-01-03 06:37:29 -08:00
|
|
|
// If the current height is in the provided set of heights to skip, it will skip and clear the upgrade plan.
|
2019-11-08 06:40:56 -08:00
|
|
|
// If it is ready, it will execute it if the handler is installed, and panic/abort otherwise.
|
|
|
|
// If the plan is not ready, it will ensure the handler is not registered too early (and abort otherwise).
|
|
|
|
//
|
2020-01-03 06:37:29 -08:00
|
|
|
// The purpose is to ensure the binary is switched EXACTLY at the desired block, and to allow
|
2019-11-08 06:40:56 -08:00
|
|
|
// a migration to be executed if needed upon this switch (migration defined in the new binary)
|
2020-01-03 06:37:29 -08:00
|
|
|
// skipUpgradeHeightArray is a set of block heights for which the upgrade must be skipped
|
2020-06-10 11:54:15 -07:00
|
|
|
func BeginBlocker(k keeper.Keeper, ctx sdk.Context, _ abci.RequestBeginBlock) {
|
2020-07-17 12:33:50 -07:00
|
|
|
defer telemetry.ModuleMeasureSince(types.ModuleName, time.Now(), telemetry.MetricKeyBeginBlocker)
|
2020-06-18 11:12:44 -07:00
|
|
|
|
2019-11-08 06:40:56 -08:00
|
|
|
plan, found := k.GetUpgradePlan(ctx)
|
|
|
|
if !found {
|
|
|
|
return
|
|
|
|
}
|
2019-11-29 12:17:13 -08:00
|
|
|
|
2020-11-24 03:45:33 -08:00
|
|
|
// Once we are at the last block this chain will commit, set the upgraded consensus state
|
|
|
|
// so that IBC clients can use the last NextValidatorsHash as a trusted kernel for verifying
|
|
|
|
// headers on the next version of the chain.
|
|
|
|
// Set the time to the last block time of the current chain.
|
|
|
|
// In order for a client to upgrade successfully, the first block of the new chain must be committed
|
|
|
|
// within the trusting period of the last block time on this chain.
|
|
|
|
if plan.IsIBCPlan() && ctx.BlockHeight() == plan.Height-1 {
|
|
|
|
upgradedConsState := &ibctmtypes.ConsensusState{
|
|
|
|
Timestamp: ctx.BlockTime(),
|
|
|
|
NextValidatorsHash: ctx.BlockHeader().NextValidatorsHash,
|
|
|
|
}
|
2020-12-17 09:32:19 -08:00
|
|
|
k.SetUpgradedConsensusState(ctx, plan.Height, upgradedConsState)
|
2020-11-24 03:45:33 -08:00
|
|
|
}
|
2020-01-03 06:37:29 -08:00
|
|
|
// To make sure clear upgrade is executed at the same block
|
2019-11-08 06:40:56 -08:00
|
|
|
if plan.ShouldExecute(ctx) {
|
2020-01-03 06:37:29 -08:00
|
|
|
// 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)
|
|
|
|
ctx.Logger().Info(skipUpgradeMsg)
|
|
|
|
|
|
|
|
// Clear the upgrade plan at current height
|
|
|
|
k.ClearUpgradePlan(ctx)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-11-08 06:40:56 -08:00
|
|
|
if !k.HasHandler(plan.Name) {
|
2020-08-19 08:58:43 -07:00
|
|
|
upgradeMsg := BuildUpgradeNeededMsg(plan)
|
2019-11-08 06:40:56 -08:00
|
|
|
// We don't have an upgrade handler for this upgrade name, meaning this software is out of date so shutdown
|
|
|
|
ctx.Logger().Error(upgradeMsg)
|
2020-02-27 22:26:04 -08:00
|
|
|
|
|
|
|
// Write the upgrade info to disk. The UpgradeStoreLoader uses this info to perform or skip
|
|
|
|
// store migrations.
|
|
|
|
err := k.DumpUpgradeInfoToDisk(ctx.BlockHeight(), plan.Name)
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Errorf("unable to write upgrade info to filesystem: %s", err.Error()))
|
|
|
|
}
|
|
|
|
|
2019-11-08 06:40:56 -08:00
|
|
|
panic(upgradeMsg)
|
|
|
|
}
|
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
|
|
|
// if we have a pending upgrade, but it is not yet time, make sure we did not
|
|
|
|
// set the handler already
|
|
|
|
if k.HasHandler(plan.Name) {
|
|
|
|
downgradeMsg := fmt.Sprintf("BINARY UPDATED BEFORE TRIGGER! UPGRADE \"%s\" - in binary but not executed on chain", plan.Name)
|
|
|
|
ctx.Logger().Error(downgradeMsg)
|
|
|
|
panic(downgradeMsg)
|
|
|
|
}
|
|
|
|
}
|
2020-08-19 08:58:43 -07:00
|
|
|
|
|
|
|
// BuildUpgradeNeededMsg prints the message that notifies that an upgrade is needed.
|
|
|
|
func BuildUpgradeNeededMsg(plan types.Plan) string {
|
|
|
|
return fmt.Sprintf("UPGRADE \"%s\" NEEDED at %s: %s", plan.Name, plan.DueAt(), plan.Info)
|
|
|
|
}
|