Write code.
Generate proofs.
A zero-knowledge DSL with dual execution. Run your code in a full VM or compile it to arithmetic circuits. Same syntax, two targets.
Dual execution engine
One language, two targets. No compromises.
VM Mode
A real programming language with closures, recursion, mark-sweep GC, 36 opcodes, and 43 native functions. Build anything from binary search to cryptographic protocols.
// Binary search — full VM mode
fn binary_search(arr, target) {
mut lo = 0
mut hi = len(arr) - 1
while lo <= hi {
let mid = (lo + hi) / 2
if arr[mid] == target { return mid }
if arr[mid] < target {
lo = mid + 1
} else {
hi = mid - 1
}
}
return -1
}
let sorted = [2, 5, 8, 12, 16, 23, 38]
assert(binary_search(sorted, 23) == 5) Circuit Mode
Same syntax compiles to R1CS or Plonkish constraints. Boolean propagation, constant folding, and taint analysis catch under-constrained bugs before proof generation.
$ ach circuit vote.ach --backend r1cs
Compiling vote.ach...
Parsed 24 statements
SSA: 18 instructions
Optimized: constant folding (3 eliminated)
Optimized: boolean propagation (2 skipped)
R1CS generated:
Constraints: 2,179
Public inputs: 4
Private inputs: 5
Wrote vote.r1cs Proofs without the ceremony
Native Groth16 and PlonK provers. One binary, zero Node.js.
First-Class Proofs
prove {} blocks return real proof objects. Chain them, extract components with proof_json(), verify inline with verify_proof(). Proofs are values, not CLI artifacts.
let secret = 0p12345
let blinding = 0p98765
prove {
witness secret
witness blinding
public commitment
let cm = poseidon(secret, blinding)
assert_eq(cm, commitment)
}
// proof is a first-class value
let json = proof_json(proof)
assert(verify_proof(proof)) On-Chain Verification
Export .r1cs and .wtns for snarkjs compatibility. Generate Solidity verifier contracts with --solidity. Deploy and verify proofs directly on Ethereum.
$ ach run proof.ach --prove --prove-backend r1cs
Proof generated (Groth16, 192 bytes)
Proof verified
$ ach circuit proof.ach --solidity Verifier.sol
Wrote Verifier.sol
Contract: Groth16Verifier
Function: verifyProof(uint[2], uint[2][2], uint[2], uint[4])
// Deploy and verify on-chain The difference
Proving a Poseidon commitment: Circom + snarkjs vs Achronyme.
// 1. Write the circuit (Circom DSL)
template Commitment() {
signal input secret;
signal input blinding;
signal output cm;
component h = Poseidon(2);
h.inputs[0] <== secret;
h.inputs[1] <== blinding;
cm <== h.out;
}
// 2. Compile
$ circom commitment.circom --r1cs --wasm
// 3. Witness (JavaScript)
const input = { secret: "12345", blinding: "98765" };
const w = await circuit.calculateWitness(input);
// 4. Powers of Tau
$ wget ptau.hermez.io/powersOfTau28_12.ptau
// 5. Trusted setup
$ snarkjs groth16 setup commitment.r1cs pot.ptau key.zkey
$ snarkjs zkey contribute key.zkey final.zkey
// 6. Prove
$ snarkjs groth16 prove final.zkey witness.wtns proof.json
// 7. Verify
$ snarkjs groth16 verify vkey.json public.json proof.json let secret = 0p12345
let blinding = 0p98765
prove {
witness secret
witness blinding
public commitment
let cm = poseidon(secret, blinding)
assert_eq(cm, commitment)
}
// Proof generated + verified (Groth16)