# How the Akash Network Audit Module Verifies Provider Attributes and Host URIs

> Discover how the Akash Network audit module safeguards provider attributes and host URIs via client-side validation, preventing invalid data from reaching chain storage.

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

---

**The Akash Network audit module verifies provider attributes and host URIs through client-side validation at entry points, ensuring malformed URIs never reach chain storage by validating them in `MsgSignProviderAttributes.ValidateBasic()` and genesis initialization.**

The `akash-network/node` repository implements a decentralized compute marketplace where auditors attest to provider capabilities through cryptographically signed attribute sets. Rather than maintaining an independent copy of a provider’s host URI, the audit module stores these attested attributes and relies on rigorous validation at creation time—both during chain initialization and transaction processing—to guarantee that every host URI conforms to proper URL syntax before it is persisted.

## Genesis-Time Validation in [`x/audit/genesis.go`](https://github.com/akash-network/node/blob/main/x/audit/genesis.go)

When the chain boots from genesis, the audit module validates every pre-existing provider record before accepting the state. In `x/audit/genesis.go:27-28`, the `ValidateGenesis` function iterates over the `Providers` slice and invokes `record.Attributes.Validate()` on each entry.

If any attribute—including the `host_uri` field—fails validation, the chain aborts initialization with `ErrInvalidAttributes`. This prevents malformed provider metadata from entering the blockchain history at the earliest possible stage.

```go
// x/audit/genesis.go
func ValidateGenesis(data *types.GenesisState) error {
    for _, record := range data.Providers {
        // address format checks …
        if err := record.Attributes.Validate(); err != nil {
            // fails on malformed host_uri, missing keys, etc.
            return errorsmod.Wrap(err, "audited attributes: invalid attributes")
        }
    }
    return nil
}

```

## Transaction Validation via `MsgSignProviderAttributes`

Before a transaction enters the mempool, the `ValidateBasic()` method—generated from `proto/akash/audit/v1/messages.proto` and located in the generated Go file—performs syntactic checks. This method validates that both the `Auditor` and `Owner` fields are valid bech32 addresses, then delegates attribute validation to `msg.Attributes.Validate()`.

The attributes validator (implemented in the shared `pkg/akt.dev/go/node/types/attributes/v1` package) parses the `host_uri` string using Go’s `net/url` parser. It enforces that the URI uses a supported scheme—such as `http`, `https`, `akash`, or `grpc`—and contains a non-empty host component.

```go
// generated from proto/akash/audit/v1/messages.proto
func (msg *MsgSignProviderAttributes) ValidateBasic() error {
    if _, err := sdk.AccAddressFromBech32(msg.Auditor); err != nil {
        return err
    }
    if _, err := sdk.AccAddressFromBech32(msg.Owner); err != nil {
        return err
    }
    // The Attributes validator checks each key/value,
    // and for the key "host_uri" it parses the URL.
    return msg.Attributes.Validate()
}

```

## Keeper Storage Trusts Pre-Validated Data

Once `ValidateBasic()` succeeds, the message server handler in `x/audit/handler/msg_server.go:44-46` invokes `keeper.CreateOrUpdateProviderAttributes`. The keeper implementation in `x/audit/keeper/keeper.go:94-130` **does not re-validate** the attributes; it trusts the previous validation steps and simply merges the new key-value pairs with any existing set for the `ProviderID` (composed of owner and auditor addresses).

```go
// x/audit/keeper/keeper.go – CreateOrUpdateProviderAttributes
func (k Keeper) CreateOrUpdateProviderAttributes(
    ctx sdk.Context, id types.ProviderID, attr attrv1.Attributes,
) error {
    // ... load existing, merge maps, sort, then store.
    store.Set(ProviderKey(id), k.cdc.MustMarshal(&attrRec))
    // Event emitted – no extra validation needed.
    return nil
}

```

## Runtime Query Guarantees

When clients query the audit store through methods like `AllProvidersAttributes`, `ProviderAttributes`, or `AuditorAttributes` in [`x/audit/keeper/grpc_query.go`](https://github.com/akash-network/node/blob/main/x/audit/keeper/grpc_query.go), the keeper reads raw bytes and unmarshals them into `types.AuditedProvider`. Because validation occurred strictly at entry time, the returned attribute list—including any host URI—is guaranteed to be syntactically correct without requiring runtime checks.

## Provider Module Host URI Validation

The canonical `HostURI` field—used by the network to reach the provider—is owned by the **provider** module, not the audit module. Before the audit module ever sees a host URI, the provider module validates it through its own `ValidateBasic()` implementation in [`x/provider/types/message.pb.go`](https://github.com/akash-network/node/blob/main/x/provider/types/message.pb.go).

In `x/provider/handler/server.go:36-56`, both `MsgCreateProvider` and `MsgUpdateProvider` handlers call `msg.ValidateBasic()`, which invokes the same attribute validator on the `HostURI` field. The audit module subsequently stores only the signed attestation of this pre-validated data.

```go
// x/provider/handler/server.go
func (h server) CreateProvider(goCtx context.Context, msg *types.MsgCreateProvider) (*types.MsgCreateProviderResponse, error) {
    if err := msg.ValidateBasic(); err != nil { // checks HostURI format
        return nil, err
    }
    // provider is stored in the provider keeper …
}

```

## Error Types and Validation Failures

The audit module surfaces specific errors during the verification process:

- **`sdkerrors.ErrInvalidAddress`** – Returned when the owner or auditor bech32 addresses are malformed.
- **`types.ErrAttributeNotFound`** – Returned when attempting to delete an attribute that does not exist in the store.
- **`types.ErrInvalidAttributes`** – Wrapped from `Attributes.Validate()` when attributes contain malformed key-value pairs, missing required keys like `host_uri`, or illegal URI schemes.

## Summary

- **Genesis validation** in [`x/audit/genesis.go`](https://github.com/akash-network/node/blob/main/x/audit/genesis.go) calls `Attributes.Validate()` on every provider record during chain startup, preventing invalid host URIs from entering the genesis state.
- **Transaction validation** in `MsgSignProviderAttributes.ValidateBasic()` validates bech32 addresses and delegates to the attributes validator, which parses URIs with `net/url` and enforces supported schemes.
- **Keeper architecture** trusts pre-validated data and performs no additional validation during storage operations in `CreateOrUpdateProviderAttributes`.
- **Query safety** relies on entry-time validation to guarantee that all returned host URIs are syntactically correct without runtime overhead.
- **Provider module integration** validates the canonical `HostURI` before the audit module processes any related attributes, creating a defense-in-depth validation strategy.

## Frequently Asked Questions

### Does the audit module validate host URIs every time they are queried?

No. The audit module validates host URIs strictly at entry time—during genesis initialization and when processing `MsgSignProviderAttributes` transactions. The keeper stores pre-validated data, so runtime queries in [`x/audit/keeper/grpc_query.go`](https://github.com/akash-network/node/blob/main/x/audit/keeper/grpc_query.go) simply return the stored bytes without additional validation overhead.

### What URL schemes are supported for provider host URIs in Akash?

The attributes validator accepts schemes including `http`, `https`, `akash`, and `grpc`. The validation logic uses Go’s standard `net/url` parser to ensure the URI contains a valid scheme and a non-empty host component before the transaction is accepted.

### What happens if a provider submits an invalid host URI during genesis?

The chain aborts initialization with `ErrInvalidAttributes`. In [`x/audit/genesis.go`](https://github.com/akash-network/node/blob/main/x/audit/genesis.go), the `ValidateGenesis` function wraps the underlying validation error and returns it, preventing the node from starting with malformed provider metadata in its genesis state.

### How does the audit module differ from the provider module regarding host URI storage?

The **provider** module owns the canonical `HostURI` field used for network reachability and validates it during `MsgCreateProvider` and `MsgUpdateProvider` processing. The **audit** module stores **signed attestations** of provider attributes (including the host URI) tied to an auditor’s address, validating these attestations during the signing transaction but never storing an independent copy of the raw host URI.