- 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.
369 lines
11 KiB
Kotlin
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
|
|
}
|