Skip to main content

Nethereum.ZkProofs

NuGet: Nethereum.ZkProofs | Source: src/Nethereum.ZkProofs/ Provider-agnostic interfaces and models for zero-knowledge proof generation and verification in .NET. This package defines the core abstractions that all Nethereum ZK proof providers implement.

Installation

dotnet add package Nethereum.ZkProofs

Core Interfaces

IZkProofProvider

The central abstraction for proof generation. All providers (browser-based, native, HTTP) implement this interface:

IZkProofProvider provider = ...; // SnarkjsBlazorProvider, RapidSnarkProofProvider, HttpZkProofProvider

var result = await provider.FullProveAsync(new ZkProofRequest
{
CircuitWasm = wasmBytes,
CircuitZkey = zkeyBytes,
InputJson = "{\"nullifier\": \"12345\", \"secret\": \"67890\"}"
});

Console.WriteLine($"Proof: {result.ProofJson}");
Console.WriteLine($"Public signals: {string.Join(", ", result.PublicSignals)}");

ICircuitArtifactSource

Abstracts how circuit artifacts (WASM binaries, proving keys) are loaded:

// From filesystem
ICircuitArtifactSource source = new FileCircuitArtifactSource("./circuits");
byte[] wasm = await source.GetWasmAsync("commitment");
byte[] zkey = await source.GetZkeyAsync("commitment");

// From memory (pre-loaded bytes)
ICircuitArtifactSource embedded = new EmbeddedCircuitArtifactSource(wasmBytes, zkeyBytes);

// From embedded resources (e.g., Nethereum.PrivacyPools.Circuits)
var privacyPools = new PrivacyPoolCircuitSource();
byte[] wasm = await privacyPools.GetWasmAsync("commitment");

ICircuitGraphSource

For native witness generation, circuits can be compiled to a graph format (.graph.bin) instead of WASM:

ICircuitGraphSource graphSource = ...;
if (graphSource.HasGraph("commitment"))
{
byte[] graphData = graphSource.GetGraphData("commitment");
// Pass to WitnessCalculator.CalculateWitness(graphData, inputJson)
}

Models

ZkProofRequest

Input model for proof generation:

PropertyTypeDescription
CircuitWasmbyte[]WebAssembly circuit binary
CircuitZkeybyte[]Proving key (zkey) binary
InputJsonstringJSON-serialized circuit inputs
WitnessBytesbyte[]Pre-computed witness (.wtns) for native providers
CircuitGraphbyte[]Circuit graph data for native witness generation
CircuitNamestringCircuit identifier
SchemeZkProofSchemeProof scheme (default: Groth16)

ZkProofResult

Output model with parsed proof data:

ZkProofResult result = await provider.FullProveAsync(request);

// JSON representations
string proofJson = result.ProofJson; // {"pi_a": [...], "pi_b": [...], "pi_c": [...]}
string signalsJson = result.PublicSignalsJson; // ["12345", "67890", ...]

// Parsed public signals as BigInteger[]
BigInteger commitmentHash = result.PublicSignals[0];
BigInteger nullifierHash = result.PublicSignals[1];

Factory method for creating results from JSON:

var result = ZkProofResult.BuildFromJson(ZkProofScheme.Groth16, proofJson, publicSignalsJson);

ZkProofScheme

public enum ZkProofScheme
{
Unknown = 0,
Groth16 = 1,
Plonk = 2,
Fflonk = 3,
Stark = 4
}

Providers

Built-in: HttpZkProofProvider

Delegates proof generation to a remote HTTP endpoint:

var httpClient = new HttpClient();
var provider = new HttpZkProofProvider(httpClient, "https://prover.example.com/prove");

var result = await provider.FullProveAsync(new ZkProofRequest
{
CircuitWasm = wasmBytes,
CircuitZkey = zkeyBytes,
InputJson = inputJson
});

External Providers

PackageProviderPlatformDescription
Nethereum.ZkProofs.Snarkjs.BlazorSnarkjsBlazorProviderBrowser (Blazor WASM)JS interop with snarkjs
Nethereum.ZkProofs.RapidSnarkRapidSnarkProofProviderDesktop/ServerNative C++ via P/Invoke
Nethereum.ZkProofsVerifierN/A (verification only)All platformsPure C# BN128 Groth16 verifier

Groth16 Utilities

Convert proof JSON to Solidity-compatible format for on-chain verification:

using Nethereum.ZkProofs.Groth16;

var proof = Groth16ProofConverter.ParseProofJson(result.ProofJson);
var (pA, pB, pC) = Groth16ProofConverter.ToSolidityProof(proof);

// pA, pB, pC are ready for Solidity Groth16Verifier.verifyProof(pA, pB, pC, publicSignals)

Circuit Artifact Locator

Resolves filesystem paths following the standard circuit directory layout:

var locator = new CircuitArtifactLocator("./circuits");

string wasmPath = locator.GetWasmPath("commitment"); // ./circuits/commitment/commitment.wasm
string zkeyPath = locator.GetZkeyPath("commitment"); // ./circuits/commitment/commitment.zkey
string vkPath = locator.GetVkPath("commitment"); // ./circuits/commitment/commitment_vk.json

if (locator.HasArtifacts("commitment"))
{
// Both WASM and zkey exist
}

Supported Frameworks

net451, net461, netstandard2.0, net6.0, net8.0, net9.0, net10.0