Skip to main content

Private Balance Proofs with EAS, Noir, and Mopro

· 6 min read
Sooyoung Hyun
Co-founder, ZKProofport

An application checking a balance requirement may only need one answer: does this user meet the threshold? The exact balance and the wallet associated with it can remain private.

GIWA Dojang provides a useful starting point. Built on the Ethereum Attestation Service (EAS), it defines a Balance Root format that represents a snapshot of balances as a Merkle root.

We used that existing format to build a complete example: express the private conditions in Noir, generate a proof through Mopro’s native Noir adapter, and verify it in a Solidity contract that reads EAS state.

The example uses synthetic balances and a local chain. Proof generation, EAS interactions, and Solidity verification are all real.

Explore the code and reproduction scripts →

From an attestation to a private balance proof​

A Balance Root summarizes a collection of balance entries. Each entry contains a wallet address, an amount, and a salt. A Merkle path connects the entry to the root recorded in an EAS attestation.

Suppose an entry contains a balance of 100, and an application requires at least 80. Our Noir circuit proves that:

  • The balance entry belongs to the specified root.
  • Its amount meets the public threshold.
  • The wallet associated with the entry authorized this request.

The exact amount, original wallet address, Merkle path, and signature are private inputs. The threshold, root, receiving address, and request context are public.

The receiving address can differ from the wallet in the balance entry. The signed request binds that address, the chain, application contract, nonce, deadline, and attestation context. Changing these fields requires a new authorization.

The Solidity application checks the EAS record, verifies the proof, and marks the request as consumed.

How the pieces fit together​

Each component handles a different part of the flow:

ComponentResponsibility
GIWA DojangProvides the existing balance data format we target
EASRecords the root’s issuer, schema, expiration, and revocation state
NoirExpresses private membership, balance comparison, and wallet authorization
MoproConnects the Noir circuit to native proving and generated bindings
Barretenberg and SolidityGenerate the proof and verify it on the EVM

Keeping the existing data format was an important constraint. Dojang uses Ethereum ABI encoding followed by double Keccak hashing for leaves, with sorted hash pairs along the Merkle path.

We implemented the same byte layout in Noir, including address padding. Amounts are represented as 32-byte integers, preserving the full uint256 range without reducing values into a single field element.

Compatibility tests cover OpenZeppelin-generated trees and an original Dojang test vector. The Noir vector test calls the same Merkle functions used by the complete circuit.

Why the EAS check still matters​

A cryptographically valid proof can refer to a root that has expired, been revoked, or was issued by an organization the application does not trust.

The gate therefore reads EAS state when processing each request. It checks the issuer, schema, expiration, revocation, asset, and snapshot policy before verifying the proof. A root revoked after proof generation will still be rejected.

This separates two responsibilities: Noir checks the conditions over the private data, while the application checks whether the referenced attestation is acceptable.

We tested both successful requests and failure cases:

CaseExpected result
Balance 100, threshold 80 or 100Accept
Balance 100, threshold 101Reject
Modified amount, Merkle path, or signatureReject
Existing proof used with a different receiving addressReject
Unauthorized issuer or expired/revoked rootReject
Identical request submitted twiceReject

The test runner also distinguishes circuit rejection from execution errors. Missing files and malformed inputs cannot count as successful negative tests.

Connecting Mopro to Solidity verification​

We used Mopro’s Noir adapter with noir-rs beta.19 and Barretenberg 4.2.0-aztecnr-rc.2. Proofs use the Keccak-based EVM configuration with zero knowledge enabled.

Three integration details were particularly useful:

  • Proof serialization. This noir-rs version includes a four-byte public-input count before the inputs and proof. We used its parser and compared the resulting public inputs with those constructed by the Solidity gate.
  • Verifier deployment. The generated Solidity verifier requires library linking. The scripts generate the verifier from the current verification key and deploy its linked library.
  • Native bindings. We generated Swift bindings and verified the complete proof through Swift on macOS.

The iOS simulator build encountered a transitive backtrace/libc dependency issue. This balance circuit has not been executed on a simulator or physical phone. The repository records that failure alongside the successful native and Swift host paths.

Measuring the complete circuit​

We measured the initial implementation at three Merkle depths. Every run included membership verification, full-width balance comparison, wallet signature verification, and request binding.

Merkle depthBarretenberg finalized size (pre-padding)Median adapter callMedian peak process memory
8311,3564.62 s2.17 GiB
12383,2486.19 s2.26 GiB
16455,1407.90 s2.35 GiB

Circuit sizes were extracted using the benchmark’s pinned toolchain and hash-matched ACIR artifacts. All three circuits have a padded size of 524,288 (2¹⁹).

Measurements used an Apple M4 with 16 GiB RAM, three measured runs per depth, and a preparatory run excluded.

