synor/sdk/kotlin/examples/ZkExample.kt
Gulshan Yadav e169c492aa Add Swift examples for Synor DEX, IBC, and ZK SDKs
- Introduced DexExample.swift demonstrating decentralized exchange operations including spot trading, perpetual futures, liquidity provision, order book management, and portfolio tracking.
- Added IbcExample.swift showcasing inter-blockchain communication operations such as cross-chain transfers, channel management, packet handling, and relayer operations.
- Created ZkExample.swift illustrating zero-knowledge proof operations including circuit compilation, proof generation and verification, and trusted setup ceremonies.
2026-01-28 14:30:19 +05:30

369 lines
11 KiB
Kotlin

package io.synor.examples
import io.synor.zk.*
import io.synor.zk.types.*
import kotlinx.coroutines.runBlocking
/**
* Synor ZK SDK Examples for Kotlin
*
* Demonstrates zero-knowledge proof operations:
* - Circuit compilation (Circom)
* - Proof generation and verification
* - Multiple proving systems (Groth16, PLONK, STARK)
* - Recursive proof composition
* - Trusted setup ceremonies
*/
fun main() = runBlocking {
// Initialize client
val config = ZkConfig(
apiKey = System.getenv("SYNOR_API_KEY") ?: "your-api-key",
endpoint = "https://zk.synor.io/v1",
timeout = 120_000, // ZK operations can be slow
retries = 3,
debug = false,
defaultProvingSystem = ProvingSystem.GROTH16,
proveTimeout = 300_000,
verifyTimeout = 30_000
)
val zk = SynorZk(config)
try {
// Check service health
val healthy = zk.healthCheck()
println("Service healthy: $healthy\n")
// Run examples
circuitExample(zk)
groth16Example(zk)
plonkExample(zk)
starkExample(zk)
recursiveExample(zk)
ceremonyExample(zk)
} finally {
zk.close()
}
}
suspend fun circuitExample(zk: SynorZk) {
println("=== Circuit Compilation ===")
// Simple Circom circuit: prove knowledge of factors
val circomCode = """
pragma circom 2.1.0;
template Multiplier() {
signal input a;
signal input b;
signal output c;
c <== a * b;
}
component main = Multiplier();
""".trimIndent()
// Compile the circuit
println("Compiling circuit...")
val circuit = zk.circuits.compile(
CircuitSource(
code = circomCode,
language = CircuitLanguage.CIRCOM
)
)
println("Circuit compiled:")
println(" Circuit ID: ${circuit.circuitId}")
println(" Constraints: ${circuit.constraints}")
println(" Public inputs: ${circuit.publicInputs}")
println(" Private inputs: ${circuit.privateInputs}")
println(" Outputs: ${circuit.outputs}")
// Get circuit info
val info = zk.circuits.get(circuit.circuitId)
println("\nCircuit info:")
println(" Name: ${info.name}")
println(" Version: ${info.version}")
println(" Wires: ${info.wireCount}")
println(" Labels: ${info.labelCount}")
// List available circuits
val circuits = zk.circuits.list()
println("\nAvailable circuits: ${circuits.size}")
circuits.take(3).forEach { c ->
println(" ${c.circuitId}: ${c.name} (${c.constraints} constraints)")
}
println()
}
suspend fun groth16Example(zk: SynorZk) {
println("=== Groth16 Proving System ===")
// Use a pre-compiled circuit
val circuitId = "multiplier-v1"
// Generate proving/verification keys (trusted setup)
println("Generating keys...")
val keys = zk.groth16.setup(circuitId)
println("Keys generated:")
println(" Proving key size: ${keys.provingKey.size} bytes")
println(" Verification key size: ${keys.verificationKey.size} bytes")
// Prepare witness (private inputs)
val witness = mapOf(
"a" to "3",
"b" to "7"
)
// Generate proof
println("\nGenerating proof...")
val proof = zk.groth16.prove(
ProveRequest(
circuitId = circuitId,
witness = witness,
provingKey = keys.provingKey
)
)
println("Proof generated:")
println(" Proof size: ${proof.proofBytes.size} bytes")
println(" Public signals: ${proof.publicSignals}")
println(" Proving time: ${proof.provingTimeMs}ms")
// Verify proof
println("\nVerifying proof...")
val verified = zk.groth16.verify(
VerifyRequest(
proof = proof.proofBytes,
publicSignals = proof.publicSignals,
verificationKey = keys.verificationKey
)
)
println("Verification result: $verified")
// Export proof for on-chain verification
val solidityCalldata = zk.groth16.exportCalldata(proof)
println("\nSolidity calldata: ${solidityCalldata.take(100)}...")
println()
}
suspend fun plonkExample(zk: SynorZk) {
println("=== PLONK Proving System ===")
val circuitId = "multiplier-v1"
// PLONK uses universal trusted setup
println("Getting universal setup...")
val srs = zk.plonk.getUniversalSetup(powersOfTau = 14) // 2^14 constraints
println("SRS loaded: ${srs.size} bytes")
// Generate circuit-specific keys
println("\nGenerating circuit keys...")
val keys = zk.plonk.setup(circuitId, srs)
println("Keys generated")
// Generate proof
val witness = mapOf("a" to "5", "b" to "9")
println("\nGenerating PLONK proof...")
val proof = zk.plonk.prove(
PlonkProveRequest(
circuitId = circuitId,
witness = witness,
provingKey = keys.provingKey
)
)
println("Proof generated:")
println(" Proof size: ${proof.proofBytes.size} bytes")
println(" Proving time: ${proof.provingTimeMs}ms")
// Verify proof
val verified = zk.plonk.verify(
PlonkVerifyRequest(
proof = proof.proofBytes,
publicSignals = proof.publicSignals,
verificationKey = keys.verificationKey
)
)
println("Verification result: $verified")
// Compare with Groth16
println("\nPLONK advantages:")
println(" - Universal trusted setup")
println(" - Larger proofs (~2.5 KB vs ~200 bytes)")
println(" - Faster proving for some circuits")
println()
}
suspend fun starkExample(zk: SynorZk) {
println("=== STARK Proving System ===")
val circuitId = "multiplier-v1"
// STARKs don't need trusted setup
println("Configuring STARK parameters...")
val config = StarkConfig(
fieldSize = 256,
hashFunction = HashFunction.POSEIDON,
blowupFactor = 8,
numQueries = 30,
foldingFactor = 8
)
// Generate proof
val witness = mapOf("a" to "11", "b" to "13")
println("\nGenerating STARK proof...")
val proof = zk.stark.prove(
StarkProveRequest(
circuitId = circuitId,
witness = witness,
config = config
)
)
println("Proof generated:")
println(" Proof size: ${proof.proofBytes.size} bytes")
println(" Proving time: ${proof.provingTimeMs}ms")
println(" FRI layers: ${proof.friLayers}")
// Verify proof
println("\nVerifying STARK proof...")
val verified = zk.stark.verify(
StarkVerifyRequest(
proof = proof.proofBytes,
publicSignals = proof.publicSignals,
config = config
)
)
println("Verification result: $verified")
// Compare with SNARKs
println("\nSTARK advantages:")
println(" - No trusted setup needed")
println(" - Post-quantum secure")
println(" - Larger proofs (~100 KB)")
println(" - Faster proving for complex computations")
println()
}
suspend fun recursiveExample(zk: SynorZk) {
println("=== Recursive Proof Composition ===")
// Create inner proofs
println("Generating inner proofs...")
val innerProofs = mutableListOf<RecursiveProof>()
for (i in 1..3) {
val witness = mapOf("a" to i.toString(), "b" to (i + 1).toString())
val proof = zk.recursive.proveInner(
RecursiveProveRequest(
circuitId = "multiplier-v1",
witness = witness,
level = 0
)
)
innerProofs.add(proof)
println(" Inner proof $i generated")
}
// Aggregate proofs recursively
println("\nAggregating proofs...")
val aggregatedProof = zk.recursive.aggregate(
AggregateRequest(
proofs = innerProofs,
aggregationCircuit = "recursive-aggregator-v1"
)
)
println("Aggregated proof:")
println(" Proof size: ${aggregatedProof.proofBytes.size} bytes")
println(" Proofs aggregated: ${aggregatedProof.proofsAggregated}")
println(" Recursion depth: ${aggregatedProof.recursionDepth}")
// Verify aggregated proof (verifies all inner proofs at once)
println("\nVerifying aggregated proof...")
val verified = zk.recursive.verifyAggregated(aggregatedProof)
println("Verification result: $verified")
// Use cases
println("\nRecursive proof use cases:")
println(" - Rollup batch verification")
println(" - Incremental computation proofs")
println(" - Cross-chain state proofs")
println()
}
suspend fun ceremonyExample(zk: SynorZk) {
println("=== Trusted Setup Ceremony ===")
// List active ceremonies
val ceremonies = zk.ceremony.list(status = CeremonyStatus.ACTIVE)
println("Active ceremonies: ${ceremonies.size}")
ceremonies.take(3).forEach { ceremony ->
println("\n ${ceremony.ceremonyId}:")
println(" Circuit: ${ceremony.circuitId}")
println(" Participants: ${ceremony.participantCount}")
println(" Current round: ${ceremony.currentRound}")
println(" Status: ${ceremony.status}")
}
// Create a new ceremony
println("\nCreating new ceremony...")
val newCeremony = zk.ceremony.create(
CeremonyConfig(
circuitId = "new-circuit-v1",
minParticipants = 10,
maxParticipants = 100,
roundDuration = 3600, // 1 hour per round
verifyContributions = true
)
)
println("Ceremony created:")
println(" Ceremony ID: ${newCeremony.ceremonyId}")
println(" Join URL: ${newCeremony.joinUrl}")
// Participate in a ceremony
println("\nParticipating in ceremony...")
val contribution = zk.ceremony.contribute(
ContributionRequest(
ceremonyId = newCeremony.ceremonyId,
entropy = generateEntropy()
)
)
println("Contribution made:")
println(" Contribution ID: ${contribution.contributionId}")
println(" Position: ${contribution.position}")
println(" Hash: ${contribution.hash}")
// Verify a contribution
println("\nVerifying contribution...")
val valid = zk.ceremony.verifyContribution(contribution.contributionId)
println("Contribution valid: $valid")
// Get ceremony transcript (for auditability)
val transcript = zk.ceremony.getTranscript(newCeremony.ceremonyId)
println("\nCeremony transcript:")
println(" Total contributions: ${transcript.contributions.size}")
println(" Start time: ${transcript.startTime}")
println(" Final hash: ${transcript.finalHash ?: "pending"}")
println()
}
// Helper function to generate random entropy
fun generateEntropy(): ByteArray {
val entropy = ByteArray(32)
java.security.SecureRandom().nextBytes(entropy)
return entropy
}