/** * Synor ZK SDK Examples for C# * * Demonstrates zero-knowledge proof operations: * - Circuit compilation (Circom) * - Proof generation and verification * - Multiple proving systems (Groth16, PLONK, STARK) * - Recursive proof composition * - Trusted setup ceremonies */ using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Threading.Tasks; using Synor.Zk; namespace Synor.Examples; public class ZkExample { private readonly SynorZk _zk; public ZkExample(SynorZk zk) { _zk = zk; } public async Task RunCircuitExample() { Console.WriteLine("=== Circuit Compilation ==="); // Simple Circom circuit: prove knowledge of factors var circomCode = @" pragma circom 2.1.0; template Multiplier() { signal input a; signal input b; signal output c; c <== a * b; } component main = Multiplier(); "; // Compile the circuit Console.WriteLine("Compiling circuit..."); var circuit = await _zk.Circuits.CompileAsync(new CompileRequest { Code = circomCode, Language = CircuitLanguage.Circom }); Console.WriteLine("Circuit compiled:"); Console.WriteLine($" Circuit ID: {circuit.CircuitId}"); Console.WriteLine($" Constraints: {circuit.Constraints}"); Console.WriteLine($" Public inputs: {circuit.PublicInputs}"); Console.WriteLine($" Private inputs: {circuit.PrivateInputs}"); Console.WriteLine($" Outputs: {circuit.Outputs}"); // Get circuit info var info = await _zk.Circuits.GetAsync(circuit.CircuitId); Console.WriteLine("\nCircuit info:"); Console.WriteLine($" Name: {info.Name}"); Console.WriteLine($" Version: {info.Version}"); Console.WriteLine($" Wires: {info.WireCount}"); Console.WriteLine($" Labels: {info.LabelCount}"); // List available circuits var circuits = await _zk.Circuits.ListAsync(); Console.WriteLine($"\nAvailable circuits: {circuits.Count}"); foreach (var c in circuits.GetRange(0, Math.Min(circuits.Count, 3))) { Console.WriteLine($" {c.CircuitId}: {c.Name} ({c.Constraints} constraints)"); } Console.WriteLine(); } public async Task RunGroth16Example() { Console.WriteLine("=== Groth16 Proving System ==="); var circuitId = "multiplier-v1"; // Generate proving/verification keys (trusted setup) Console.WriteLine("Generating keys..."); var keys = await _zk.Groth16.SetupAsync(circuitId); Console.WriteLine("Keys generated:"); Console.WriteLine($" Proving key size: {keys.ProvingKey.Length} bytes"); Console.WriteLine($" Verification key size: {keys.VerificationKey.Length} bytes"); // Prepare witness (private inputs) var witness = new Dictionary { ["a"] = "3", ["b"] = "7" }; // Generate proof Console.WriteLine("\nGenerating proof..."); var proof = await _zk.Groth16.ProveAsync(new ProveRequest { CircuitId = circuitId, Witness = witness, ProvingKey = keys.ProvingKey }); Console.WriteLine("Proof generated:"); Console.WriteLine($" Proof size: {proof.ProofBytes.Length} bytes"); Console.WriteLine($" Public signals: {proof.PublicSignals.Count}"); Console.WriteLine($" Proving time: {proof.ProvingTimeMs}ms"); // Verify proof Console.WriteLine("\nVerifying proof..."); var verified = await _zk.Groth16.VerifyAsync(new VerifyRequest { Proof = proof.ProofBytes, PublicSignals = proof.PublicSignals, VerificationKey = keys.VerificationKey }); Console.WriteLine($"Verification result: {verified}"); // Export proof for on-chain verification var solidityCalldata = await _zk.Groth16.ExportCalldataAsync(proof); Console.WriteLine($"\nSolidity calldata: {solidityCalldata[..Math.Min(solidityCalldata.Length, 100)]}..."); Console.WriteLine(); } public async Task RunPlonkExample() { Console.WriteLine("=== PLONK Proving System ==="); var circuitId = "multiplier-v1"; // PLONK uses universal trusted setup Console.WriteLine("Getting universal setup..."); var srs = await _zk.Plonk.GetUniversalSetupAsync(14); // 2^14 constraints Console.WriteLine($"SRS loaded: {srs.Length} bytes"); // Generate circuit-specific keys Console.WriteLine("\nGenerating circuit keys..."); var keys = await _zk.Plonk.SetupAsync(circuitId, srs); Console.WriteLine("Keys generated"); // Generate proof var witness = new Dictionary { ["a"] = "5", ["b"] = "9" }; Console.WriteLine("\nGenerating PLONK proof..."); var proof = await _zk.Plonk.ProveAsync(new ProveRequest { CircuitId = circuitId, Witness = witness, ProvingKey = keys.ProvingKey }); Console.WriteLine("Proof generated:"); Console.WriteLine($" Proof size: {proof.ProofBytes.Length} bytes"); Console.WriteLine($" Proving time: {proof.ProvingTimeMs}ms"); // Verify proof var verified = await _zk.Plonk.VerifyAsync(new VerifyRequest { Proof = proof.ProofBytes, PublicSignals = proof.PublicSignals, VerificationKey = keys.VerificationKey }); Console.WriteLine($"Verification result: {verified}"); // Compare with Groth16 Console.WriteLine("\nPLONK advantages:"); Console.WriteLine(" - Universal trusted setup"); Console.WriteLine(" - Larger proofs (~2.5 KB vs ~200 bytes)"); Console.WriteLine(" - Faster proving for some circuits"); Console.WriteLine(); } public async Task RunStarkExample() { Console.WriteLine("=== STARK Proving System ==="); var circuitId = "multiplier-v1"; // STARKs don't need trusted setup Console.WriteLine("Configuring STARK parameters..."); var config = new StarkConfig { FieldSize = 256, HashFunction = HashFunction.Poseidon, BlowupFactor = 8, NumQueries = 30, FoldingFactor = 8 }; // Generate proof var witness = new Dictionary { ["a"] = "11", ["b"] = "13" }; Console.WriteLine("\nGenerating STARK proof..."); var proof = await _zk.Stark.ProveAsync(new StarkProveRequest { CircuitId = circuitId, Witness = witness, Config = config }); Console.WriteLine("Proof generated:"); Console.WriteLine($" Proof size: {proof.ProofBytes.Length} bytes"); Console.WriteLine($" Proving time: {proof.ProvingTimeMs}ms"); Console.WriteLine($" FRI layers: {proof.FriLayers}"); // Verify proof Console.WriteLine("\nVerifying STARK proof..."); var verified = await _zk.Stark.VerifyAsync(new StarkVerifyRequest { Proof = proof.ProofBytes, PublicSignals = proof.PublicSignals, Config = config }); Console.WriteLine($"Verification result: {verified}"); // Compare with SNARKs Console.WriteLine("\nSTARK advantages:"); Console.WriteLine(" - No trusted setup needed"); Console.WriteLine(" - Post-quantum secure"); Console.WriteLine(" - Larger proofs (~100 KB)"); Console.WriteLine(" - Faster proving for complex computations"); Console.WriteLine(); } public async Task RunRecursiveExample() { Console.WriteLine("=== Recursive Proof Composition ==="); // Create inner proofs Console.WriteLine("Generating inner proofs..."); var innerProofs = new List(); for (var i = 1; i <= 3; i++) { var witness = new Dictionary { ["a"] = i.ToString(), ["b"] = (i + 1).ToString() }; var proof = await _zk.Recursive.ProveInnerAsync(new RecursiveProveRequest { CircuitId = "multiplier-v1", Witness = witness, Level = 0 }); innerProofs.Add(proof); Console.WriteLine($" Inner proof {i} generated"); } // Aggregate proofs recursively Console.WriteLine("\nAggregating proofs..."); var aggregatedProof = await _zk.Recursive.AggregateAsync(new AggregateRequest { Proofs = innerProofs, AggregationCircuit = "recursive-aggregator-v1" }); Console.WriteLine("Aggregated proof:"); Console.WriteLine($" Proof size: {aggregatedProof.ProofBytes.Length} bytes"); Console.WriteLine($" Proofs aggregated: {aggregatedProof.ProofsAggregated}"); Console.WriteLine($" Recursion depth: {aggregatedProof.RecursionDepth}"); // Verify aggregated proof (verifies all inner proofs at once) Console.WriteLine("\nVerifying aggregated proof..."); var verified = await _zk.Recursive.VerifyAggregatedAsync(aggregatedProof); Console.WriteLine($"Verification result: {verified}"); // Use cases Console.WriteLine("\nRecursive proof use cases:"); Console.WriteLine(" - Rollup batch verification"); Console.WriteLine(" - Incremental computation proofs"); Console.WriteLine(" - Cross-chain state proofs"); Console.WriteLine(); } public async Task RunCeremonyExample() { Console.WriteLine("=== Trusted Setup Ceremony ==="); // List active ceremonies var ceremonies = await _zk.Ceremony.ListAsync(CeremonyStatus.Active); Console.WriteLine($"Active ceremonies: {ceremonies.Count}"); foreach (var ceremony in ceremonies.GetRange(0, Math.Min(ceremonies.Count, 3))) { Console.WriteLine($"\n {ceremony.CeremonyId}:"); Console.WriteLine($" Circuit: {ceremony.CircuitId}"); Console.WriteLine($" Participants: {ceremony.ParticipantCount}"); Console.WriteLine($" Current round: {ceremony.CurrentRound}"); Console.WriteLine($" Status: {ceremony.Status}"); } // Create a new ceremony Console.WriteLine("\nCreating new ceremony..."); var newCeremony = await _zk.Ceremony.CreateAsync(new CreateCeremonyRequest { CircuitId = "new-circuit-v1", MinParticipants = 10, MaxParticipants = 100, RoundDuration = 3600, // 1 hour per round VerifyContributions = true }); Console.WriteLine("Ceremony created:"); Console.WriteLine($" Ceremony ID: {newCeremony.CeremonyId}"); Console.WriteLine($" Join URL: {newCeremony.JoinUrl}"); // Participate in a ceremony Console.WriteLine("\nParticipating in ceremony..."); // Generate entropy var entropy = new byte[32]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(entropy); } var contribution = await _zk.Ceremony.ContributeAsync(new ContributeRequest { CeremonyId = newCeremony.CeremonyId, Entropy = entropy }); Console.WriteLine("Contribution made:"); Console.WriteLine($" Contribution ID: {contribution.ContributionId}"); Console.WriteLine($" Position: {contribution.Position}"); Console.WriteLine($" Hash: {contribution.Hash}"); // Verify a contribution Console.WriteLine("\nVerifying contribution..."); var valid = await _zk.Ceremony.VerifyContributionAsync(contribution.ContributionId); Console.WriteLine($"Contribution valid: {valid}"); // Get ceremony transcript (for auditability) var transcript = await _zk.Ceremony.GetTranscriptAsync(newCeremony.CeremonyId); Console.WriteLine("\nCeremony transcript:"); Console.WriteLine($" Total contributions: {transcript.Contributions.Count}"); Console.WriteLine($" Start time: {transcript.StartTime}"); Console.WriteLine($" Final hash: {(string.IsNullOrEmpty(transcript.FinalHash) ? "pending" : transcript.FinalHash)}"); Console.WriteLine(); } public static async Task Main(string[] args) { // Initialize client var apiKey = Environment.GetEnvironmentVariable("SYNOR_API_KEY") ?? "your-api-key"; var config = new ZkConfig { ApiKey = apiKey, Endpoint = "https://zk.synor.io/v1", Timeout = TimeSpan.FromSeconds(120), // ZK operations can be slow Retries = 3, Debug = false, DefaultProvingSystem = ProvingSystem.Groth16, ProveTimeout = TimeSpan.FromSeconds(300), VerifyTimeout = TimeSpan.FromSeconds(30) }; var zk = new SynorZk(config); var example = new ZkExample(zk); try { // Check service health var healthy = await zk.HealthCheckAsync(); Console.WriteLine($"Service healthy: {healthy}\n"); // Run examples await example.RunCircuitExample(); await example.RunGroth16Example(); await example.RunPlonkExample(); await example.RunStarkExample(); await example.RunRecursiveExample(); await example.RunCeremonyExample(); } catch (Exception ex) { Console.Error.WriteLine($"Error: {ex.Message}"); Environment.Exit(1); } } }