The adapter interval includes witness execution, proving, and internal SRS reading/setup. Initial downloads and initial verification-key preparation are excluded. Memory covers the entire native process. These are host measurements, not mobile benchmarks or isolated proving times.

Successful local redemption transactions used approximately 3.06 million gas, including EAS policy checks, proof verification, and request consumption.

The results document identifies the measured revision and preserves the raw data. Validation of the subsequent refactor is recorded separately; its depth benchmarks have not been rerun.

Try the example​

With the prerequisites listed in the README installed:

git clone https://github.com/zkproofport/dojang-private-balance.git
cd dojang-private-balance
bash scripts/bootstrap.sh
bash scripts/run.sh

The scripts prepare the pinned dependencies, start a local Anvil chain, deploy EAS and the verifier, and run the proof and policy checks.

Connecting this example to real GIWA issuer data still requires a private way for holders to obtain their amount, salt, and Merkle path. The implementation checks a condition about an issuer-asserted snapshot. It does not establish a current balance or conceal information already published elsewhere.

The repository brings together an existing GIWA attestation format, EAS state checks, Noir conditions, Mopro native proving, and Solidity verification in one reproducible example. Developers can use it to explore the same boundaries with their own attestation data and application policies.

At ZKProofport, we have also explored a related flow in a Dojang KYC demo on GIWA Sepolia. This separate prototype uses test attestations to demonstrate KYC eligibility and authorization for another wallet, applying a similar idea to a different credential.

From Zero to ZK: Vibe a ZK Mobile App with mopro-ai

· 10 min read
Moven Tsai
Developer on the Mopro Team

TL;DR​

  • The problem: Building a mobile app with zero-knowledge (ZK) proofs requires complex environment setup and multiple toolchains. Most developers never get past the setup stage.
  • The tool: mopro-ai is a playbook that lets AI coding agents build ZK mobile apps for you.
  • Demo result: Starting from a single prompt, an AI agent built vibe-app, a Flutter app that generates and verifies ZK proofs entirely on-device.

The Problem: ZK on Mobile Is Still Too Hard​

At workshops, the pattern is always the same. Attendees show up excited to build a mobile proof-of-concept. Within the first hour, half the room is stuck on environment setup. Rust is not installed, or the wrong version. CMake is missing. Android NDK paths are misconfigured. Xcode command-line tools point to the wrong directory. The circuit compiles, but the trusted setup artifacts end up in the wrong folder. By the time someone gets to actually calling a prove function from Dart or Swift, the session is over.

The gap between "I want to try ZK on mobile" and "I have a working proof" is surprisingly wide. Here is what stands between a developer and a running mobile ZK app:

  • Environment setup: Rust toolchain (rustup, cargo, cross-compilation targets), platform SDKs (Xcode with command-line tools, Android Studio with NDK and JDK 17+, Flutter SDK), and all the PATH variables that glue them together
  • Circuit knowledge: Circom compiler, snarkjs for trusted setup, circomlib dependencies via npm, and the naming conventions and file structure that make a circuit compile cleanly
  • Mobile knowledge: Native build systems (Gradle, Xcode project settings), FFI wiring (UniFFI bindings, flutter_rust_bridge code generation), and asset bundling for .zkey files
  • Mopro knowledge: The correct sequence of mopro init, mopro build, mopro create, which flags to pass for each platform, and how these commands interact with the layers above

Each layer has its own failure modes and error messages. A developer who is proficient in Flutter but unfamiliar with Rust will hit different walls than one who knows Circom but has never opened Android Studio. The toolchain complexity is the bottleneck, not the ZK concepts themselves.

A ZK Mobile App Playbook for Agents​

mopro-ai is not just a plugin. It is a manual with structured knowledge that lets AI agents use mopro accurately and fluently instead of guessing at CLI flags and build sequences.

To install in Claude Code:

/plugin marketplace add zkmopro/mopro-ai
/plugin install mopro
mopro-ai-plugin
Plugin Installation for mopro-ai

The playbook covers the full mopro lifecycle:

CommandWhat it does
/mopro:check-envDiagnose environment and missing tools
/mopro:initInitialize a new mopro project
/mopro:buildBuild ZK bindings (5-15 min, runs in background)
/mopro:createGenerate app template from bindings
/mopro:testRun Rust, FFI, or UI tests
/mopro:deviceManage simulators, emulators, devices
/mopro:newFull workflow: init + build + create

Beyond slash commands, skills also activate automatically based on context. Mention "build for iOS" and the build skill triggers. Say "check my environment" and the env diagnostic runs. The agent does not need to memorize command names. It just needs mopro-ai loaded.

Crucially, mopro-ai includes guardrails that prevent common agent mistakes: never chain build + create in one step (builds take minutes and must be confirmed before proceeding), always pass --platforms flutter for Flutter apps (not --platforms ios, which produces incompatible native-only bindings), always use non-interactive CLI flags to avoid blocking on prompts, and never re-run a build without user confirmation. It also encodes error recovery paths and environment diagnostics.

