Three machines.
One language.
Zero trust.
Three bytecode VMs. Akron runs your code. Artik computes witnesses. Lysis builds the circuit.
Meet the Machines
Three bytecode VMs. Three layers of the pipeline.
Runs Achronyme as a real language. Variables, closures, mark-sweep GC, 40 opcodes. The same code you test with ach run is the code that gets compiled. No translation gap.
Computes witnesses for circuits where Circom hits a wall. No heap, no GC, pure field arithmetic. Runs inside the R1CS backend to close the E212 gap.
Expands templates into constraints without memory explosions. Hash-consing collapses identical sub-graphs. Turns eager expansions from gigabytes into lean IR.
VM Mode
A real programming language with closures, recursion, mark-sweep GC, 37 opcodes, and 50 type methods. 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) $ ach circuit vote.ach --inputs "..." --backend r1cs
Compiling vote.ach...
IR: 18 instructions
Optimized: 3 eliminated (constant folding + DCE)
Boolean propagation: 2 proven
R1CS generated:
Constraints: 2,179
Public inputs: 4
Private inputs: 5
Wrote vote.r1cs (932 bytes)
Wrote witness.wtns (236 bytes) — verified OK Circuit Mode
Same syntax compiles to R1CS or Plonkish constraints. Boolean propagation, constant folding, and taint analysis catch under-constrained bugs before proof generation.
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-backend r1cs
Proof generated (Groth16, 855 bytes)
Proof verified — 5 constraints
$ ach circuit proof.ach --solidity Verifier.sol
Wrote Verifier.sol (Solidity Groth16 verifier)
// Deploy and verify on-chain let secret = 0p12345
let blinding = 0p98765
let commitment = poseidon(secret, blinding)
let proof = prove(commitment: Public) {
assert_eq(poseidon(secret, blinding), commitment)
}
// proof is a first-class value
let json = proof_json(proof)
assert(verify_proof(proof)) 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.
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
let commitment = poseidon(secret, blinding)
prove(commitment: Public) {
assert_eq(poseidon(secret, blinding), commitment)
}
// Proof generated + verified (Groth16) $ ach run commitment.ach
Proof generated (Groth16, 855 bytes)
Proof verified — 361 constraints