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
| Concern | Stock CosmWasm | ZK-CosmWasm |
|---|---|---|
| Crypto hosts | secp256k1, ed25519, BLS12-381, … | Same, plus Halo2/PLONK-style proof verification |
| Circuit selection | Smart-Contract Specific | Application-assigned zkid → circuit metadata / key |
| Storage of VKs | Smart-Contract Specific | Content-addressed blob (params + constraint system + VK + footer) |
| Contract API | api.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
- Upload / register a circuit verifying key (often with contract code via
store_code_with_circuit, or as a standalone circuit viastore_circuit). - Map an application
zkidto the circuit’s content-addressed key (consensus/app state). - 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) |
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) |
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) |
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:
| Crate | Role |
|---|---|
packages/std | Contract-facing API and Wasm imports |
packages/vm | Host import, gas, cache integration |
packages/zk | Footer, serialization, AnyVerifyingKey |
packages/zk-vote-bridge | Example: vote-sdk circuits → CosmWasm footer format |
packages/crypto | Shared 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
zkoncosmwasm-std/ contract crates that callproof_instance_verify. - Host environments must wire circuit queries (
CircuitInfo/Circuit) and the VM circuit cache loader.
See Gas and capabilities for negotiation and metering.