Axiomatic
Privacy & Confidential Transfers

Engine & Prover

Build matrix, feature flags, and verifier export for the Halo2-KZG proving system.

Build Matrix

The Rust engine (engine/) supports multiple build configurations via Cargo feature flags:

FeatureBackendUse CaseBinary
zkHalo2 IPA (Pallas)Accounting proofs (period close, solvency, etc.)axiomatic-prover
zk-privacyHalo2 KZG (BN254)JoinSplit circuit for shielded transfersexport-verifier

Default Build (WASM)

cargo build --target wasm32-unknown-unknown

Produces the WASM module for the DSL engine. No ZK proving capabilities — proofs are mocked.

Native Prover Build

cargo build --release --features zk

Builds the axiomatic-prover binary with all accounting circuits. The TypeScript platform shells out to this binary for proof generation.

Privacy Prover Build

cargo build --release --features zk-privacy

Enables the JoinSplit circuit (Halo2-KZG on BN254) and the export-verifier binary. This is required for real shielded transfer proofs.

Prover Commands

The axiomatic-prover binary accepts commands via CLI arguments and reads witness data from stdin:

CommandDescription
prove-joinsplitGenerate a JoinSplit proof from a witness
prove-innocenceProve deposit origins are not in a sanctioned set
prove-periodGenerate a period close proof
prove-solvencyGenerate a solvency proof
poseidon-hashCompute Poseidon hash of two BN254 field elements
verifyVerify a proof
export-vkExport verification key for a circuit

JoinSplit Witness Format

The witness JSON sent to prove-joinsplit must match the Rust JoinSplitWitness struct:

{
  "spending_key": "hex-string",
  "input_notes": [
    { "owner_pubkey": "hex", "token_hash": "hex", "value": "hex", "salt": "hex" },
    { "owner_pubkey": "hex", "token_hash": "hex", "value": "hex", "salt": "hex" }
  ],
  "input_merkle_paths": [
    { "siblings": ["hex", "...32 total"], "indices": [false, "...32 total"] },
    { "siblings": ["hex", "...32 total"], "indices": [false, "...32 total"] }
  ],
  "output_notes": [
    { "owner_pubkey": "hex", "token_hash": "hex", "value": "hex", "salt": "hex" },
    { "owner_pubkey": "hex", "token_hash": "hex", "value": "hex", "salt": "hex" }
  ],
  "merkle_root": "hex",
  "nullifier_hashes": ["hex", "hex"],
  "new_commitments": ["hex", "hex"],
  "value_delta": "hex",
  "token_hash": "hex",
  "recipient_pubkey_hash": "hex"
}

The circuit enforces:

  • Input notes exist in the Merkle tree (membership proof)
  • Nullifiers are correctly derived from spending key + commitment
  • Output commitments are correctly computed
  • Values are conserved: sum(inputs) == sum(outputs) + value_delta
  • Owner derivation: owner_pubkey == Poseidon(spending_key)

Verifier Export

flowchart LR
  BUILD["cargo build<br/>--features zk-privacy"] --> VK["Generate VK from<br/>JoinSplit circuit"]
  VK --> EXPORT["export-verifier binary"]
  EXPORT --> SOL["Halo2KZGVerifier.sol"]
  SOL --> DEPLOY["Deploy to chain"]

To regenerate the Solidity verifier after circuit changes:

cargo run --features zk-privacy --bin export-verifier > protocol/packages/privacy/src/Halo2KZGVerifier.sol

This generates the full Solidity verifier contract (via halo2-solidity-verifier) containing Halo2VerifyingKey, Halo2Verifier, and a wrapper Halo2KZGVerifier that implements IHalo2KZGVerifier. Pass --json to output VK metadata instead of Solidity.

Circuit Parameters

ParameterValue
CurveBN254
BackendKZG (GWC prover)
k14 (16,384 rows)
Merkle depth32
Inputs2
Outputs2
Public inputs8
Estimated proving time2-5s (native), 30-60s (WASM)
On-chain verification gas~250,000-350,000

On this page