mopro-ai is built on open standards, specifically Agent Skills for auto-triggered workflows and AGENTS.md for universal agent instructions, so it works across Claude Code, Cursor, VS Code Copilot, Codex CLI, and Gemini CLI.

What We Are Building​

The concrete example for this tutorial is vibe-app: a Flutter app that implements challenge-response authentication using zero-knowledge proofs. The user proves they know a secret S such that Poseidon(S, nonce) = expectedHash, without revealing S.

Everything runs on-device. No server-side proving. The "server" in the demo is a mock that provides the challenge (nonce + expected hash), simulating what a real backend would do.

The Prompt That Built vibe-app​

Here is the prompt that kicked off the entire project:

"Build a Flutter mobile app that uses mopro for proving knowing a server challenge in Circom. It should use mopro skills."

That is it. One sentence. With mopro-ai loaded, the agent recognized this as a mopro project and produced a 6-step implementation plan:

  1. Initialize a mopro project with Circom adapter
  2. Write the Circom circuit and run trusted setup
  3. Customize the Rust core to register the circuit
  4. Build bindings and create a Flutter app template
  5. Customize the Flutter UI for challenge-response flow
  6. Test end-to-end on a simulator

Each step maps directly to a mopro skill. The agent knew the correct CLI flags, the right file locations, and the build sequence, because mopro-ai told it exactly how mopro works. Without the playbook, the agent would have had to search documentation, guess at flags, and likely hit several dead ends before arriving at a working build. With the playbook, it executed the plan on the first try.

What the Agent Did​

Step 1: Initialize the project​

mopro init --project_name vibe-app --adapter circom

This scaffolds a Rust project with:

  • Cargo.toml with mopro-ffi, circom-prover, and rust-witness dependencies
  • src/lib.rs with template slots for each proof system
  • test-vectors/ directory for circuit artifacts
  • Config.toml for build configuration

Step 2: Write the circuit and run trusted setup​

The agent wrote a Circom circuit implementing Poseidon-based challenge-response:

pragma circom 2.0.0;

include "node_modules/circomlib/circuits/poseidon.circom";

template ChallengeResponse() {
signal input secret; // private
signal input nonce; // public
signal input expectedHash; // public

component hasher = Poseidon(2);
hasher.inputs[0] <== secret;
hasher.inputs[1] <== nonce;

expectedHash === hasher.out;
}

component main {public [nonce, expectedHash]} = ChallengeResponse();

The circuit takes three inputs: a private secret and two public signals (nonce and expectedHash). It computes Poseidon(secret, nonce) and constrains the result to equal expectedHash. A valid proof demonstrates knowledge of the secret without revealing it.

After writing the circuit, the agent compiled it with Circom and ran trusted setup using snarkjs to produce the .zkey and .wasm artifacts, then placed them in test-vectors/circom/.

Step 3: Customize the Rust core​

The agent modified src/lib.rs to register the circuit using mopro's macro system:

mod witness {
rust_witness::witness!(challengeresponse);
}

crate::set_circom_circuits! {
("challengeresponse_final.zkey",
circom_prover::witness::WitnessFn::RustWitness(
witness::challengeresponse_witness
)),
}

The rust_witness! macro generates a native Rust witness calculator from the compiled circuit, eliminating the need for WASM-based witness generation at runtime. The set_circom_circuits! macro registers the circuit with its .zkey file so generateCircomProof() knows which proving key to use.

The agent also wrote Rust tests to validate the circuit with known inputs:

#[test]
fn test_challenge_response_valid() {
let circuit_inputs = serde_json::json!({
"secret": "12345",
"nonce": "67890",
"expectedHash": "11344094074881186137859743404234365978119253787583526441303892667757095072923"
}).to_string();

let result = generate_circom_proof(
ZKEY_PATH.to_string(), circuit_inputs, ProofLib::Arkworks
);
assert!(result.is_ok());

let proof = result.unwrap();
let verify = verify_circom_proof(
ZKEY_PATH.to_string(), proof, ProofLib::Arkworks
);
assert!(verify.is_ok());
}

Step 4: Build bindings and create Flutter app​

The agent configured Config.toml:

build_mode = "release"
target_adapters = ["circom"]
target_platforms = ["flutter"]
auto_update = false

Then ran the two-step build process:

mopro build --platforms flutter --mode release

This cross-compiles the Rust prover for the target architectures and generates mopro_flutter_bindings/, a Flutter package containing the native libraries and Dart API.

After confirming the build succeeded:

mopro create --framework flutter

This generates a Flutter app template in flutter/ with the bindings already wired up, the .zkey file bundled as an asset, and a working pubspec.yaml.

