Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Architecture

This chapter describes how multi-circuit proof verification works in the CosmWasm VM for integrators and contract authors.

Engineering source of truth: ZK_PROOF_VERIFICATION_ARCHITECTURE.md, ZK_COSMWASM_ZKVM_SPEC.md (repo root).

Two-level identity

LayerIdentifierWhat it stores
App / consensuszkid (u64 / u32 at the Wasm boundary)Logical circuit id → content key / checksum mapping
VM cacheCircuit key (72 bytes) or component keys (36 bytes)Actual serialized params, constraint system, VK

Think of zkid as a virtual address and the circuit key as a physical page: contracts only ever pass zkid; operators and keepers manage content-addressed blobs.

Historically the mapping was described as zk_circuits:{zkid} → checksum. The host path used today resolves WasmQuery::CircuitInfo { zk_id } for metadata (including the 72-byte circuit_key), then loads bytes from the host circuit cache (Path A). On cache miss it falls back to WasmQuery::Circuit for the full blob (cold path).

Host import

do_proof_instance_verify(zkid, proof_ptr, proof_len, instances_ptr, instances_len) → u32

Implemented in packages/vm/src/imports.rs:

  1. Charge host-call gas and read proof / instance regions from Wasm memory
    • Proof max size: 2 MiB
    • Instances max size: 64 KiB
  2. Charge halo2_proof_instance_verify gas (linear cost model).
  3. Query CircuitInfo for zkidcircuit_key (72 bytes).
  4. Load verifying key:
    • Prefer host cache loader (no full circuit over the querier)
    • Else cold path: Circuit query → deserialize footer + body → AnyVerifyingKey
  5. Decode instances with footer.curve_id (never with zkid as a curve hint).
  6. Verify; return codes:
    • 0 — cryptographic verification succeeded
    • 1 — proof does not verify (not a host crash)
    • Err — missing registry entry, parse/format errors, gas, system query failure

Contract sketch:

#![allow(unused)]
fn main() {
match api.proof_instance_verify(zkid, &proof, &instances) {
    Ok(0) => { /* accept */ }
    Ok(1) => { /* reject invalid proof */ }
    Ok(_) => { /* unexpected */ }
    Err(e) => { /* registry / encoding / gas */ }
}
}

Upload path

API (VM cache)Purpose
store_code_with_circuit(code_bundle, checked, persist)Validate Wasm + VK; store both; pin VK by default; returns checksums
store_circuit(vk_bytes, persist)Store / pin a circuit blob alone

App layer responsibilities:

  • Persist zkid → circuit key / metadata in consensus state
  • Ensure mappings exist before contracts verify against that zkid
  • Optionally re-pin hot circuits after node restart (disk survives; pinned memory does not)

Virtual-memory analogy

OS conceptZK-CosmWasm
Virtual addresszkid
Page tableApp mapping / CircuitInfo
Physical frameDeserialized VK in pinned memory
Page faultCache miss → disk or Circuit query
Wired pagesPinned circuits
Page cacheFile-system .bin under zk_* dirs

Roadmap note (zkVM)

ZK_COSMWASM_ZKVM_SPEC.md describes an evolution from programmable circuit verification (what ships today: upload VKs, verify proofs) toward a Turing-complete WASM execution prover (trace capture, late-binding commit/batch/claim, nested sub-commitments). That is design-forward material for protocol builders. Day-to-day contract integration only needs the multi-circuit verify path above.

Error patterns operators see

SymptomLikely cause
“circuit not found” / CircuitInfo errorzkid never registered or wrong chain state
Deserialization / footer errorsCorrupt blob, wrong format version, truncated file
Ok(1)Valid host path, invalid proof or wrong public inputs
Instance length errorsInstances not multiple of 32-byte field elements

Implementation map

AreaPath
Host importpackages/vm/src/imports.rs
Gas / envpackages/vm/src/environment.rs
Cachepackages/vm/src/cache.rs, packages/vm/src/zk.rs
Serializationpackages/zk/