ZK-SNARK Application Development: From Circuit to Audit

The proof circuit determines whether a solution will run fast and predictably. We develop ZK-SNARK turnkey: from circuit design to audit and handover of procedures. The client receives a manageable result and a reduction in data verification time by orders of magnitude.

Blockchain Development Services

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1376
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1350
  • B2B Advance company logo design
    B2B Advance company logo design
    798
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1088
  • AIDER company logo development
    AIDER company logo development
    1034
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1130

Why zero-knowledge proofs hit a wall with the circuit

ZK-SNARK development almost never hits a wall with the choice of curve or library — it hits a wall with the constraint system.

Every arithmetic operation, every range check, every memory access turns into constraints, and it is their number that determines everything downstream: how much memory key generation will consume, how long proof generation will take on the client side, and how much verification will cost on-chain. A circuit assembled "however it came out" works in tests and falls apart at real volumes.

The typical picture looks like this: logic is ported into the circuit one-to-one from ordinary code, without decomposition into reusable components.

The circuit balloons several times over, proof generation time grows from seconds to tens of seconds, and verification stops fitting into reasonable gas.

Then the patching begins: some checks are moved outside the circuit, trusting the input data — and that is already a hole in the security model, not an optimization.

Control is lost in three places. First — the circuit boundaries: it is unclear what exactly is being proven and what is taken on faith.

Second — the constraint budget: there is no target number that the optimization converges to, so there is nothing to measure "improvements" against.

Third — the cost of verification: it is baked into the contract last, when it is already too late to change the architecture.

We break down how this is closed: by designing the circuit from the target proof generation time and verification cost, rather than from the convenience of porting code.

What a correctly designed proof scheme delivers

A correctly designed scheme is not "beautiful mathematics" but concrete metrics that the customer sees in production.

The number of constraints in an arithmetic circuit directly determines proof generation time and key size: a successful decomposition of the computation and moving heavy operations outside the circuit reduce the circuit severalfold, and the prover starts fitting into a predictable window instead of "depending on how lucky you get with the hardware."

Verifier load is a topic of its own. If verifying a proof is expensive, it cannot be cheaply embedded into a smart contract or a client application.

We design the scheme so that verification remains compact and cheap in gas, and the verifying party does not drag heavy computations along with it.

Trusted setup is the most common source of hidden vulnerabilities. An error in the ceremony or insecure storage of "toxic waste" devalues the entire proof system.

We close this class of risks architecturally: either we use transparent schemes without a trusted setup, or we build a multi-party ceremony with verifiable contributions and publish the artifacts for independent verification.

The practical effect is a predictable proof cost on the user's side and reduced risks on the protocol's side.

We build the scheme on Circom and test it against real scenarios before it goes to audit — this way the number of rework iterations falls rather than grows toward release.

Comparison of approaches: where each proof mode is appropriate

The choice of proof mode determines not only the cost of verification, but also which trust requirements you accept at the start.

Transparent setup removes the multi-party ceremony, but requires schemes where parameters are derived from public randomness — otherwise trust in the initialization becomes part of the threat model.

Universal schemes provide a single verification circuit for different types of statements, whereas task-specific schemes win in proof size and generation time, but are tied to a specific logic.

The separation of off-chain proving and on-chain verification is about where the computation lives and where only verification happens.

The heavy part is computed off-network, a compact proof and a verifier call go to the chain; both the gas cost and what actually enters the public state depend on the correctness of this boundary.

Option When it is suitable Limitations
Transparent setup Reproducibility of parameters without a ceremony is needed; auditability matters more than minimal proof size Proofs are larger, generation takes longer; not every scheme supports this mode
Trusted setup Maximum compactness and on-chain verification speed are required Trust in the initialization; a ceremony protocol and its artifacts are needed
Universal scheme Multiple types of statements on one circuit, frequent logic changes Higher verification overhead compared to a specialized scheme
Task-specific scheme One stable logic where proof size and generation time matter Reuse is limited; changing the scheme requires rebuilding and re-verification
Off-chain proving Heavy computations, private input data Generation infrastructure and control over it are needed; delay before entering the network
On-chain verification Public verification of the result, integration with contracts Gas cost for verification; constraints on proof size and format

In practice, modes are combined: transparent setup for auditable circuits, a specialized scheme where the proof goes on-chain constantly. Let's break down which set is suitable for your logic and trust requirements.