Step 5: Customize the Flutter UI​

The agent built a step-by-step authentication flow in Dart. The key integration points are the proof generation and verification calls:

Generating a proof:

final proofResult = await generateCircomProof(
zkeyPath: zkeyPath,
circuitInputs: '{"secret":"$secret","nonce":"$nonce","expectedHash":"$expectedHash"}',
proofLib: ProofLib.arkworks,
);

Verifying a proof:

final valid = await verifyCircomProof(
zkeyPath: zkeyPath,
proofResult: proofResult,
proofLib: ProofLib.arkworks,
);

These two function calls are the entire ZK integration surface. Everything else (loading the proving key, computing the witness, running the Groth16 prover, serializing the proof) is handled by the mopro bindings underneath.

The UI guides users through four steps: enter a secret, receive a challenge from the (mock) server, generate a ZK proof, and verify it. Each step displays timing information and proof metadata so the user can see exactly what is happening.

The mock server simulates what a real backend would do: given a registered user's secret, it returns a nonce and the pre-computed Poseidon(secret, nonce) hash. In production, the server would never see the secret. It would only store the hash and generate fresh nonces for each authentication attempt. The ZK proof lets the user demonstrate they know the secret that produces the expected hash, without transmitting the secret itself.

Step 6: Test on simulator​

The agent started an iOS simulator and ran the app:

cd flutter && flutter run

The flow: enter 12345 as the secret, tap "Request Challenge" to get a nonce and expected hash from the mock server, tap "Generate ZK Proof" to run the Groth16 prover on-device, then tap "Verify Proof" to confirm the proof is valid. Proof generation typically completes in a few seconds on a modern phone or simulator. The secret never leaves the device.

The agent also handled the .zkey asset bundling by copying the proving key into flutter/assets/ and registering it in pubspec.yaml so Flutter can load it at runtime. This is one of those details that is easy to miss manually but that mopro-ai's app skill covers automatically.

What mopro-ai Handled For You​

Here is what the developer provided versus what mopro-ai automated:

Developer providedmopro-ai handled
One-sentence prompt describing the appCLI flag selection and build sequencing
Choice of proof system (Circom)Rust project scaffolding and dependency wiring
Choice of platform (Flutter)Cross-compilation for target architectures
Circuit logic (Poseidon challenge-response)FFI binding generation (flutter_rust_bridge)
UI requirements (step-by-step auth flow)Asset bundling (.zkey in Flutter assets)
Macro registration (rust_witness!, set_circom_circuits!)
Build duration management (background execution)
Platform-specific configuration (pubspec.yaml, Gradle)

Without mopro-ai, the agent would have had to guess at mopro's CLI interface, likely passing wrong flags (--platforms ios instead of --platforms flutter), missing the non-interactive flag requirements, or trying to chain build and create in a single step. mopro-ai eliminates that guesswork.

Vibe Your First ZK Mobile App​

Building a mobile ZK app no longer requires mastering five different toolchains. With mopro-ai loaded, an AI coding agent can go from a one-sentence description to a working Flutter app with on-device Groth16 proving. It handles the Rust scaffolding, circuit compilation, FFI binding generation, and platform wiring along the way.

The developer's job shifts from fighting build systems to designing circuits and user experiences. That is the gap mopro-ai is designed to close.

Try it yourself: install mopro-ai, describe the ZK app you want to build, and let the agent handle the plumbing.

References​

Client-Side GPU Acceleration for ZK: A Path to Everyday Ethereum Privacy

· 14 min read
Moven Tsai
Developer on the Mopro Team

Thanks to Alex Kuzmin, Andy Guzman, Miha Stopar, Sinu, and Zoey for their generous feedback and review.

TL;DR​

  • The Problem: Delegating ZK proof generation to servers often fails to preserve privacy, as the server sees your private inputs, though there are recent researches on private proof delegation 1 2 3 to mitigate this issue. Ultimately, true privacy requires client-side proving, but current performance is too slow for mainstream adoption.
  • The Opportunity: Modern mobile phones and laptops contain GPUs well-suited to accelerating parallelizable ZK primitives (NTT, MSM, hashing). Benchmarks show field operations on smaller fields like M31 achieve more than 100x throughput compared to BN254 on an Apple M3 chip 4.
  • The Gap: No standard cryptographic library exists for client-side GPU implementations. Projects reinvent primitives from scratch, and best practices for mobile-specific constraints (hybrid CPU-GPU coordination, thermal management) remain unexplored.
  • Post-Quantum Alignment: Smaller-field operations in post-quantum (PQ) schemes (hash-based, lattice-based) map naturally to GPU 32-bit ALUs, making this exploration more valuable as the ecosystem prepares for quantum threats.

1. Privacy is Hygiene​

Ethereum's public ledger ensures transparency, but it comes at a steep cost: every transaction is permanently visible, exposing users' financial histories, preferences, and behaviors. Chain analysis tools can easily link pseudonymous addresses to real-world identities, potentially turning the blockchain into a surveillance machine.

As Vitalik put it, "Privacy is not a feature, but hygiene." It is a fundamental requirement for a safe decentralized system that people are willing to adopt for everyday use.

privacy-is-hygiene

Delegating ZK proof generation to servers undermines this hygiene. While server-side proving is fast and convenient, it requires sharing raw inputs with third parties. Imagine handing your bank statement to a stranger to "anonymize" it for you. If a server sees your IP or, even worse, your transaction details, privacy is compromised regardless of the proof's validity. Though recent studies explore private delegation of provers 1, true sovereignty requires client-side proving: users generate proofs on their own devices, keeping data private from the start.

This is especially critical for everyday Ethereum privacy. Think of sending payments, voting in DAOs, or managing identity-related credentials (e.g. health records) without fear of exposure. Without client-side capabilities, privacy-preserving tech remains niche, adopted only by privacy-maximalist geeks. Hence, accelerating proofs on consumer hardware could be the bedrock for creating mass adoption of privacy, making it as seamless as signing a transaction today.

2. GPU Acceleration: A Multi-Phase Necessity for Client Proving​

Committing resources to client-side GPU acceleration for ZKP is both a short-term and long-term opportunity for Ethereum's privacy landscape. GPUs excel at parallel computations, aligning perfectly with core primitives that could be used in privacy-preserving techs like ZKP and FHE, and client devices (phones, laptops) increasingly feature growing GPU capabilities. This could reduce proving times to interactive levels, fostering mass adoption.

Current Status and Progress​

Although client-side proving is a reality, the user experience is still catching up. CSP benchmarks from ethproofs.org show that while consumer devices can now generate proofs in seconds, the process often takes longer than 100ms. For scenarios requiring real-time experience, like payments or some DeFi applications, this delay creates noticeable friction that hinders adoption.

csp-benchmark
CSP benchmarks from ethproofs.org 5. Snapshot taken on January 19, 2026

Several zkVM projects working on real-time proving have leveraged server-side GPUs (e.g. CUDA on RTX-5090) for ~79x improvement on average proving times, according to site metrics from Jan 28, 2025 to Jan 23, 2026, validating the potential of GPU acceleration for proving.

On the client side, though still in the early stages of PoC and exploration, several projects highlight potential:

  • Ingonyama ICICLE Metal: Optimizes ZK primitives such as MSM and NTT for Apple's Metal API, achieving up to 5x acceleration on iOS/macOS GPUs (v3.6 release detailed in their blog post).
  • zkMopro Metal MSM v2: Explores MSM acceleration on Apple GPUs, improved 40-100x over v1. For details, check this write-up. Building on ZPrize 2023 winners Tal and Koh's WebGPU innovations (inspired by their implementation) 6.
  • Ligetron: Leverages WebGPU for faster SHA-256 and NTT operations, enabling cross-platform ZK both natively and in browsers.

Broader efforts from ZPrize and Geometry.xyz underscore growing momentum, though protocol integration remains limited 78.

Opportunities for Acceleration​

Several ZK primitives are inherently parallelizable, making GPUs a natural fit:

  • MSM (Multi-Scalar Multiplication): Sums scalar multiplications on elliptic curves; parallel via independent additions, bottleneck in elliptic curve-related schemes.
  • NTT (Number Theoretic Transform): A fast algorithm for polynomial multiplication similar to FFT but over finite fields; parallel via butterfly ops, core to polynomial operations in many schemes.
  • Polynomial Evaluation and Matrix-Vector Multiplication: Computes polynomial values at points or matrix-vector products; high-throughput on GPU shaders via SIMD parallelism.
  • Merkle Tree Commitments: Builds hashed tree structures for efficient verification; parallel-friendly for batch processing and hashing.

Additionally, building blocks in interactive oracle proofs (IOPs), such as the sumcheck protocol 9, which reduces multivariate polynomial sums to univariate checks, benefit from massive parallelism in tasks such as summing large datasets or verifying constraints. While promising for GPU acceleration in schemes like WHIR 10 or GKR-based systems 11, sumcheck is not currently the primary bottleneck in most polynomial commitment schemes (PCS).

These primitives map directly to bottlenecks in popular PCS, as shown in the table below.

