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
399 lines
14 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|