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
345 lines
9.3 KiB
Ruby
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
|