PCS TypeTypical SchemesFamily (Hardness Assumption)Primary Prover BottleneckAcceleration PotentialPQ Secure
KZG 12Groth16, PlonK, LibraPairing-based (-SDH)MSMModerate: Memory-bandwidth limitedNo
IPA 13Halo2, Bulletproofs, HyraxDiscrete Log (DL)MSMModerate: Parallel EC additionsNo
Hyrax 14GKR-based SNARKsDiscrete Log (DL)MSMModerate: Similar to IPA but multilinearNo
LaBRADOR 15LaBRADOR-based SNARKsLattice-based (SIS / LWE)NTT, Matrix-Vector OpsHigh: Fast small-integer arithmeticYes
FRI 16 / STIR 17STARKs, Plonky2Hash-based (CRHF)Hashing, NTTHigh: Extremely parallel throughputYes
WHIR 10Multivariate SNARKsHash-based (CRHF)HashingHigh: Extremely parallel throughputYes
Basefold 18Basefold-SNARKsHash-based (CRHF)Linear Encoding & HashingHigh: Field-agnostic parallel encodingYes
Brakedown 19Binius, OrionHash-based (CRHF)Linear EncodingHigh: Bit-slicing (SIMD)Yes

Table 1: ZK primitives mapped to PCS bottlenecks and GPU potential

Moreover, VOLE-based ZK proving systems, such as QuickSilver 20, Wolverine 21, and Mac'n'Cheese 22, utilize vector oblivious linear evaluation (VOLE) to construct efficient homomorphic commitments. These act as PCS based on symmetric cryptography or learning parity with noise (LPN) assumptions. The systems are post-quantum secure. Their main prover bottlenecks are VOLE extensions, hashing, and linear operations, which make them well-suited for GPU acceleration through parallel correlation generation and batch processing.

In the short term, primitives related to ECC (e.g. MSM in pairing-based schemes) are suitable for accelerating existing, well-adopted proving systems like Groth16 or those using KZG commitments, providing immediate performance gains for current Ethereum applications.

Quantum preparedness adds urgency for the long term: schemes on smaller fields (e.g. 31-bit fields like Mersenne 31, Baby Bear, or Koala Bear 23) align better with GPU native words (32-bit), yielding higher throughput. Field-Ops Benchmarks 4 confirm this. Under the same settings (not optimal for max performance but for fairness of experiment), smaller fields like M31 achieve over 100 Gops/s on client GPUs, compared to <1 Gops/s for larger ones like BN254.

OperationMetal GOP/sWebGPU GOP/sRatio
u32_add264.2250.11.06x
u64_add177.5141.11.26x
m31_field_add146.0121.71.20x
m31_field_mul112.057.91.93x
bn254_field_add7.91.07.64x
bn254_field_mul0.630.087.59x

As quantum tech advances, exploration related to PQ primitives (e.g. lattice-based or hash-based operations) will drive mid-to-long-term client-side proving advancements, ensuring resilience against quantum threats like "Harvest Now, Decrypt Later" (HNDL) attacks, as mentioned in the Federal Reserve HNDL Paper and underscored by the Ethereum Foundation's long-term quantum strategy, which is a critical factor if we are going to defend people's privacy on a daily-life scale.

3. Challenges: Bridging the Gap to Everyday Privacy​

Despite progress, some hurdles remain between the current status and everyday usability.

3.1 Fragmented Implementation​

  • No standard crypto library exists for client-side GPUs, forcing developers to reinvent wheels from scratch, which is often not fully optimized.
  • Lack of State-of-the-Art (SoTA) references for new explorations, leading to duplicated efforts.
  • Inconsistent benchmarking: metrics like performance, I/O overhead, peak memory, and thermal/power traces are rarely standardized, complicating comparisons. Luckily, PSE's client-side proving team is improving this 5.

3.2 Limited Quantum-Resistant Support​

Most GPU accelerations have focused on PCS related to elliptic-curve cryptography (ECC) like IPA, Hyrax, and KZG (pairing-based). All are vulnerable to quantum attacks via Shor's algorithm. These operate on larger fields (e.g. 254-bit), inefficient for GPUs' 32-bit native operations, and schemes like Groth16 face theoretical acceleration upper bounds, as analyzed in Ingonyama's blog post on hardware acceleration for ZKP 24. On the other hand, PQ schemes such as those based on lattices or hashes (e.g. FRI variants) are underexplored on client GPUs but offer greater parallelism.

3.3 Device-Specific Constraints​

Client devices differ vastly from servers: limited resources, shared GPU duties (e.g. graphics rendering), and thermal risks. Blindly offloading to GPUs can cause crashes or battery drain 25 26. Hybrid CPU-GPU approaches, inspired by Vitalik's Glue and Coprocessor architecture, need further exploration. Key unknowns include:

  • Task dispatching hyperparameters.
  • Caching in unified memory. Check Ingonyama's Metal PoC for zero-cost CPU-GPU transfers.
  • Balancing operations: GPUs for parallelism, CPUs for sequential tasks.
Apple&#39;s UMA
Apple GPUs have the unified memory model in which the CPU and the GPU share system memory

4. PSE's Roadmap for GPU Acceleration​

