# How Akash Implements Block Height-Based Upgrades and State Synchronization

> Discover how Akash Network uses block height-based upgrades via a registry and snapshot protocol for efficient state synchronization. Learn about its decentralized upgrade process.

- Repository: [Akash Network/node](https://github.com/akash-network/node)
- Tags: internals
- Published: 2026-02-24

---

**Akash implements block height-based upgrades through a centralized registry system in [`upgrades/types/types.go`](https://github.com/akash-network/node/blob/main/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`](https://github.com/akash-network/node/blob/main/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`](https://github.com/akash-network/node/blob/main/upgrades/software/v1.0.0/init.go), the upgrade constructor registers itself with the central registry:

```go
// 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`](https://github.com/akash-network/node/blob/main/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 implementing `IUpgrade`
- **`heightPatches`** – Stores non-software patches that execute at specific block heights via the `IHeightPatch` interface
- **`migrations`** – 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`](https://github.com/akash-network/node/blob/main/upgrades/software/v1.0.0/upgrade.go) follows this structure:

```go
// 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`](https://github.com/akash-network/node/blob/main/upgrades/types/types.go) registry. The patch structure requires a `Name()` method and a `Begin` method:

```go
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 canonical
- **`trust-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`](https://github.com/akash-network/node/blob/main/cmd/akashd/main.go). The application entry point forward state-sync flags to the underlying `BaseApp` configuration:

```go
// 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.go`](https://github.com/akash-network/node/blob/main/upgrades/types/types.go) maintains three maps (`upgrades`, `heightPatches`, `migrations`) that register software upgrades via `RegisterUpgrade()` and height-specific patches via `RegisterHeightPatch()`.

- **Software Upgrade Implementation**: Each upgrade lives in `upgrades/software/<semver>/` and implements `IUpgrade` with `StoreLoader` for state migrations and `UpgradeHandler` for custom logic.

- **Height-Based Execution**: The Cosmos SDK `x/upgrade` module automatically invokes registered handlers when block heights match upgrade plans, while `BeginBlock` checks `GetHeightPatchesList()` to execute one-off patches.

- **State Sync Bootstrap**: [`cmd/akashd/main.go`](https://github.com/akash-network/node/blob/main/cmd/akashd/main.go) forwards state-sync configuration to the Cosmos SDK, enabling nodes to download snapshots from trusted RPC nodes using `trust-height` and `trust-hash` parameters.

- **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`](https://github.com/akash-network/node/blob/main/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`](https://github.com/akash-network/node/blob/main/upgrade.go) file implementing the `IUpgrade` interface with `UpgradeHandler()` and `StoreLoader()` methods, and an [`init.go`](https://github.com/akash-network/node/blob/main/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`](https://github.com/akash-network/node/blob/main/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.