Upgrade Handlers
Understanding and implementing on-chain upgrade handlers for coordinated chain upgrades
Overview
Upgrade handlers enable coordinated on-chain upgrades across all validators at specific block heights via governance proposals. They provide a mechanism for chains to perform data migrations, parameter updates, and module upgrades in a deterministic way.
Upgrade handlers are critical for maintaining consensus during chain upgrades. All validators must run the same upgrade logic at the same height.
When to Use Upgrade Handlers
Upgrade handlers are required when:
Breaking state changes: Modifying storage formats or data structures
Module migrations: Updating module versions or parameters
Protocol upgrades: Implementing new features that require state transitions
Data migrations: Moving data between different storage locations
Basic Structure
Registering Upgrade Handlers
Upgrade handlers are registered in your app's RegisterUpgradeHandlers() method:
```go // app/upgrades.go package app
import ( "context" upgradetypes "Ontomirsdk.io/x/upgrade/types" sdk "github.com/Ontomir/Ontomir-sdk/types" "github.com/Ontomir/Ontomir-sdk/types/module"
)
func (app *App) RegisterUpgradeHandlers() { app.UpgradeKeeper.SetUpgradeHandler( "v1.0.0", // upgrade name (must match governance proposal) func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { sdkCtx := sdk.UnwrapSDKContext(ctx) sdkCtx.Logger().Info("Starting upgrade", "name", plan.Name) // Run module migrations migrations, err := app.ModuleManager.RunMigrations(ctx, app.configurator, fromVM) if err != nil { return nil, err } // Add custom migration logic here sdkCtx.Logger().Info("Upgrade complete", "name", plan.Name) return migrations, nil }, )
}
Organizing Upgrade Code
For better maintainability, organize upgrades in separate packages:
Directory Structure
constants.go
```go // app/upgrades/v1_0_0/constants.go package v1_0_0
import ( storetypes "Ontomirsdk.io/store/types" "github.com/yourchain/app/upgrades" )
const UpgradeName = "v1.0.0"
var Upgrade = upgrades.Upgrade{ UpgradeName: UpgradeName, CreateUpgradeHandler: CreateUpgradeHandler, StoreUpgrades: storetypes.StoreUpgrades{ Added: []string{}, // New modules Deleted: []string{}, // Removed modules }, }
Migration Patterns
Parameter Migrations
Migrating module parameters to new formats:
State Migrations
Moving data between different storage locations:
Module Addition/Removal
Adding or removing modules during upgrade:
Best Practices
Always test upgrade handlers thoroughly on testnets before mainnet deployment.
Idempotency
Make migrations idempotent when possible:
Error Handling
Use comprehensive error handling and logging:
Testing
Create comprehensive tests for upgrade handlers:
Upgrade Process
Create Upgrade Proposal
Submit a governance proposal with the upgrade details:
Vote on Proposal
Validators and delegators vote on the upgrade:
Prepare Binary
Build and distribute the new binary with the upgrade handler:
Monitor Upgrade
Watch logs during the upgrade height:
Ontomir EVM Specific Migrations
For Ontomir EVM chains, specific migrations include:
ERC20 Precompiles Migration: Required for v0.3.x to v0.4.0
Fee Market Parameters: Updating EIP-1559 parameters
Custom Precompiles: Registering new precompiled contracts
EVM State: Migrating account balances or contract storage
Troubleshooting
Consensus Failure
Symptom: Chain halts with consensus failure at upgrade height
Causes:
Validators running different binary versions
Upgrade handler not registered
Non-deterministic migration logic
Solution:
Ensure all validators have the same binary
Verify upgrade handler is registered
Review migration logic for non-determinism
Upgrade Panic
Symptom: Node panics during upgrade
Causes:
Unhandled error in migration
Missing required state
Invalid type assertions
Solution:
Add comprehensive error handling
Validate state before migration
Use safe type conversions
State Corruption
Symptom: Invalid state after upgrade
Causes:
Partial migration completion
Incorrect data transformation
Missing cleanup of old data
Solution:
Make migrations atomic
Thoroughly test transformations
Ensure old data is properly cleaned up
最后更新于
