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

Proof VM

ZK-CosmWasm extends CosmWasm so contracts can verify zero-knowledge proofs on-chain through a host import, with verifying keys (VKs) stored and cached like Wasm modules.

What you get

ConcernStock CosmWasmZK-CosmWasm
Crypto hostssecp256k1, ed25519, BLS12-381, …Same, plus Halo2/PLONK-style proof verification
Circuit selectionSmart-Contract SpecificApplication-assigned zkid → circuit metadata / key
Storage of VKsSmart-Contract SpecificContent-addressed blob (params + constraint system + VK + footer)
Contract APIapi.secp256k1_verify, …api.proof_instance_verify(zkid, proof, instances) (feature zk)

Contracts do not re-implement proving systems in Wasm. They pass proof bytes and public inputs; the host resolves the circuit, loads the verifying key, and returns success/failure.

Mental model

  1. Upload / register a circuit verifying key (often with contract code via store_code_with_circuit, or as a standalone circuit via store_circuit).
  2. Map an application zkid to the circuit’s content-addressed key (consensus/app state).
  3. Verify from a contract:
#![allow(unused)]
fn main() {
// feature = "zk" on cosmwasm-std
let code = api.proof_instance_verify(zkid, &proof_bytes, &instance_bytes)?;
// 0 = valid proof, 1 = invalid proof
// Err = missing circuit, bad encoding, gas, or host error
}

Public instances are fixed-size field elements (length must be a multiple of 32 bytes per instance scalar encoding). Curve routing uses the circuit footer’s curve_id, not the numeric zkid.

Host crypto surface

Contract Wasm imports under env (wired in packages/vm). Highlighted rows are entrypoints added in this fork (not stock CosmWasm). Feature flags must be enabled on the host build for those imports to exist.

Import / API Kind Feature Notes
secp256k1_verify Signature ECDSA over secp256k1 (Cosmos default)
secp256k1_recover_pubkey Signature Pubkey recovery from compact signature
secp256r1_verify Signature ECDSA over P-256 (CosmWasm 2.1+)
secp256r1_recover_pubkey Signature P-256 recovery
ed25519_verify Signature EdDSA over ed25519
ed25519_batch_verify Signature Batch Ed25519 verify
bls12_381_aggregate_g1 Pairing curve Aggregate G1 points (48-byte elements)
bls12_381_aggregate_g2 Pairing curve Aggregate G2 points (96-byte elements)
bls12_381_pairing_equality Pairing curve Multi-pairing equality check
bls12_381_hash_to_g1 Hash-to-curve Map message → G1 (HashFunction + DST)
bls12_381_hash_to_g2 Hash-to-curve Map message → G2
proof_instance_verify NEW ZK proof zk Halo2 / Groth16 verify via zkid → circuit key
blake2b_256 NEW Hash hash-blake BLAKE2b digest truncated/output 32 bytes
blake3_256 NEW Hash hash-blake BLAKE3 256-bit digest
bn254_add NEW Pairing curve bn254 EIP-196 ECADD on alt_bn128 G1
bn254_scalar_mul NEW Pairing curve bn254 EIP-196 ECMUL on alt_bn128 G1
bn254_pairing_equality NEW Pairing curve bn254 EIP-197 pairing check (also used by Groth16 path)
Stock CosmWasm rows are always present on modern hosts. Rows marked NEW require the listed feature on the linked wasmvm / cosmwasm-vm build. Contract crates call api.proof_instance_verify via cosmwasm-std feature zk; hash and BN254 may be used as Wasm imports depending on std bindings.

Hash functions

Function Output Host import Status
SHA-256 (BLS hash-to-curve mode) via HashFunction inside bls12_381_hash_to_g* Stock CosmWasm
blake2b_256 NEW 32 bytes env.blake2b_256 feature hash-blake
blake3_256 NEW 32 bytes env.blake3_256 feature hash-blake
blake2b_512 64 bytes Library helper in cosmwasm-crypto only (not a host import)
Poseidon / RedJubjub helpers may exist as library stubs; they are not listed until a stable host import is wired.

Curves (signature & pairing hosts)

Existing CosmWasm curve families used by the stock signature / BLS APIs:

Curve / group APIs Typical use
secp256k1 secp256k1_verify, secp256k1_recover_pubkey Tendermint / Cosmos account signatures
secp256r1 (P-256) secp256r1_verify, secp256r1_recover_pubkey WebAuthn / passkey-style credentials
ed25519 ed25519_verify, ed25519_batch_verify Consensus / validator-style EdDSA; light-client batches
BLS12-381 (G1 / G2) bls12_381_* Aggregate signatures, pairings, hash-to-curve

Curves for proof verification (curve_id)

Footer field curve_id routes proof_instance_verify (independent of app zkid):

curve_id Curve Circuit family Proving system
0 NEW Pasta (Vesta) Generic Plonkish Halo2
1 NEW Pasta (Vesta) Vote delegation (ZKP #1) Halo2
2 NEW Pasta (Vesta) Vote commitment (ZKP #2) Halo2
3 NEW Pasta (Vesta) Share reveal (ZKP #3) Halo2
4 NEW BN254 (alt_bn128) Generic Groth16 Groth16 (feature bn254)
Defined as CurveType in packages/zk. Host BN254 precompiles (bn254_*) share the same curve family as id 4 but are separate entrypoints from proof verification.

Stack layers

Contract (cosmwasm-std, feature "zk")
    → host import proof_instance_verify
        → resolve zkid → circuit_key (WasmQuery::CircuitInfo)
        → load VK (host cache / cold path Circuit query)
        → AnyVerifyingKey::verify(proof, instances)

Relevant crates in this repository:

CrateRole
packages/stdContract-facing API and Wasm imports
packages/vmHost import, gas, cache integration
packages/zkFooter, serialization, AnyVerifyingKey
packages/zk-vote-bridgeExample: vote-sdk circuits → CosmWasm footer format
packages/cryptoShared crypto primitives used by the VM

Go hosts typically consume this via a wasmvm build linked against the fork (e.g. monorepo crates/zk-wasmvm).

Feature flags

  • Enable zk on cosmwasm-std / contract crates that call proof_instance_verify.
  • Host environments must wire circuit queries (CircuitInfo / Circuit) and the VM circuit cache loader.

See Gas and capabilities for negotiation and metering.

Next Chapters