ZK-SNARK Development Stages: from Task Audit to Handover

ZK-SNARK development is not "write a circuit and compile it," but a sequence where a mistake at an early step nullifies all the work: a poorly formulated statement yields a circuit that proves the wrong thing, while extra constraints in the circuit inflate proof generation time by an order of magnitude. Below is the route our team follows.

  1. Statement analysis. We pin down exactly what we are proving and what remains private: which inputs are public, which are hidden, which conditions must hold. The output is a formal statement and a list of edge cases the circuit must reject.
  2. Circuit design. We choose the field arithmetic, break the computation down into constraints, and estimate their number. Here we also decide where we can do without a proof — every extra operation inside the circuit multiplies the cost of generation.
  3. Circuit implementation. We write the circuit in the chosen domain-specific language and cover it with tests on valid and deliberately false inputs. The goal is for an invalid witness to consistently fail verification, not "usually fail."
  4. Parameter setup. We run the trusted parameter generation ceremony and describe the procedure so that it can be reproduced and independently verified.
  5. Proof generation and verification. We measure generation time and proof size, and check verification on the consumer side — in a contract, backend, or client. If verification does not fit within the platform's limits, we return to step 2.
  6. Audit and handover. We send the circuit and constraints for an external audit, address the findings, and hand over the repository, parameters, tests, and documentation on the statement and setup procedure.

This route keeps things predictable: you see the cost of the proof in advance and the point you will return to if it stops being acceptable. Describe your task — we will come back with an estimate for each stage and a work plan.

Output artifacts: circuits, constraint systems, keys, and procedures

ZK-SNARK development ends not with a prototype demonstration, but with a set of artifacts that allow the system to be built, verified, and maintained without us. Below is what exactly remains with the client after delivery.

  • Statement description. A formal specification of what the circuit proves, with explicit boundaries: which inputs are public, which are private, which conditions are considered a violation. This is the document that serves as the starting point for any change in logic.
  • Circuit source code. Readable source code of the circuits and constraint systems, not just the compiled artifacts: they show how the statement is decomposed into operations, and allow you to modify the logic without rewriting everything from scratch.
  • Setup parameters. Trusted setup files and the procedure for generating them: who participated, how correctness was verified, what to do in case of compromise. Without this step, the proofs are invalid.
  • Verifier. Proof verification code embedded in your infrastructure — a smart contract or a service — with tests for valid and deliberately false proofs.
  • Test suite. Vectors with reference pairs of "proof — verification result," including negative cases: forgery, reuse, out-of-bounds inputs.
  • Documentation. Component interaction diagram, environment requirements, build and deployment procedure, known limitations of the chosen construction.
  • Update procedure. Rules for modifying the circuit: when a new setup is needed, how to maintain compatibility of old proofs, who approves the transition to a new version.

Such a package allows you to hand over maintenance to your team or a contractor without reverse engineering. Describe your task — we will get back to you with an estimate and a plan for each artifact.

Case study: how a scheme with a million constraints became manageable

What it was before

The client came with a working private transfer proof scheme: the logic was correct, local tests passed, but in the production environment proof generation hit a ceiling.

The scheme had grown to ~4.2 million constraints — each new range check and hash chain added arithmetic, not logic. Proof generation took 40+ seconds, on some user devices the process crashed due to memory, and only about 82% of attempts made it to verification. For the product, this meant drop-off at the final step and manual incident investigations.

What was changed

Our engineers started not with code, but with profiling the scheme: they captured the distribution of constraints across blocks and saw that almost a third of the arithmetic came from repetitive checks that could be moved into shared "gates" and reused.

They rewrote the hash chain using a more economical variant, moved some of the heavy operations outside the scheme, leaving inside only what genuinely required proof.

In parallel, they separated the contours: proof and verification received separate resource profiles, and the trusted setup parameters were fixed and documented so that the result would reproduce at the client's side without "magic".

The key step was a regression set of test vectors: every optimization was checked for matching results against the original scheme, otherwise the constraint savings would break correctness.

What it became

Metric Before After
Number of constraints ~4.2 million ~1.6 million
Proof time 40+ s 9–11 s
Share of successful verifications ~82% ~99.6%

The scheme stopped hitting memory limits on weak devices, drop-off at the final step almost disappeared, and proof time fit into a window comfortable for the user.

The client confirmed the result on their own test bench: the metrics reproduced without changes, and the regression test vectors passed completely.

