Skip to main content
state_server is a REST API for managing persistent Merkle tries used by HDP injected state workflows. It is different from HDP Server API:
  • State Server: injected-state trie service (/create_trie, /read, /write, /get_state_proofs).
  • HDP Server API: orchestrated HDP task execution service (/tasks, task status, task outputs).
Repository:

What it provides

  • Create and manage multiple tries by label
  • Read and write key/value pairs
  • Return trie roots for specific states
  • Generate inclusion/non-inclusion and update proofs
  • Persist trie data in SQLite-backed storage

Run the server

cargo run --release --bin state_server -- --host 0.0.0.0 --port 3000 --db_root_path db
Common options:
  • --host (default 0.0.0.0)
  • --port (default 3000)
  • --db_root_path (default db)
Set HDP to use it with:
INJECTED_STATE_BASE_URL=http://localhost:3000

Core endpoints

  • POST /create_trie
  • GET /read
  • POST /write
  • POST /get_state_proofs
  • GET /get_trie_root_node_idx

Endpoint behavior

  • POST /create_trie: create a trie label with initial keys/values
  • GET /read: read a key for a specific trie root
  • POST /write: upsert key/value and return the new trie root
  • POST /get_state_proofs: generate proof payloads for read/write actions
  • GET /get_trie_root_node_idx: resolve the internal node index for a root

Quick examples

Create trie:
curl -X POST http://localhost:3000/create_trie \
  -H "Content-Type: application/json" \
  -d '{
    "trie_label": "0x123",
    "keys": ["0x1", "0x2"],
    "values": ["0x42", "0x84"]
  }'
Read key:
curl "http://localhost:3000/read?trie_label=0x123&trie_root=0x0&key=0x1"
Write key:
curl -X POST http://localhost:3000/write \
  -H "Content-Type: application/json" \
  -d '{
    "trie_label": "0x123",
    "trie_root": "0x0",
    "key": "0x4",
    "value": "0x168"
  }'
Get state proofs:
curl -X POST http://localhost:3000/get_state_proofs \
  -H "Content-Type: application/json" \
  -d '{
    "actions": [
      {
        "Read": {
          "trie_label": "0x123",
          "trie_root": "0x0",
          "key": "0x1"
        }
      }
    ]
  }'
All trie labels, keys, values, and roots are felt-compatible values (hex or decimal strings).

HDP integration

In HDP flows, injected-state handlers use the state server during dry/fetch phases, and the resulting proofs are consumed during sound-run.

End-to-end usage with HDP

This is the practical flow most teams use:
  1. Start state_server
  2. Set INJECTED_STATE_BASE_URL
  3. Run dry-run with --injected_state
  4. Run fetch-proofs (state proofs are pulled from state server)
  5. Run sound-run with the same --injected_state file
Example:
# 1) Start state server
cargo run --release --bin state_server -- --host 0.0.0.0 --port 3000 --db_root_path db

# 2) Point HDP to state server
export INJECTED_STATE_BASE_URL=http://localhost:3000

# 3) Run HDP pipeline with injected state
hdp dry-run -m target/dev/example_injected_state_module.compiled_contract_class.json \
  --injected_state examples/injected_state/injected_state.json \
  --print_output

hdp fetch-proofs

hdp sound-run -m target/dev/example_injected_state_module.compiled_contract_class.json \
  --injected_state examples/injected_state/injected_state.json \
  --print_output
During this flow:
  • dry-run records injected-state read/write actions,
  • fetch-proofs converts those actions into state proof payloads,
  • sound-run verifies those proofs before your Cairo logic consumes the values.

Cairo-side usage in modules

In your module, use hdp.injected_state helpers:
let root = hdp.injected_state.read_injected_state_trie_root('my_trie');
let maybe_value = hdp.injected_state.read_key('my_trie', 'my_key');
let new_root = hdp.injected_state.write_key('my_trie', 'my_key', 42);

Working example to copy from

See: