synor/sdk/ruby/examples/zk_example.rb
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

345 lines
9.3 KiB
Ruby

# frozen_string_literal: true
#
# Synor ZK SDK Examples for Ruby
#
# Demonstrates zero-knowledge proof operations:
# - Circuit compilation (Circom)
# - Proof generation and verification
# - Multiple proving systems (Groth16, PLONK, STARK)
# - Recursive proof composition
# - Trusted setup ceremonies
#
require 'securerandom'
require 'synor/zk'
class ZkExample
def initialize(zk)
@zk = zk
end
def run_circuit_example
puts '=== Circuit Compilation ==='
# Simple Circom circuit: prove knowledge of factors
circom_code = <<~CIRCOM
pragma circom 2.1.0;
template Multiplier() {
signal input a;
signal input b;
signal output c;
c <== a * b;
}
component main = Multiplier();
CIRCOM
# Compile the circuit
puts 'Compiling circuit...'
circuit = @zk.circuits.compile(
code: circom_code,
language: :circom
)
puts 'Circuit compiled:'
puts " Circuit ID: #{circuit.circuit_id}"
puts " Constraints: #{circuit.constraints}"
puts " Public inputs: #{circuit.public_inputs}"
puts " Private inputs: #{circuit.private_inputs}"
puts " Outputs: #{circuit.outputs}"
# Get circuit info
info = @zk.circuits.get(circuit.circuit_id)
puts "\nCircuit info:"
puts " Name: #{info.name}"
puts " Version: #{info.version}"
puts " Wires: #{info.wire_count}"
puts " Labels: #{info.label_count}"
# List available circuits
circuits = @zk.circuits.list
puts "\nAvailable circuits: #{circuits.length}"
circuits.first(3).each do |c|
puts " #{c.circuit_id}: #{c.name} (#{c.constraints} constraints)"
end
puts
end
def run_groth16_example
puts '=== Groth16 Proving System ==='
circuit_id = 'multiplier-v1'
# Generate proving/verification keys (trusted setup)
puts 'Generating keys...'
keys = @zk.groth16.setup(circuit_id)
puts 'Keys generated:'
puts " Proving key size: #{keys.proving_key.length} bytes"
puts " Verification key size: #{keys.verification_key.length} bytes"
# Prepare witness (private inputs)
witness = { 'a' => '3', 'b' => '7' }
# Generate proof
puts "\nGenerating proof..."
proof = @zk.groth16.prove(
circuit_id: circuit_id,
witness: witness,
proving_key: keys.proving_key
)
puts 'Proof generated:'
puts " Proof size: #{proof.proof_bytes.length} bytes"
puts " Public signals: #{proof.public_signals.length}"
puts " Proving time: #{proof.proving_time_ms}ms"
# Verify proof
puts "\nVerifying proof..."
verified = @zk.groth16.verify(
proof: proof.proof_bytes,
public_signals: proof.public_signals,
verification_key: keys.verification_key
)
puts "Verification result: #{verified}"
# Export proof for on-chain verification
solidity_calldata = @zk.groth16.export_calldata(proof)
puts "\nSolidity calldata: #{solidity_calldata[0, 100]}..."
puts
end
def run_plonk_example
puts '=== PLONK Proving System ==='
circuit_id = 'multiplier-v1'
# PLONK uses universal trusted setup
puts 'Getting universal setup...'
srs = @zk.plonk.get_universal_setup(14) # 2^14 constraints
puts "SRS loaded: #{srs.length} bytes"
# Generate circuit-specific keys
puts "\nGenerating circuit keys..."
keys = @zk.plonk.setup(circuit_id, srs)
puts 'Keys generated'
# Generate proof
witness = { 'a' => '5', 'b' => '9' }
puts "\nGenerating PLONK proof..."
proof = @zk.plonk.prove(
circuit_id: circuit_id,
witness: witness,
proving_key: keys.proving_key
)
puts 'Proof generated:'
puts " Proof size: #{proof.proof_bytes.length} bytes"
puts " Proving time: #{proof.proving_time_ms}ms"
# Verify proof
verified = @zk.plonk.verify(
proof: proof.proof_bytes,
public_signals: proof.public_signals,
verification_key: keys.verification_key
)
puts "Verification result: #{verified}"
# Compare with Groth16
puts "\nPLONK advantages:"
puts ' - Universal trusted setup'
puts ' - Larger proofs (~2.5 KB vs ~200 bytes)'
puts ' - Faster proving for some circuits'
puts
end
def run_stark_example
puts '=== STARK Proving System ==='
circuit_id = 'multiplier-v1'
# STARKs don't need trusted setup
puts 'Configuring STARK parameters...'
config = {
field_size: 256,
hash_function: :poseidon,
blowup_factor: 8,
num_queries: 30,
folding_factor: 8
}
# Generate proof
witness = { 'a' => '11', 'b' => '13' }
puts "\nGenerating STARK proof..."
proof = @zk.stark.prove(
circuit_id: circuit_id,
witness: witness,
config: config
)
puts 'Proof generated:'
puts " Proof size: #{proof.proof_bytes.length} bytes"
puts " Proving time: #{proof.proving_time_ms}ms"
puts " FRI layers: #{proof.fri_layers}"
# Verify proof
puts "\nVerifying STARK proof..."
verified = @zk.stark.verify(
proof: proof.proof_bytes,
public_signals: proof.public_signals,
config: config
)
puts "Verification result: #{verified}"
# Compare with SNARKs
puts "\nSTARK advantages:"
puts ' - No trusted setup needed'
puts ' - Post-quantum secure'
puts ' - Larger proofs (~100 KB)'
puts ' - Faster proving for complex computations'
puts
end
def run_recursive_example
puts '=== Recursive Proof Composition ==='
# Create inner proofs
puts 'Generating inner proofs...'
inner_proofs = []
(1..3).each do |i|
witness = { 'a' => i.to_s, 'b' => (i + 1).to_s }
proof = @zk.recursive.prove_inner(
circuit_id: 'multiplier-v1',
witness: witness,
level: 0
)
inner_proofs << proof
puts " Inner proof #{i} generated"
end
# Aggregate proofs recursively
puts "\nAggregating proofs..."
aggregated_proof = @zk.recursive.aggregate(
proofs: inner_proofs,
aggregation_circuit: 'recursive-aggregator-v1'
)
puts 'Aggregated proof:'
puts " Proof size: #{aggregated_proof.proof_bytes.length} bytes"
puts " Proofs aggregated: #{aggregated_proof.proofs_aggregated}"
puts " Recursion depth: #{aggregated_proof.recursion_depth}"
# Verify aggregated proof (verifies all inner proofs at once)
puts "\nVerifying aggregated proof..."
verified = @zk.recursive.verify_aggregated(aggregated_proof)
puts "Verification result: #{verified}"
# Use cases
puts "\nRecursive proof use cases:"
puts ' - Rollup batch verification'
puts ' - Incremental computation proofs'
puts ' - Cross-chain state proofs'
puts
end
def run_ceremony_example
puts '=== Trusted Setup Ceremony ==='
# List active ceremonies
ceremonies = @zk.ceremony.list(:active)
puts "Active ceremonies: #{ceremonies.length}"
ceremonies.first(3).each do |ceremony|
puts "\n #{ceremony.ceremony_id}:"
puts " Circuit: #{ceremony.circuit_id}"
puts " Participants: #{ceremony.participant_count}"
puts " Current round: #{ceremony.current_round}"
puts " Status: #{ceremony.status}"
end
# Create a new ceremony
puts "\nCreating new ceremony..."
new_ceremony = @zk.ceremony.create(
circuit_id: 'new-circuit-v1',
min_participants: 10,
max_participants: 100,
round_duration: 3600, # 1 hour per round
verify_contributions: true
)
puts 'Ceremony created:'
puts " Ceremony ID: #{new_ceremony.ceremony_id}"
puts " Join URL: #{new_ceremony.join_url}"
# Participate in a ceremony
puts "\nParticipating in ceremony..."
# Generate entropy
entropy = SecureRandom.random_bytes(32)
contribution = @zk.ceremony.contribute(
ceremony_id: new_ceremony.ceremony_id,
entropy: entropy
)
puts 'Contribution made:'
puts " Contribution ID: #{contribution.contribution_id}"
puts " Position: #{contribution.position}"
puts " Hash: #{contribution.hash}"
# Verify a contribution
puts "\nVerifying contribution..."
valid = @zk.ceremony.verify_contribution(contribution.contribution_id)
puts "Contribution valid: #{valid}"
# Get ceremony transcript (for auditability)
transcript = @zk.ceremony.get_transcript(new_ceremony.ceremony_id)
puts "\nCeremony transcript:"
puts " Total contributions: #{transcript.contributions.length}"
puts " Start time: #{transcript.start_time}"
puts " Final hash: #{transcript.final_hash.empty? ? 'pending' : transcript.final_hash}"
puts
end
end
# Main execution
if __FILE__ == $PROGRAM_NAME
# Initialize client
api_key = ENV.fetch('SYNOR_API_KEY', 'your-api-key')
config = Synor::Zk::Config.new(
api_key: api_key,
endpoint: 'https://zk.synor.io/v1',
timeout: 120, # ZK operations can be slow
retries: 3,
debug: false,
default_proving_system: :groth16,
prove_timeout: 300,
verify_timeout: 30
)
zk = Synor::Zk::Client.new(config)
example = ZkExample.new(zk)
begin
# Check service health
healthy = zk.health_check
puts "Service healthy: #{healthy}\n\n"
# Run examples
example.run_circuit_example
example.run_groth16_example
example.run_plonk_example
example.run_stark_example
example.run_recursive_example
example.run_ceremony_example
rescue StandardError => e
warn "Error: #{e.message}"
exit 1
end
end