On this page
Source: paxeer-network/modules/store/

Overview

The store module provides utilities for Cosmos SDK module state management. It standardizes key formatting, iteration patterns, and marshaling/unmarshaling operations that other Paxeer modules use to interact with PaxDB storage.

Key Formatting

Modules store state in key-value pairs. The store module provides helpers for consistent key prefixing:

  • Prefix constants: Each module defines unique byte prefixes for its keys
  • Key builders: Functions to construct keys from module prefix + identifier
  • Collision avoidance: Ensures different modules and different state types within a module never overlap

Example pattern:

const (
    AccountPrefix = byte(0x01)
    CodePrefix    = byte(0x02)
    StoragePrefix = byte(0x03)
)

func AccountKey(address common.Address) []byte {
    return append([]byte{AccountPrefix}, address.Bytes()...)
}

Iterator Utilities

The store module provides helpers for range queries:

  • Prefix iteration: Iterate all keys sharing a prefix
  • Range bounds: Start and end keys for bounded iteration
  • Reverse iteration: Iterate keys in descending order

These utilities wrap the underlying PaxDB iterators and handle edge cases like prefix overflow and empty ranges.

Codec Helpers

The store module standardizes state marshaling:

  • Protobuf encoding: Marshal/unmarshal state structs to/from bytes
  • JSON encoding: For human-readable export/import
  • Legacy amino support: For backwards compatibility with older state formats

Modules call these helpers instead of directly invoking codec methods, ensuring consistent encoding across the codebase.

Common Patterns

Get/Set State

func (k Keeper) GetAccount(ctx sdk.Context, addr common.Address) (Account, error) {
    store := ctx.KVStore(k.storeKey)
    bz := store.Get(AccountKey(addr))
    if bz == nil {
        return Account{}, errors.New("account not found")
    }
    var acc Account
    k.cdc.MustUnmarshal(bz, &acc)
    return acc, nil
}

func (k Keeper) SetAccount(ctx sdk.Context, addr common.Address, acc Account) {
    store := ctx.KVStore(k.storeKey)
    bz := k.cdc.MustMarshal(&acc)
    store.Set(AccountKey(addr), bz)
}

Iterate All Accounts

func (k Keeper) IterateAccounts(ctx sdk.Context, cb func(addr common.Address, acc Account) bool) {
    store := ctx.KVStore(k.storeKey)
    iter := store.Iterator(PrefixRange(AccountPrefix))
    defer iter.Close()
    
    for ; iter.Valid(); iter.Next() {
        var acc Account
        k.cdc.MustUnmarshal(iter.Value(), &acc)
        addr := common.BytesToAddress(iter.Key()[1:]) // skip prefix byte
        if cb(addr, acc) {
            break
        }
    }
}

State Migration

The store module includes utilities for state migration during chain upgrades:

  • Key remapping: Move state from old keys to new keys
  • Schema changes: Transform state from old format to new format
  • Batching: Migrate large state in chunks to avoid running out of gas

Integration with PaxDB

The store module sits above PaxDB. It provides a module-friendly API while PaxDB handles the low-level storage engine details (state commitment, state store, WAL).

Modules call store helpers → store helpers call SDK KVStore → SDK KVStore calls PaxDB.

Testing Utilities

The store module provides test helpers:

  • In-memory stores: Fast, isolated storage for unit tests
  • Mock contexts: Simulate SDK context with controlled block height, time
  • State snapshots: Capture and restore state for test isolation

Next Steps

Paxeer Network · Developer documentationBack to top ↑

Ask Paxeer Docs

Answers from the documentation.

What would you like to know?

Ask a question, find a guide, or get help with your next step.

Enter to send · Shift+Enter for a new line