Separately, we handed over a profiling report and an optimization log — so the team would understand how much constraint headroom remained for future features.

How does a trusted setup differ from a transparent one?

A trusted setup is a stage of generating circuit parameters in which a secret random value is created. If it is not destroyed, its owner gains the ability to forge proofs: to generate a valid proof for a false statement, and no one will notice.

That is precisely why the parameters are not created by a single person, but through a ceremony — a multi-round protocol in which each participant contributes their share of randomness and destroys it.

It is enough for at least one participant to honestly erase their fragment — then the secret cannot be recovered.

The risks of a trusted setup do not disappear entirely; they shift. The question of trust in the ceremony organizers remains: how many independent participants there were, whether confirmations of destruction were published, whether the final parameters can be verified.

The fewer the participants and the weaker the transparency of the process, the higher the cost of an error — compromising the circuit devalues all proofs built on it.

A transparent setup removes this class of risks: the parameters are derived from public data, and a secret that could be lost or stolen simply does not exist. The price for this is a larger proof size and a higher computational load for generation and verification.

The scheme is justified where the cost of trust is higher than the cost of performance: public registries, bridges, voting systems, any scenarios where the verifying party must not trust anyone.

The practical choice depends on the task. If proofs are verified within a closed environment and the parties are bound by a contract, a trusted setup with a correctly conducted ceremony yields compact and fast proofs.

If verification is public and the parties do not trust each other, a transparent scheme removes the question of "what if the organizers kept a secret." We work through this choice at the circuit design stage — before the first line of code is written, because changing the setup type rewrites the entire proof chain.

Technical concerns before starting work

Before starting, almost every team asks the same set of questions: will the proof scheme integrate into the current product, what to do with already running contracts, will verification withstand the real transaction flow, and who maintains the scheme after release. Below are the answers on the merits, without generalities.

Is the proof scheme compatible with our current stack?

The scheme and the verifier are not tied to a specific blockchain — they are compiled for the target environment and connected as a regular contract or module.

We check compatibility at the design stage: which curves and hash functions your network supports, whether ready-made verification libraries exist, and whether the proof size fits within gas limits.

If the network does not support the required primitives, we propose an alternative scheme before work begins, not after.

What about migrating an already deployed solution?

Migration proceeds in stages: the new verifier is deployed in parallel with the old one, and traffic is switched after testing under load.

State and trust keys are transferred according to a pre-described procedure, and rollback to the previous version remains available throughout the transition. We fix the points of no return and keep the rollback plan in the documentation.

Will verification withstand the real load?

The cost of verifying a proof is orders of magnitude lower than the cost of the computation itself, so the bottleneck is usually not the verifier but proof generation on the client side.

We profile both sections on a realistic transaction profile, measure generation and verification time, and determine where batching or offloading of computations is needed. The result is a throughput forecast before launch, not after.

Who maintains the scheme after release?

The scheme is code and trust parameters; they require versioning and updates when the logic changes. We hand over the scheme sources, build scripts, a description of the setup ceremony, and update instructions.

After that, either your team handles maintenance according to this documentation, or we remain on support with an incident response procedure.

If any of the questions comes down to the specifics of your product — describe the task, and we will come back with an estimate and a work plan.

Let's discuss your task and come back with an estimate and a plan

To come back with an estimate and a work plan for ZK-SNARK development, we need a minimum of input — after that, the engineers will figure out the scheme, constraints, and fill in the gaps themselves.

The more precisely the scenario is described, the fewer assumptions in the estimate and the more realistic the timelines at the start of the project.

To get started, the following is enough:

  • task description: what exactly we are proving — ownership of data, correctness of computation, the fact without revealing the amount;
  • where the proof is verified: a separate service, a smart contract, an off-chain verifier;
  • privacy requirements: which inputs remain private, which are published;
  • expected load: how many proofs per second and the acceptable generation time;
  • target environment: network, clients, resource constraints of the verifier;
  • project constraints: timelines, regulatory requirements, existing code and schemes;
  • who on your side makes decisions on the scheme and confirms acceptance.

This is enough to come back with an estimate of effort, scheme options, and a staged work plan — from circuit design to audit and launch. If some of the data is not yet defined, we will record the assumptions explicitly and clarify them at the very first review.

Describe the task in any convenient form — we will come back with an estimate and a plan, with no obligations on your side.