Skip to content
LogoLogo

Generated — do not edit. Source of truth: crates/cosmwasm/book/src/using/vm/proof-vm.md. Edit there, then rebuild docs.

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:
// 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 / APIKindFeatureNotes
secp256k1_verifySignatureECDSA over secp256k1 (Cosmos default)
secp256k1_recover_pubkeySignaturePubkey recovery from compact signature
secp256r1_verifySignatureECDSA over P-256 (CosmWasm 2.1+)
secp256r1_recover_pubkeySignatureP-256 recovery
ed25519_verifySignatureEdDSA over ed25519
ed25519_batch_verifySignatureBatch Ed25519 verify
bls12_381_aggregate_g1Pairing curveAggregate G1 points (48-byte elements)
bls12_381_aggregate_g2Pairing curveAggregate G2 points (96-byte elements)
bls12_381_pairing_equalityPairing curveMulti-pairing equality check
bls12_381_hash_to_g1Hash-to-curveMap message → G1 (HashFunction + DST)
bls12_381_hash_to_g2Hash-to-curveMap message → G2
proof_instance_verify NEWZK proofzkHalo2 / Groth16 verify via zkid → circuit key
blake2b_256 NEWHashhash-blakeBLAKE2b digest truncated/output 32 bytes
blake3_256 NEWHashhash-blakeBLAKE3 256-bit digest
bn254_add NEWPairing curvebn254EIP-196 ECADD on alt_bn128 G1
bn254_scalar_mul NEWPairing curvebn254EIP-196 ECMUL on alt_bn128 G1
bn254_pairing_equality NEWPairing curvebn254EIP-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

FunctionOutputHost importStatus
SHA-256 (BLS hash-to-curve mode)via HashFunctioninside bls12_381_hash_to_g*Stock CosmWasm
blake2b_256 NEW32 bytesenv.blake2b_256feature hash-blake
blake3_256 NEW32 bytesenv.blake3_256feature hash-blake
blake2b_51264 bytesLibrary 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 / groupAPIsTypical use
secp256k1secp256k1_verify, secp256k1_recover_pubkeyTendermint / Cosmos account signatures
secp256r1 (P-256)secp256r1_verify, secp256r1_recover_pubkeyWebAuthn / passkey-style credentials
ed25519ed25519_verify, ed25519_batch_verifyConsensus / 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_idCurveCircuit familyProving system
0 NEWPasta (Vesta)Generic PlonkishHalo2
1 NEWPasta (Vesta)Vote delegation (ZKP #1)Halo2
2 NEWPasta (Vesta)Vote commitment (ZKP #2)Halo2
3 NEWPasta (Vesta)Share reveal (ZKP #3)Halo2
4 NEWBN254 (alt_bn128)Generic Groth16 (snarkjs / circom)Groth16 (feature bn254)
5 NEWM31Lean SSLE / fold / valsetStwo Circle STARK
6 NEWBN256zkjwt.passkeyHalo2 KZG / SHPLONK (feature halo2-kzg)
7 NEWFlock (hash / GF(2))Hash-chain / archive attestationFlock Ligerito (verify_ligerito)

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. Terp product mapping: Curve IDs And Terp Use Cases.

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