Gm!gm!
I’ve been building groth16-ckb, a general-purpose Groth16 zkSNARK verifier that runs as a CKB-VM type script. As of today it’s verified its first end-to-end proof on testnet, and I wanted to share where it stands.
This is pre-audit - please do not deploy to mainnet.
What it is
- Curve: BN254
- Proof system: Groth16
- Backend: arkworks (ark-groth16, ark-bn254) 0.5, no patches
- Target:
riscv64imac-unknown-none-elf,no_std,panic = "abort" - Wire format: VK as a
cell_dep; proof + public inputs inWitnessArgs.input_type; all Molecule-encoded - Toolchain: stable Rust, reproducible build (pinned
rust-toolchain.toml,--locked, source-path remapping)
Compatible with both arkworks-native proofs and circom Groth16 proofs (via arkworks-format export).
What works today
End-to-end verification on CKB Pudge testnet:
- Verifier code cell: 0x8e849c96509c1805d8bf1e906454151ea9f6c3d118d3e616ebb25c50f7d3a75e
- VK cell: 0x8214d4ce2c0a575a4d9c2ff7fa5b7aaf4037ef61c0bbbcaf9df1506a12e9bf1c
- Trigger created: 0x8c135e6e745cc5ba4d325e8602164d60dc71052ed334de85d3a71461784f44ba
- Trigger spent (proof verified on chain): 0xc658f9e8a846747a3aad373b2145ac49d920aba00c88885219d6c25f3dc53c96
Cycle costs (Molecule-decode VK + proof, then pairing check) for N public inputs, measured on riscv64imac CKB-VM:
| N | cycles | % of 250M bound |
|---|---|---|
| 1 | 102,419,769 | 41.0 |
| 8 | 104,285,448 | 41.7 |
| 32 | 111,343,646 | 44.5 |
| 64 | 121,128,923 | 48.5 |
On-chain binary is 98 KB. Default 1.5 MB heap is sufficient across the whole range. Each extra public input costs ~270-300k cycles (one G1 scalar mul).
What’s next (Phase 4, before audit)
- Fuzzing + property tests on the Molecule wire decoders
- Targeted unit tests for edge-of-curve inputs (off-subgroup G2,
non-canonical encodings, identity, truncated/oversized buffers) - Threat model document
- Audit prep
How to try it
Repo: groth16-ckb
examples/square-root/ walks through the full deploy + verify flow on Pudge using the trivial x*x = y circuit, with a TypeScript SDK (sdk/ts/) for building the verify transaction.
Feedback welcome
Particularly on the Molecule schema (schemas/groth16.mol) and the threat model scope before I lock it in. The verifier is intended as general CKB infra (the original motivation was Spectre’s key-recovery needs, but the design is application-agnostic), so I’d love to hear whatother circuits people are thinking about.