From 3275c25ac80ae9e4e805ea235a2f4e280ca8a97c Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 26 Jan 2026 17:10:46 +0100 Subject: [PATCH 1/3] migrate to height upgrade style --- app/app.go | 2 ++ app/upgrades.go | 62 ++++++++++++++++++++++++++++++++++- app/upgrades/types.go | 1 + app/upgrades/upgrade_0_3_0.go | 3 +- 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/app/app.go b/app/app.go index 7fd8a09..215d4f7 100644 --- a/app/app.go +++ b/app/app.go @@ -781,6 +781,8 @@ func (app *NillionApp) Name() string { return app.BaseApp.Name() } // PreBlocker application updates every pre block func (app *NillionApp) PreBlocker(ctx sdk.Context, _ *abci.RequestFinalizeBlock) (*sdk.ResponsePreBlock, error) { + // Schedule height-based upgrades before the upgrade module's PreBlock runs + app.scheduleHeightBasedUpgrades(ctx) return app.ModuleManager.PreBlock(ctx) } diff --git a/app/upgrades.go b/app/upgrades.go index 566bf21..9cb8260 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -1,8 +1,11 @@ package nillionapp import ( - upgradetypes "cosmossdk.io/x/upgrade/types" "fmt" + + upgradetypes "cosmossdk.io/x/upgrade/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/NillionNetwork/nilchain/app/upgrades" ) @@ -35,8 +38,65 @@ func (app NillionApp) setupUpgradeStoreLoaders() { } for _, upgrade := range Upgrades { + // Handle upgrade info from disk (standard upgrade module halt) if upgradeInfo.Name == upgrade.UpgradeName { app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgradeInfo.Height, &upgrade.StoreUpgrades)) + return + } + } + + // Handle height-based upgrades with manual --halt-height (no disk info). + // UpgradeStoreLoader only applies when latestVersion == upgradeHeight - 1, + // so setting this unconditionally is safe - it's a no-op at other heights. + for _, upgrade := range Upgrades { + if upgrade.UpgradeHeight > 0 && len(upgrade.StoreUpgrades.Added) > 0 { + app.SetStoreLoader(upgradetypes.UpgradeStoreLoader(upgrade.UpgradeHeight, &upgrade.StoreUpgrades)) + return + } + } +} + +// scheduleHeightBasedUpgrades schedules upgrades that have a non-zero UpgradeHeight. +// This should be called in PreBlocker before the upgrade module's PreBlock runs. +// Supports manual halt-height flow: validators set --halt-height, restart with new binary, +// and this function schedules the upgrade to run on the first block. +func (app NillionApp) scheduleHeightBasedUpgrades(ctx sdk.Context) { + for _, upgrade := range Upgrades { + if upgrade.UpgradeHeight == 0 { + continue + } + + // Skip if we've already passed the upgrade height (upgrade already applied) + if ctx.BlockHeight() > upgrade.UpgradeHeight { + continue + } + + // Check if this upgrade is already scheduled + plan, err := app.UpgradeKeeper.GetUpgradePlan(ctx) + if err == nil && plan.Name == upgrade.UpgradeName { + continue + } + + // Check if upgrade was already applied + applied, err := app.UpgradeKeeper.GetDoneHeight(ctx, upgrade.UpgradeName) + if err == nil && applied > 0 { + continue + } + + // Schedule the upgrade at the target height, or current height if we're at/past it + scheduleHeight := upgrade.UpgradeHeight + if ctx.BlockHeight() == upgrade.UpgradeHeight { + // We're at the upgrade height (post manual halt-height restart) + // Schedule for current height so upgrade module applies it + scheduleHeight = ctx.BlockHeight() + } + + err = app.UpgradeKeeper.ScheduleUpgrade(ctx, upgradetypes.Plan{ + Name: upgrade.UpgradeName, + Height: scheduleHeight, + }) + if err != nil { + app.Logger().Error("failed to schedule upgrade", "name", upgrade.UpgradeName, "height", scheduleHeight, "error", err) } } } diff --git a/app/upgrades/types.go b/app/upgrades/types.go index a465abe..46eb779 100644 --- a/app/upgrades/types.go +++ b/app/upgrades/types.go @@ -8,6 +8,7 @@ import ( type Upgrade struct { UpgradeName string + UpgradeHeight int64 // 0 = governance-triggered, >0 = height-triggered CreateUpgradeHandler func(mm module.Manager, configurator module.Configurator) upgradetypes.UpgradeHandler StoreUpgrades types.StoreUpgrades } diff --git a/app/upgrades/upgrade_0_3_0.go b/app/upgrades/upgrade_0_3_0.go index 7e4b989..34bff5a 100644 --- a/app/upgrades/upgrade_0_3_0.go +++ b/app/upgrades/upgrade_0_3_0.go @@ -9,7 +9,8 @@ import ( ) var Upgrade_0_3_0 = Upgrade{ - UpgradeName: "v0.3.0", + UpgradeName: "v0.3.0", + UpgradeHeight: 5335502, CreateUpgradeHandler: func(mm module.Manager, configurator module.Configurator) upgradetypes.UpgradeHandler { return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { return mm.RunMigrations(ctx, configurator, fromVM) From fa81f2a3f598a85c7256aa51a668222e9d015dba Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 26 Jan 2026 18:42:42 +0100 Subject: [PATCH 2/3] add migration set --- app/upgrades.go | 4 ++++ app/upgrades/types.go | 7 ++++++- app/upgrades/upgrade_0_2_1.go | 2 +- app/upgrades/upgrade_0_2_4.go | 2 +- app/upgrades/upgrade_0_3_0.go | 17 +++++++++++++++-- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/app/upgrades.go b/app/upgrades.go index 9cb8260..3422166 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -16,12 +16,16 @@ var Upgrades = []upgrades.Upgrade{ } func (app NillionApp) setupUpgradeHandlers() { + keepers := upgrades.Keepers{ + MigrationMngrKeeper: &app.MigrationMngrKeeper, + } for _, upgrade := range Upgrades { app.UpgradeKeeper.SetUpgradeHandler( upgrade.UpgradeName, upgrade.CreateUpgradeHandler( *app.ModuleManager, app.configurator, + keepers, ), ) } diff --git a/app/upgrades/types.go b/app/upgrades/types.go index 46eb779..8bbef9b 100644 --- a/app/upgrades/types.go +++ b/app/upgrades/types.go @@ -3,12 +3,17 @@ package upgrades import ( "cosmossdk.io/store/types" upgradetypes "cosmossdk.io/x/upgrade/types" + migrationmngr_keeper "github.com/evstack/ev-abci/modules/migrationmngr/keeper" "github.com/cosmos/cosmos-sdk/types/module" ) +type Keepers struct { + MigrationMngrKeeper *migrationmngr_keeper.Keeper +} + type Upgrade struct { UpgradeName string UpgradeHeight int64 // 0 = governance-triggered, >0 = height-triggered - CreateUpgradeHandler func(mm module.Manager, configurator module.Configurator) upgradetypes.UpgradeHandler + CreateUpgradeHandler func(mm module.Manager, configurator module.Configurator, keepers Keepers) upgradetypes.UpgradeHandler StoreUpgrades types.StoreUpgrades } diff --git a/app/upgrades/upgrade_0_2_1.go b/app/upgrades/upgrade_0_2_1.go index 984cc22..03d17df 100644 --- a/app/upgrades/upgrade_0_2_1.go +++ b/app/upgrades/upgrade_0_2_1.go @@ -10,7 +10,7 @@ import ( var Upgrade_0_2_1 = Upgrade{ UpgradeName: "v0.2.1", - CreateUpgradeHandler: func(mm module.Manager, configurator module.Configurator) upgradetypes.UpgradeHandler { + CreateUpgradeHandler: func(mm module.Manager, configurator module.Configurator, _ Keepers) upgradetypes.UpgradeHandler { return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { return mm.RunMigrations(ctx, configurator, fromVM) } diff --git a/app/upgrades/upgrade_0_2_4.go b/app/upgrades/upgrade_0_2_4.go index 6515fa3..373e23c 100644 --- a/app/upgrades/upgrade_0_2_4.go +++ b/app/upgrades/upgrade_0_2_4.go @@ -10,7 +10,7 @@ import ( var Upgrade_0_2_4 = Upgrade{ UpgradeName: "v0.2.4-rc11", - CreateUpgradeHandler: func(mm module.Manager, configurator module.Configurator) upgradetypes.UpgradeHandler { + CreateUpgradeHandler: func(mm module.Manager, configurator module.Configurator, _ Keepers) upgradetypes.UpgradeHandler { return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { return mm.RunMigrations(ctx, configurator, fromVM) } diff --git a/app/upgrades/upgrade_0_3_0.go b/app/upgrades/upgrade_0_3_0.go index 34bff5a..bfcf927 100644 --- a/app/upgrades/upgrade_0_3_0.go +++ b/app/upgrades/upgrade_0_3_0.go @@ -2,17 +2,30 @@ package upgrades import ( "context" + "cosmossdk.io/store/types" upgradetypes "cosmossdk.io/x/upgrade/types" - migrationmngrtypes "github.com/evstack/ev-abci/modules/migrationmngr/types" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" + migrationmngrtypes "github.com/evstack/ev-abci/modules/migrationmngr/types" ) var Upgrade_0_3_0 = Upgrade{ UpgradeName: "v0.3.0", UpgradeHeight: 5335502, - CreateUpgradeHandler: func(mm module.Manager, configurator module.Configurator) upgradetypes.UpgradeHandler { + CreateUpgradeHandler: func(mm module.Manager, configurator module.Configurator, keepers Keepers) upgradetypes.UpgradeHandler { return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + sdkCtx := sdk.UnwrapSDKContext(ctx) + migrationHeight := uint64(sdkCtx.BlockHeight() + 2) + + if err := keepers.MigrationMngrKeeper.Migration.Set(ctx, migrationmngrtypes.EvolveMigration{ + BlockHeight: migrationHeight, + // Sequencer: , //TODO: set sequencer address + StayOnComet: true, + }); err != nil { + return nil, err + } + return mm.RunMigrations(ctx, configurator, fromVM) } }, From a63ee1249961c2f40aac0f98a9c258b5deb3fad7 Mon Sep 17 00:00:00 2001 From: tac0turtle Date: Mon, 26 Jan 2026 19:05:25 +0100 Subject: [PATCH 3/3] add polkachu key --- app/upgrades/upgrade_0_3_0.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app/upgrades/upgrade_0_3_0.go b/app/upgrades/upgrade_0_3_0.go index bfcf927..7f0c69f 100644 --- a/app/upgrades/upgrade_0_3_0.go +++ b/app/upgrades/upgrade_0_3_0.go @@ -2,9 +2,12 @@ package upgrades import ( "context" + "encoding/base64" + "cosmossdk.io/api/cosmos/crypto/ed25519" "cosmossdk.io/store/types" upgradetypes "cosmossdk.io/x/upgrade/types" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" migrationmngrtypes "github.com/evstack/ev-abci/modules/migrationmngr/types" @@ -18,9 +21,27 @@ var Upgrade_0_3_0 = Upgrade{ sdkCtx := sdk.UnwrapSDKContext(ctx) migrationHeight := uint64(sdkCtx.BlockHeight() + 2) + // Decode the base64 key from `tendermint show-validator` + keyBytes, err := base64.StdEncoding.DecodeString("z4OQC3UzB8xUlJKigQu/mI7mclgofa8qGQtp3RUPcqc=") + if err != nil { + return nil, err + } + + // Create the ed25519 public key + pubKey := &ed25519.PubKey{Key: keyBytes} + + // Wrap it in a codectypes.Any + pubKeyAny, err := codectypes.NewAnyWithValue(pubKey) + if err != nil { + return nil, err + } + if err := keepers.MigrationMngrKeeper.Migration.Set(ctx, migrationmngrtypes.EvolveMigration{ BlockHeight: migrationHeight, - // Sequencer: , //TODO: set sequencer address + Sequencer: migrationmngrtypes.Sequencer{ + Name: "polkachu", + ConsensusPubkey: pubKeyAny, + }, StayOnComet: true, }); err != nil { return nil, err