Akash Provider Module: Role and Market Interaction Explained

The provider module in the Akash Network acts as the authoritative registry for compute providers, storing their addresses, host URIs, and attributes, while the market module consumes this data via the ProviderKeeper interface to validate bids, create leases, and enforce provider-centric rules.

The akash-network/node repository implements the provider module as a Cosmos SDK module responsible for on-chain provider identity management. This module maintains the canonical state of all compute providers in the network and exposes a read-only interface that the market module relies on to ensure every bid and lease references a valid, registered entity.

Provider Module Core Responsibilities

The provider module serves as the single source of truth for provider metadata within the Akash ecosystem. It handles four critical functions that enable the decentralized cloud marketplace to operate securely.

Provider Registry and State Management

At the heart of the module lies the provider keeper, implemented in x/provider/keeper/keeper.go, which persists provider objects to the blockchain state. Each provider is stored under a unique key ProviderKey(owner) and contains the owner address, host URI, and capability attributes. The keeper emits EventProviderCreated and EventProviderUpdated events during state transitions, allowing external observers to track provider lifecycle changes.

Message Handling for Provider Lifecycle

The module processes three primary transaction types through its message handler defined in x/provider/handler/handler.go:

  • MsgCreateProvider: Registers a new provider with initial attributes
  • MsgUpdateProvider: Modifies existing provider metadata such as the host URI or capability attributes
  • MsgDeleteProvider: Removes a provider from the active registry

The NewHandler function routes these messages to MsgServerImpl, which validates and executes state changes through the keeper.

Query Services and Module Wiring

In x/provider/module.go, the RegisterServices function exposes both the message server and a gRPC querier, enabling other modules and external clients to fetch provider data. The module also implements DefaultGenesis, InitGenesis, and WeightedOperations to support chain initialization and simulation testing.

Market Module Integration and Provider Validation

The market module does not maintain its own provider state; instead, it depends on the provider module through a well-defined interface. This dependency injection pattern ensures loose coupling while maintaining data consistency.

ProviderKeeper Interface Contract

Defined in x/market/handler/keepers.go, the ProviderKeeper interface specifies the minimal methods required by the market module:

type ProviderKeeper interface {
    Get(sdk.Context, sdk.AccAddress) (ptypes.Provider, bool)
    WithProviders(sdk.Context, func(ptypes.Provider) bool)
}

The market module receives a concrete implementation of this interface during initialization. In x/market/module.go, the NewAppModule constructor accepts a handler.ProviderKeeper parameter and stores it within the market keepers struct, establishing the wiring between the two modules.

Bid and Lease Validation

When creating a bid, the market handler in x/market/handler/server.go performs strict provider validation. The handler extracts msg.ID.Provider from the incoming MsgCreateBid transaction and invokes ms.keepers.Provider.Get to verify the address exists. If the lookup fails, the transaction aborts with v1.ErrUnknownProvider, preventing bids from referencing non-existent providers.

During lease creation and withdrawal operations, the market handler additionally queries audited provider attributes via ms.keepers.Audit.GetProviderAttributes. This ensures that only providers meeting specific audit criteria can participate in active leases.

Market-Wide Provider Iteration

For housekeeping operations such as cleaning stale bids or calculating global statistics, the market module uses WithProviders to iterate over the entire provider set without loading them all into memory simultaneously. This efficient iteration pattern is defined in the keeper interface and implemented in the provider module's state layer.

Practical Implementation: Creating Providers and Bids

The following example demonstrates the end-to-end interaction between the provider and market modules, showing how a provider registration enables subsequent market operations.

// Step 1: Register a provider via the provider module
prov := ptypes.Provider{
    Owner:   "akash1xyz...",              // Bech32 provider address
    HostUri: "https://provider.example.com",
    Attributes: []atypes.Attribute{
        {Key: "region", Value: "us-east"},
        {Key: "tier", Value: "compute"},
    },
}

// Create through the provider keeper (IKeeper from x/provider/keeper)
err := providerKeeper.Create(ctx, prov)
if err != nil {
    panic(err)
}

// Step 2: Create a market bid referencing the registered provider
bid := v1.MsgCreateBid{
    ID: v1.BidID{
        Provider: prov.Owner,              // References the provider above
        // Additional bid identifiers...
    },
    Price: sdk.NewCoin("uakt", sdk.NewInt(1000)),
    // Additional bid parameters...
}

// Initialize market message server with injected keepers
msgSrv := marketHandler.NewServer(keepers) // keepers.Provider implements ProviderKeeper
res, err := msgSrv.CreateBid(ctx, &bid)
if err != nil {
    // Returns v1.ErrUnknownProvider if prov.Owner is not found in provider state
    // (see x/market/handler/server.go validation logic)
}

In this flow, the provider keeper manages the creation and persistence of provider data, while the market handler consumes this data through the ProviderKeeper interface to validate bid integrity.

Summary

  • The provider module maintains the canonical registry of all compute providers, storing addresses, host URIs, and attributes in x/provider/keeper/keeper.go.
  • It exposes CRUD operations through MsgCreateProvider, MsgUpdateProvider, and MsgDeleteProvider handlers in x/provider/handler/handler.go.
  • The market module consumes provider data via the ProviderKeeper interface defined in x/market/handler/keepers.go, enabling loose coupling between the two systems.
  • Bid validation occurs in x/market/handler/server.go, where the market handler verifies provider existence before accepting bids, returning ErrUnknownProvider for invalid references.
  • Lease operations leverage provider attributes fetched through the keeper interface to enforce audit requirements and provider-specific policies.

Frequently Asked Questions

How does the market module access provider data without direct state access?

The market module uses dependency injection to receive a ProviderKeeper interface implementation during app initialization. This interface, defined in x/market/handler/keepers.go, exposes only Get and WithProviders methods, allowing the market module to query provider state while the provider module retains full control over the underlying storage implementation.

What happens if a bid references a provider that does not exist?

The market handler in x/market/handler/server.go validates every MsgCreateBid by calling ms.keepers.Provider.Get with the provider address from the bid ID. If the provider is not found in the state, the transaction fails immediately with v1.ErrUnknownProvider, ensuring the market only processes bids from registered entities.

Can provider attributes be updated after registration?

Yes. The provider module supports attribute modification through MsgUpdateProvider, handled in x/provider/handler/handler.go. When executed, the keeper updates the existing provider object under ProviderKey(owner) and emits an EventProviderUpdated event, making the new attributes immediately available to the market module for subsequent bid and lease evaluations.

Where is the boundary between provider and market module responsibilities?

The provider module owns all state mutations and persistence logic for provider entities, including the Create, Update, and Delete keeper methods. The market module acts as a consumer, using the read-only ProviderKeeper interface to validate references and fetch attributes during bid creation and lease management, but never directly modifying provider state.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →