How Akash Implements Block Height-Based Upgrades and State Synchronization
Akash implements block height-based upgrades through a centralized registry system in upgrades/types/types.go that registers software upgrades and height-specific patches, while state synchronization relies on the Cosmos SDK's snapshot protocol configured via cmd/akashd/main.go to bootstrap nodes from trusted snapshots without replaying the entire chain.
The Akash Network node implementation builds on the Cosmos SDK to coordinate protocol changes deterministically and enable efficient validator onboarding. This article examines the specific mechanisms in the akash-network/node repository that govern block height-based upgrades and state synchronization, including the registry patterns, interface implementations, and snapshot protocols that ensure network consistency.
Block Height-Based Upgrade Architecture
Akash coordinates protocol upgrades by combining the Cosmos SDK's x/upgrade module with a custom registration system that maps specific block heights to upgrade handlers and state patches.
Software Upgrade Registration
Every software upgrade resides in a dedicated directory under upgrades/software/<semver>/. Each upgrade package implements the IUpgrade interface, which requires both a StoreLoader for state migrations and an UpgradeHandler for custom logic.
Registration occurs during package initialization. In upgrades/software/v1.0.0/init.go, the upgrade constructor registers itself with the central registry:
// upgrades/software/v1.0.0/init.go
func init() {
utypes.RegisterUpgrade(v1_0_0.UpgradeName, v1_0_0.New)
}
This pattern ensures that all upgrades self-register when the application starts, eliminating the need for manual maintenance of upgrade lists in central configuration files.
Central Registry Management
The core coordination logic lives in upgrades/types/types.go, which maintains three distinct maps to handle different types of height-based operations:
upgrades– Maps upgrade names to software upgrade constructors implementingIUpgradeheightPatches– Stores non-software patches that execute at specific block heights via theIHeightPatchinterfacemigrations– Tracks module-level store migrations
These maps populate at startup through the init() functions of individual upgrade packages, creating a dynamic registry without hardcoded conditional blocks.
Execution at Target Height
When the Cosmos SDK's x/upgrade module detects a SoftwareUpgradeProposal with a Plan specifying a target block height, it automatically invokes the registered UpgradeHandler when the chain reaches that height.
The handler implementation in upgrades/software/v1.0.0/upgrade.go follows this structure:
// upgrades/software/v1.0.0/upgrade.go – UpgradeHandler skeleton
func (up *upgrade) UpgradeHandler() upgradetypes.UpgradeHandler {
return func(ctx context.Context, plan upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) {
// Custom migration logic: provider key migration, escrow prefix fixes, etc.
return fromVM, nil
}
}
The handler can perform arbitrary state modifications, including store renames, parameter updates, or data structure migrations, ensuring the application state transitions correctly at the predetermined block height.
Height-Only Patches for Critical Fixes
For scenarios requiring immediate state corrections without a full software version bump, Akash implements the IHeightPatch interface. These patches execute one-time logic at a specific block height during the BeginBlock phase.
Registration occurs via RegisterHeightPatch(height, patch) in the same upgrades/types/types.go registry. The patch structure requires a Name() method and a Begin method:
type myPatch struct{}
func (p *myPatch) Name() string { return "my-patch" }
func (p *myPatch) Begin(ctx sdk.Context, app *apptypes.AppKeepers) {
// One-off state correction logic
}
func init() { utypes.RegisterHeightPatch(1234567, &myPatch{}) }
During BeginBlock, the application checks GetHeightPatchesList() and executes the Begin method for any patch registered at the current height, allowing surgical interventions without binary upgrades.
State Synchronization Mechanism
Akash leverages the Cosmos SDK's state-sync feature to enable new validators to join the network by downloading recent application snapshots rather than processing every historical block.
Trusted Snapshot Discovery
When a node starts with state synchronization enabled, it queries a state-sync RPC endpoint operated by a trusted full-node or validator. This RPC provides two critical pieces of data:
trust-height– A recent block height that the node will treat as canonicaltrust-hash– The application hash (Merkle root) of the state at that height
These parameters establish a cryptographically verifiable checkpoint that eliminates the need to verify every preceding block.
Snapshot Download and Restoration
The Cosmos SDK requests the application state in chunks (snapshots) from the RPC peer. Each snapshot contains the complete store state at the trusted height, including all module data. Once restored, the node's state matches the trusted height exactly, allowing it to begin validating new blocks immediately.
This approach reduces synchronization time from days (for full historical replay) to minutes, significantly improving the validator onboarding experience.
CLI Integration in Akash
The integration point for state synchronization resides in cmd/akashd/main.go. The application entry point forward state-sync flags to the underlying BaseApp configuration:
// cmd/akashd/main.go – enabling state sync
app := server.NewApp(options...)
if opts.StateSyncEnable {
app.SetStateSyncConfig(opts.StateSyncConfig) // Populates trust-height / trust-hash
}
When operators include --state-sync flags during initialization, the node configures itself to fetch snapshots from the specified RPC endpoints rather than executing the standard block replay process.
Summary
-
Upgrade Registry:
upgrades/types/types.gomaintains three maps (upgrades,heightPatches,migrations) that register software upgrades viaRegisterUpgrade()and height-specific patches viaRegisterHeightPatch(). -
Software Upgrade Implementation: Each upgrade lives in
upgrades/software/<semver>/and implementsIUpgradewithStoreLoaderfor state migrations andUpgradeHandlerfor custom logic. -
Height-Based Execution: The Cosmos SDK
x/upgrademodule automatically invokes registered handlers when block heights match upgrade plans, whileBeginBlockchecksGetHeightPatchesList()to execute one-off patches. -
State Sync Bootstrap:
cmd/akashd/main.goforwards state-sync configuration to the Cosmos SDK, enabling nodes to download snapshots from trusted RPC nodes usingtrust-heightandtrust-hashparameters. -
Operational Safety: Both mechanisms preserve consensus safety—upgrades through deterministic height-based execution and state sync through cryptographic verification of trusted snapshots.
Frequently Asked Questions
What is the difference between a software upgrade and a height patch in Akash?
A software upgrade requires a binary version change and implements the full IUpgrade interface with both StoreLoader and UpgradeHandler, typically used for protocol changes and store migrations. A height patch implements only the IHeightPatch interface and executes a Begin method at a specific block height without requiring a software version bump, suitable for emergency state fixes or one-off data corrections.
How does the Cosmos SDK x/upgrade module interact with Akash's custom handlers?
The Cosmos SDK x/upgrade module monitors the blockchain for SoftwareUpgradeProposal transactions containing target heights. When the chain reaches the planned height, the SDK automatically calls the UpgradeHandler registered in Akash's upgrades/types/types.go registry. Akash's handler then executes custom migration logic defined in upgrades/software/<semver>/upgrade.go before returning control to the SDK.
What files must developers modify to implement a new block height-based upgrade?
Developers must create a new directory under upgrades/software/<semver>/ containing: an upgrade.go file implementing the IUpgrade interface with UpgradeHandler() and StoreLoader() methods, and an init.go file calling utypes.RegisterUpgrade() to add the upgrade to the central registry. If store migrations are required, they must also update the migrations map in upgrades/types/types.go.
Is state synchronization safe for validating transactions on Akash?
Yes, state synchronization is safe because the node verifies the application state against a cryptographically secure trust-hash provided by a trusted RPC node. While the node skips historical block execution, it starts from a verified state snapshot at the trust-height and validates all subsequent blocks normally, ensuring no compromise to consensus safety for future transactions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →