Technical Deep Dive

How LiberProof works

From zero-knowledge fundamentals to Groth16 circuits and on-chain attestation — the complete picture of how LiberProof turns credentials into proofs without leaking data.

What is a zero-knowledge proof?

A ZK proof lets you convince someone that a statement is true — without revealing anything about why it's true. The math enforces the privacy; there's no trust required.

🧮
The core intuition
Imagine you want to prove you know the solution to a puzzle without showing the solution itself. A zero-knowledge proof is exactly that — a mathematical protocol where a Prover convinces a Verifier that a statement is true, without the Verifier learning anything else.

Formally, a ZK proof satisfies three properties: Completeness (an honest prover always convinces the verifier), Soundness (a dishonest prover cannot fake a valid proof), and Zero-Knowledge (the verifier learns only that the statement is true — nothing more). LiberProof implements ZK-SNARKs: Succinct Non-interactive Arguments of Knowledge. "Succinct" means proofs are small (~128 bytes) and fast to verify. "Non-interactive" means no back-and-forth — you generate the proof once and anyone can verify it.
🎭
Prover vs Verifier
The Prover (you) holds private data — your credential attributes. You generate a proof that commits to specific claims without revealing the underlying data. The Verifier (a service, smart contract, or institution) receives the proof and a set of public inputs — the claims being made — and verifies the proof is valid. They learn whether the claims are true. Nothing else.
🔑
Public inputs vs private witness
Every ZK proof has two parts: the public inputs (what you're claiming — "age ≥ 18") and the private witness (the data that makes it true — your actual age of 31). The circuit encodes the relationship between them. The proof proves the witness satisfies the circuit — without revealing the witness itself.

Groth16 — the proving system

LiberProof uses Groth16, a pairing-based ZK-SNARK construction that produces constant-size proofs with millisecond verification — ideal for both browser and on-chain use.

~128 B
Proof size (constant)
<1 ms
On-chain verification
BN254
Elliptic curve pairing
3 points
Proof structure (A, B, C)
⚙️
Trusted Setup
Groth16 requires a one-time trusted setup ceremony per circuit to generate proving and verification keys. LiberProof's setup uses multi-party computation (MPC) — meaning as long as one participant is honest, the toxic waste is destroyed. Setup parameters are public and auditable.
🔗
Pairing-based cryptography
Groth16 relies on bilinear pairings over the BN254 elliptic curve. The pairing operation allows the verifier to check a linear relationship between the prover's commitments without evaluating the polynomial directly — this is what makes verification constant-time regardless of circuit complexity.
📐
R1CS constraint system
Each circuit is expressed as a Rank-1 Constraint System (R1CS) — a set of equations that must hold for a valid witness. For example, the age circuit enforces age - threshold ≥ 0 as a constraint. Compilation converts the R1CS into the Groth16 proving/verification key pair.
📦
Proof structure
A Groth16 proof consists of three elliptic curve points: π_A (in G1), π_B (in G2), and π_C (in G1). These 128 bytes are all a verifier needs — along with the public inputs — to confirm the proof's validity. No additional communication required.

Credential to proof — step by step

Every LiberProof flow follows the same four-stage pipeline. Private data stays local at every stage.

01
Stage 1 — Issuance
Issuer signs a credential
A trusted issuer — a government registry, institutional verifier, or LiberVault wallet itself — signs a credential containing your attributes: { age, citizenship, balance, ... }. The signature is an EdDSA commitment over the attribute set. The credential is delivered to you and stored only on your device.
Local
02
Stage 2 — Witness Generation
Select claims to prove
You choose which claims to prove from your credential — for example, age ≥ 18. LiberProof constructs the witness: the full private inputs to the circuit, including your actual age value and the credential signature. The witness never leaves your device.
Local
03
Stage 3 — Proof Generation
Groth16 proof computed in browser
The Groth16 prover runs entirely in your browser using snarkjs and WebAssembly. It takes the witness and the circuit proving key, and outputs a 128-byte proof along with the public inputs. The private witness is discarded after proof generation — it is never transmitted.
Local
04
Stage 4 — Verification
Proof verified — on-chain or off
The proof and public inputs are submitted to a verifier — a web service, API endpoint, or Solidity smart contract on the Liberland blockchain. Verification runs the Groth16 pairing check: valid or invalid. The verifier learns only the result and the public claims — nothing else.
Public

API reference

LiberProof exposes a clean JavaScript API. Generate and verify proofs in a few lines.

liberproof-sdk / example.js
import { LiberProof } from '@liberproof/sdk'; // Initialize with your circuit configuration const lp = new LiberProof({ circuit: 'age_threshold_v2', wasmPath: '/circuits/age_threshold.wasm', zkeyPath: '/circuits/age_threshold_final.zkey', }); // Load a credential (stored locally — never transmitted) const credential = await lp.loadCredential(credentialJWT); // Generate a ZK proof — runs entirely in browser const { proof, publicInputs } = await lp.prove({ credential, claim: { age: { gte: 18 } }, // what to prove // actual age stays private — never exposed }); // Verify locally (or send proof + publicInputs to a verifier endpoint) const valid = await lp.verify({ proof, publicInputs }); console.log(valid); // true — 0 bytes of raw data exposed // Submit to on-chain verifier contract await verifierContract.verifyAgeProof(proof, publicInputs);

Attestation on the Liberland chain

Proofs can be submitted as permanent, verifiable records on the Liberland blockchain — creating tamper-proof attestations without revealing the underlying data.

📜
Solidity Verifier
Each circuit type has a generated Solidity verifier contract deployed on the Liberland chain. The contract exposes a verifyProof() function that runs the Groth16 pairing check on-chain. Gas cost is constant regardless of circuit complexity.
🗃️
Attestation Registry
The LiberProof registry contract records verified proofs as nullifier hashes — preventing double-submission while preserving privacy. An attestation record proves a proof was valid at a specific block height, without storing the proof or public inputs indefinitely.
🔁
Composable Verification
Other smart contracts on the Liberland chain can query the registry or call verifier contracts directly. This enables composable governance: a DAO can require a verified age proof or citizenship proof as a prerequisite for participation — with no identity exposure.

Own your
proof layer.

LiberProof is open source and ready to integrate. Start building privacy-preserving credentials for your sovereign systems.

GitHub Repository