Skip to content
prasad-kumkar edited this page May 5, 2025 · 2 revisions

State

The jam.state module manages the blockchain state in Tessera, including state transitions, storage, and validation.

State Architecture

The Tessera state system is built on a Merkle-Patricia trie structure:

  • Merkle-Patricia Trie: Efficient key-value storage with cryptographic verification
  • State Root: A hash representing the entire state at a given block
  • State Transitions: Functions that modify state based on extrinsics
  • State Proofs: Merkle proofs that verify inclusion of specific state items

State Components

The state includes several key components as defined in the JAM protocol:

  • Alpha: Core authorizations pool tracking allowed authorizers for each core (α ∈ C⟦H⟧:OH C)
  • Beta: Recent block history including block hash, state root, accumulation MMR, and work package hashes
  • Gamma: Safrole consensus state containing ticket accumulator (γₐ), next epoch validator keys (γₖ), sealing key sequence (γₛ), and Bandersnatch root (γᵧ)
  • Delta: Service accounts state including smart contracts, with intermediate states (δ† and δ‡) for preimage integration and accumulation
  • Eta: Entropy accumulator and epochal randomness (sequence of 4 hash values)
  • Iota: Queue of validator keys to be activated in future epochs
  • Kappa: Currently active validator keys and metadata
  • Lambda: Previous epoch's validator keys and metadata
  • Rho: Tracks work-reports available but not yet accumulated (has states ρ† and ρ‡)
  • Tau: Most recent block's timeslot index
  • Phi: Authorization queue that feeds into the authorization pool
  • Chi: Privileged service indices (manager, validator designator, always-accumulate services)
  • Psi: Tracks judgments on work-reports (good/bad/unknown) and validator offenses
  • Pi: Validator activity statistics (blocks produced, tickets submitted, etc.)
  • Nu: Accumulation queue for ready work-reports
  • Xi: History of accumulated work-reports

State Transitions

State transitions follow this general pattern:

  1. Begin with previous state (parent block's state)
  2. Apply extrinsics sequentially
  3. Execute state transition functions for each extrinsic
  4. Calculate new state root
  5. Include new state root in block header

Optimizations

The state module includes several optimizations for performance:

  • Partial State Updates: Only rehash branches affected by changes
  • Caching: In-memory caching of frequently accessed state
  • Batch Processing: Efficiently process multiple state changes
  • Pruning: Remove historical state data that's no longer needed

Usage

from jam.state import State
from jam.storage import Storage

# Initialize state with storage backend
storage = Storage(db_path="./data/db")
state = State(storage)

# Access state
account = state.get(b"account:alice")
print(f"Balance: {account.balance}")

# Update state
state.begin_transaction()
state.set(b"account:alice", new_account_data)
state.commit_transaction()

# Verify state
state_root = state.root_hash()
proof = state.generate_proof(b"account:alice")

State Storage Design

The state storage system uses a specialized design for efficient updates and verification:

  • In-Memory Trie: Complete trie structure maintained in RAM
  • Partial Persistence: Only changed nodes are persisted
  • Path-Based Updates: Efficient updates that only affect the path from leaf to root

For detailed information about the state storage design, see ADR-0002: State Storage Design.

Merklization

The state system supports efficient merklization of arbitrary data:

from jam.state import merkelize

# Create a merkle tree from dictionary data
data = {
    b"key1": b"value1",
    b"key2": b"value2",
    b"key3": b"value3"
}

# Merkelize the data
root_hash, db_nodes = merkelize(data)

# Verify a value with a proof
is_valid = verify_proof(root_hash, b"key1", b"value1", proof)

Clone this wiki locally