synor/sdk/csharp/examples/ZkExample.cs
Gulshan Yadav cf5130d9e4 feat(sdk): Add comprehensive examples for C, C++, C#, and Ruby SDKs
Add example code demonstrating all SDK services (Crypto, DEX, ZK, IBC,
Compiler) for the remaining languages:

- C SDK (5 examples): Using synor_* C API with explicit memory management
- C++ SDK (5 examples): Modern C++17 with RAII and designated initializers
- C# SDK (5 examples): Async/await patterns with .NET conventions
- Ruby SDK (5 examples): Ruby idioms with blocks and symbols

Each example covers:
- Crypto: Hybrid signatures, mnemonics, Falcon, SPHINCS+, KDF, hashing
- DEX: Markets, spot trading, perpetuals, liquidity, portfolio
- ZK: Circuits, Groth16, PLONK, STARK, recursive proofs, ceremonies
- IBC: Chains, channels, transfers, packets, relayer, monitoring
- Compiler: Compilation, optimization, ABI, analysis, validation, security
2026-01-28 14:44:04 +05:30

399 lines
14 KiB
C#

/**
* 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<string, string>
{
["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<string, string>
{
["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<string, string>
{
["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<RecursiveProof>();
for (var i = 1; i <= 3; i++)
{
var witness = new Dictionary<string, string>
{
["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);
}
}
}