Skip to main content

Zero-Knowledge Proofs

Specter uses Groth16 zero-knowledge proofs on the BN254 curve to verify Ghost Protocol reveals. Proofs are 256 bytes, verified in a single pairing check (~200K gas), and can be generated client-side in a browser or server-side via the proof relayer.

Proof system

ParameterValue
Proof systemGroth16
CurveBN254 (alt_bn128)
Proof size256 bytes (3 EC points)
Verification gas~200,000 (via ecPairing precompile)
Circuit languageCircom 2.x
Proving librarysnarkjs (browser/Node.js)

Circuits

Specter has two ZK circuits:

Redemption circuit

The primary circuit used for revealing (redeeming) committed tokens. Proves:

  • Knowledge of a commitment's preimage (secret, nullifierSecret, amount, etc.)
  • The commitment exists in the Merkle tree
  • The nullifier is correctly derived
  • Amount conservation (withdraw + change = committed amount)
  • Policy binding (if applicable)

Public inputs: 8 | Private inputs: 7+ (including Merkle path)

Access proof circuit

A non-destructive proof used for persistent key operations. Proves knowledge of a commitment without revealing or spending it. Used for the Phantom Keys system.

Public inputs: 4 | Private inputs: 5+

Proof generation options

Client-side (snarkjs in browser)

import * as snarkjs from 'snarkjs';

const { proof, publicSignals } = await snarkjs.groth16.fullProve(
circuitInputs,
'redemption.wasm',
'redemption_final.zkey'
);

Server-side (proof relayer)

curl -X POST https://relayer.specterchain.com/api/proof/generate \
-H "Content-Type: application/json" \
-H "X-HMAC-Signature: $HMAC_SIG" \
-d '{ ... circuit inputs ... }'

On-chain verification

The Groth16ProofVerifier contract at 0x2C8Fb67874E5f380efB995a9Ab59b2Ef327E5bd2 uses Ethereum's ecPairing precompile for verification. The verification key is hardcoded from the trusted setup.

Next steps