To achieve client-side GPU acceleration's full potential, we propose a structured roadmap focused on collaboration and sustainability:

  1. Build Standard Cryptography GPU Libraries for ZK

    • Mirror Arkworks's success in Rust zkSNARKs: Create modular, reusable libs optimized for client GPUs (e.g. low RAM, sustained performance) 27.
    • Prioritize PQ foundations to enable HNDL-resistant solutions. For example, lattice-based primitives like NTT that scale with GPU parallelism 28.
    • Make it community-owned, involving Ethereum, ZK, and privacy ecosystems for joint development, accelerating iteration and adoption in projects like mobile digital wallets.
  2. Develop Best-Practice References

    • Integrate GPU acceleration into client-side suitable protocols, including at least one PQ scheme and mainstream ones like Plonky3 29 or Jolt 30.
    • Optimize for mobile, tuning for sustained performance over peaks and avoiding thermal throttling via hybrid CPU-GPU coordination.
    • Create demo protocols as end-to-end references running on real devices with GPU boosts, serving as "how-to" guides for adopting standard libs.

This path transitions from siloed projects to ecosystem-wide tools, paving the way for explorations in sections like our starting points below.

5. Starting Points​

zkSecurity's WebGPU overview highlights its constraints versus native APIs like Metal or Vulkan. For example, limited integer support and abstraction overheads.

To validate, a PoC was conducted to compare field operations (M31 vs. BN254) across APIs 4. Key findings:

  • u64 Emulation Overhead: Metal's native 64-bit support edges WebGPU (1.26x slower due to u32 emulation), compounding on complex ops.
  • Field Size vs. Throughput: Smaller fields shine. M31 hits 100+ Gops/s; BN254 <1 Gops/s (favoring PQ schemes).
  • Complexity Amplifies Gaps: Simple u32 ops show parity (1.06x); advanced arithmetic like Montgomery multiplication widens to 7x for BN254.

Start with native APIs first, such as Metal for iOS (sustainable boosts), then WebGPU for cross-platform reach. This prioritizes real-world viability over premature optimization.

6. Conclusion​

Client-side GPU acceleration for ZKPs represents both immediate and long-term opportunities for Ethereum privacy, potentially improving UX for adopting privacy-preserving tech and enabling quantum-secure daily-life use cases like private payments. By addressing fragmentation, embracing PQ schemes, and optimizing for mobile devices, we can make privacy "hygiene" for everyone (from casual users to privacy-maximalists). We believe that with collaborative efforts from existing players and the broader community, everyday Ethereum privacy is within reach.

Footnotes​

  1. Kasra Abbaszadeh, Hossein Hafezi, Jonathan Katz, & Sarah Meiklejohn. (2025). Single-Server Private Outsourcing of zk-SNARKs. Cryptology ePrint Archive. https://eprint.iacr.org/2025/2113 ↩ ↩2

  2. Takamichi Tsutsumi. (2025). TEE based private proof delegation. https://pse.dev/blog/tee-based-ppd ↩

  3. Takamichi Tsutsumi. (2025). Constant-Depth NTT for FHE-Based Private Proof Delegation. https://pse.dev/blog/const-depth-ntt-for-fhe-based-ppd ↩

  4. Field-Ops Benchmarks. GitHub. https://github.com/moven0831/field-ops-benchmarks ↩ ↩2 ↩3

  5. Proving Backends Benchmarks by Client-side Proving Team from PSE. https://ethproofs.org/csp-benchmarks ↩ ↩2

  6. ZPrize 2023 Entry: Tal and Koh's WebGPU MSM Implementation. GitHub. https://github.com/z-prize/2023-entries/tree/main/prize-2-msm-wasm/webgpu-only/tal-derei-koh-wei-jie ↩

  7. ZPrize. (2023). Announcing the 2023 ZPrize Winners. https://www.zprize.io/blog/announcing-the-2023-zprize-winners ↩

  8. Geometry: Curve Arithmetic Implementation in Metal. GitHub. https://github.com/geometryxyz/msl-secp256k1 ↩

  9. Carsten Lund, Lance Fortnow, Howard Karloff, & Noam Nisan. (1992). Algebraic methods for interactive proof systems. Journal of the ACM (JACM). https://dl.acm.org/doi/10.1145/146585.146605 ↩

  10. Gal Arnon, Alessandro Chiesa, Giacomo Fenzi, & Eylon Yogev. (2024). WHIR: Reed–Solomon Proximity Testing with Super-Fast Verification. Cryptology ePrint Archive. https://eprint.iacr.org/2024/1586 ↩ ↩2

  11. Shafi Goldwasser, Yael Tauman Kalai, & Guy N. Rothblum. (2008). Delegating computation: interactive proofs for muggles. In Proceedings of the fortieth annual ACM symposium on Theory of computing. https://dl.acm.org/doi/10.1145/1374376.1374396 ↩

  12. Aniket Kate, Gregory M. Zaverucha, & Ian Goldberg. (2010). Constant-Size Commitments to Polynomials and Their Applications. In Advances in Cryptology - ASIACRYPT 2010. Springer. https://link.springer.com/chapter/10.1007/978-3-642-17373-8_11 ↩

  13. Jonathan Bootle, Andrea Cerulli, Pyrros Chaidos, Jens Groth, & Christophe Petit. (2016). Efficient Zero-Knowledge Arguments for Arithmetic Circuits in the Discrete Log Setting. Cryptology ePrint Archive. https://eprint.iacr.org/2016/263 ↩

  14. Riad S. Wahby, Ioanna Tzialla, abhi shelat, Justin Thaler, & Michael Walfish. (2017). Doubly-efficient zkSNARKs without trusted setup. Cryptology ePrint Archive. https://eprint.iacr.org/2017/1132 ↩

  15. Ward Beullens & Gregor Seiler. (2022). LaBRADOR: Compact Proofs for R1CS from Module-SIS. Cryptology ePrint Archive. https://eprint.iacr.org/2022/1341 ↩

  16. Eli Ben-Sasson, Iddo Bentov, Yinon Horesh, & Michael Riabzev. (2018). Scalable, transparent, and post-quantum secure computational integrity. Cryptology ePrint Archive. https://eprint.iacr.org/2018/046 ↩

  17. Gal Arnon, Alessandro Chiesa, Giacomo Fenzi, & Eylon Yogev. (2024). STIR: Reed–Solomon Proximity Testing with Fewer Queries. Cryptology ePrint Archive. https://eprint.iacr.org/2024/390 ↩

  18. Hadas Zeilberger, Binyi Chen, & Ben Fisch. (2023). BaseFold: Efficient Field-Agnostic Polynomial Commitment Schemes from Foldable Codes. Cryptology ePrint Archive. https://eprint.iacr.org/2023/1705 ↩

  19. Alexander Golovnev, Jonathan Lee, Srinath Setty, Justin Thaler, & Riad S. Wahby. (2021). Brakedown: Linear-time and field-agnostic SNARKs for R1CS. Cryptology ePrint Archive. https://eprint.iacr.org/2021/1043 ↩

  20. Kang Yang, Pratik Sarkar, Chenkai Weng, & Xiao Wang. (2021). QuickSilver: Efficient and Affordable Zero-Knowledge Proofs for Circuits and Polynomials over Any Field. Cryptology ePrint Archive. https://eprint.iacr.org/2021/076 ↩

  21. Chenkai Weng, Kang Yang, Jonathan Katz, & Xiao Wang. (2020). Wolverine: Fast, Scalable, and Communication-Efficient Zero-Knowledge Proofs for Boolean and Arithmetic Circuits. Cryptology ePrint Archive. https://eprint.iacr.org/2020/925 ↩

  22. Carsten Baum, Alex J. Malozemoff, Marc B. Rosen, & Peter Scholl. (2020). Mac'n'Cheese: Zero-Knowledge Proofs for Boolean and Arithmetic Circuits with Nested Disjunctions. Cryptology ePrint Archive. https://eprint.iacr.org/2020/1410 ↩

  23. Voidkai. Efficient Prime Fields for Zero-knowledge proof. HackMD. https://hackmd.io/@Voidkai/BkNX3xUZA ↩

  24. Ingonyama. (2023, September 27). Revisiting Paradigm’s “Hardware Acceleration for Zero Knowledge Proofs”. Medium. https://medium.com/@ingonyama/revisiting-paradigms-hardware-acceleration-for-zero-knowledge-proofs-5dffacdc24b4 ↩

  25. "GPU in Your Pockets", zkID Days Talk at Devconnect 2025. https://streameth.org/6918e24caaaed07b949bbdd1/playlists/69446a85e505fdb0fa31a760 ↩

  26. Benoit-Cattin, T., Velasco-Montero, D., & Fernández-Berni, J. (2020). Impact of Thermal Throttling on Long-Term Visual Inference in a CPU-Based Edge Device. Electronics, 9(12), 2106. https://doi.org/10.3390/electronics9122106 ↩

  27. Arkworks. https://arkworks.rs/ ↩

  28. Jillian Mascelli & Megan Rodden. (2025, September). “Harvest Now Decrypt Later”: Examining Post-Quantum Cryptography and the Data Privacy Risks for Distributed Ledger Networks. Federal Reserve Board. https://www.federalreserve.gov/econres/feds/files/2025093pap.pdf ↩

  29. Plonky3. GitHub. https://github.com/Plonky3/Plonky3 ↩

  30. Jolt. GitHub. https://github.com/a16z/jolt ↩