synor/sdk/java/examples/ZkExample.java
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

537 lines
21 KiB
Java

package io.synor.examples;
import io.synor.zk.*;
import io.synor.zk.types.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
/**
* Synor ZK SDK Examples for Java
*
* Demonstrates Zero-Knowledge proof operations:
* - Circuit compilation
* - Proof generation and verification
* - Groth16, PLONK, and STARK proving systems
* - Recursive proofs
* - On-chain verification
*/
public class ZkExample {
public static void main(String[] args) throws Exception {
// Initialize client
ZkConfig config = ZkConfig.builder()
.apiKey(System.getenv("SYNOR_API_KEY") != null ?
System.getenv("SYNOR_API_KEY") : "your-api-key")
.endpoint("https://zk.synor.io/v1")
.timeout(120000) // ZK ops can be slow
.retries(3)
.debug(false)
.defaultProvingSystem(ProvingSystem.GROTH16)
.build();
SynorZk zk = new SynorZk(config);
try {
// Check service health
boolean healthy = zk.healthCheck().get();
System.out.println("Service healthy: " + healthy + "\n");
// Run examples
circuitExample(zk);
proofExample(zk);
provingSystemsExample(zk);
recursiveProofExample(zk);
onChainVerificationExample(zk);
setupExample(zk);
} finally {
zk.close();
}
}
static void circuitExample(SynorZk zk) throws Exception {
System.out.println("=== Circuit Compilation ===");
// Circom circuit example: prove knowledge of preimage
String circomCircuit = """
pragma circom 2.1.0;
template HashPreimage() {
signal input preimage;
signal input hash;
// Simplified hash computation (in reality, use proper hash)
signal preimageSquared;
preimageSquared <== preimage * preimage;
// Constrain that hash matches
hash === preimageSquared;
}
component main {public [hash]} = HashPreimage();
""";
// Compile circuit
System.out.println("Compiling Circom circuit...");
CompiledCircuit compiled = zk.circuits().compile(CompileRequest.builder()
.code(circomCircuit)
.format(CircuitFormat.CIRCOM)
.name("hash_preimage")
.provingSystem(ProvingSystem.GROTH16)
.build()).get();
System.out.println("Circuit compiled:");
System.out.println(" Circuit ID: " + compiled.getCircuitId());
System.out.println(" Constraints: " + compiled.getConstraintCount());
System.out.println(" Public inputs: " + compiled.getPublicInputCount());
System.out.println(" Private inputs: " + compiled.getPrivateInputCount());
System.out.println(" Proving key size: " + compiled.getProvingKeySize() + " bytes");
System.out.println(" Verification key size: " + compiled.getVerificationKeySize() + " bytes");
// List circuits
List<Circuit> circuits = zk.circuits().list().get();
System.out.println("\nYour circuits: " + circuits.size());
for (Circuit circuit : circuits) {
System.out.println(" " + circuit.getName() + " (" + circuit.getCircuitId() + ")");
}
// Get circuit details
CircuitDetails details = zk.circuits().get(compiled.getCircuitId()).get();
System.out.println("\nCircuit details:");
System.out.println(" Format: " + details.getFormat());
System.out.println(" Proving system: " + details.getProvingSystem());
System.out.println(" Created: " + details.getCreatedAt());
// Download proving key
byte[] provingKey = zk.circuits().getProvingKey(compiled.getCircuitId()).get();
System.out.println("\nProving key downloaded: " + provingKey.length + " bytes");
// Download verification key
byte[] verificationKey = zk.circuits().getVerificationKey(compiled.getCircuitId()).get();
System.out.println("Verification key downloaded: " + verificationKey.length + " bytes");
System.out.println();
}
static void proofExample(SynorZk zk) throws Exception {
System.out.println("=== Proof Generation ===");
// First, compile a simple circuit
String circuit = """
pragma circom 2.1.0;
template Multiplier() {
signal input a;
signal input b;
signal output c;
c <== a * b;
}
component main {public [c]} = Multiplier();
""";
CompiledCircuit compiled = zk.circuits().compile(CompileRequest.builder()
.code(circuit)
.format(CircuitFormat.CIRCOM)
.name("multiplier")
.provingSystem(ProvingSystem.GROTH16)
.build()).get();
// Generate proof
System.out.println("Generating proof...");
long startTime = System.currentTimeMillis();
Map<String, String> inputs = new HashMap<>();
inputs.put("a", "3");
inputs.put("b", "7");
Proof proof = zk.proofs().generate(GenerateProofRequest.builder()
.circuitId(compiled.getCircuitId())
.inputs(inputs)
.build()).get();
long proofTime = System.currentTimeMillis() - startTime;
System.out.println("Proof generated in " + proofTime + "ms");
System.out.println(" Proof ID: " + proof.getProofId());
System.out.println(" Proof size: " + proof.getProof().length() + " bytes");
System.out.println(" Public signals: " + proof.getPublicSignals());
// Verify proof
System.out.println("\nVerifying proof...");
long verifyStart = System.currentTimeMillis();
boolean isValid = zk.proofs().verify(VerifyRequest.builder()
.circuitId(compiled.getCircuitId())
.proof(proof.getProof())
.publicSignals(proof.getPublicSignals())
.build()).get();
long verifyTime = System.currentTimeMillis() - verifyStart;
System.out.println("Verification completed in " + verifyTime + "ms");
System.out.println(" Valid: " + isValid);
// Verify with wrong public signals (should fail)
System.out.println("\nVerifying with wrong signals...");
boolean invalidResult = zk.proofs().verify(VerifyRequest.builder()
.circuitId(compiled.getCircuitId())
.proof(proof.getProof())
.publicSignals(List.of("42")) // Wrong answer
.build()).get();
System.out.println(" Valid: " + invalidResult + " (expected false)");
// Get proof status
ProofStatus status = zk.proofs().getStatus(proof.getProofId()).get();
System.out.println("\nProof status:");
System.out.println(" State: " + status.getState());
System.out.println(" Verified: " + status.isVerified());
System.out.println(" Created: " + status.getCreatedAt());
// List proofs
List<ProofInfo> proofs = zk.proofs().list(compiled.getCircuitId()).get();
System.out.println("\nProofs for circuit: " + proofs.size());
System.out.println();
}
static void provingSystemsExample(SynorZk zk) throws Exception {
System.out.println("=== Proving Systems Comparison ===");
// Simple circuit for comparison
String circuit = """
pragma circom 2.1.0;
template Comparison() {
signal input x;
signal input y;
signal output sum;
sum <== x + y;
}
component main {public [sum]} = Comparison();
""";
ProvingSystem[] systems = {
ProvingSystem.GROTH16,
ProvingSystem.PLONK,
ProvingSystem.STARK
};
System.out.println("Comparing proving systems:\n");
for (ProvingSystem system : systems) {
System.out.println(system + ":");
// Compile for this system
CompiledCircuit compiled = zk.circuits().compile(CompileRequest.builder()
.code(circuit)
.format(CircuitFormat.CIRCOM)
.name("comparison_" + system.toString().toLowerCase())
.provingSystem(system)
.build()).get();
// Generate proof
long proofStart = System.currentTimeMillis();
Map<String, String> inputs = new HashMap<>();
inputs.put("x", "10");
inputs.put("y", "20");
Proof proof = zk.proofs().generate(GenerateProofRequest.builder()
.circuitId(compiled.getCircuitId())
.inputs(inputs)
.build()).get();
long proofTime = System.currentTimeMillis() - proofStart;
// Verify proof
long verifyStart = System.currentTimeMillis();
zk.proofs().verify(VerifyRequest.builder()
.circuitId(compiled.getCircuitId())
.proof(proof.getProof())
.publicSignals(proof.getPublicSignals())
.build()).get();
long verifyTime = System.currentTimeMillis() - verifyStart;
System.out.println(" Setup: " + compiled.getSetupTime() + "ms");
System.out.println(" Proof time: " + proofTime + "ms");
System.out.println(" Verify time: " + verifyTime + "ms");
System.out.println(" Proof size: " + proof.getProof().length() + " bytes");
System.out.println(" Verification key: " + compiled.getVerificationKeySize() + " bytes");
System.out.println();
}
System.out.println("Summary:");
System.out.println(" Groth16: Smallest proofs, fast verification, trusted setup required");
System.out.println(" PLONK: Universal setup, flexible, moderate proof size");
System.out.println(" STARK: No trusted setup, largest proofs, quantum resistant");
System.out.println();
}
static void recursiveProofExample(SynorZk zk) throws Exception {
System.out.println("=== Recursive Proofs ===");
// Inner circuit
String innerCircuit = """
pragma circom 2.1.0;
template Inner() {
signal input x;
signal output y;
y <== x * x;
}
component main {public [y]} = Inner();
""";
// Compile inner circuit
CompiledCircuit inner = zk.circuits().compile(CompileRequest.builder()
.code(innerCircuit)
.format(CircuitFormat.CIRCOM)
.name("inner_circuit")
.provingSystem(ProvingSystem.GROTH16)
.build()).get();
// Generate multiple proofs to aggregate
System.out.println("Generating proofs to aggregate...");
List<ProofData> proofsToAggregate = new ArrayList<>();
for (int i = 1; i <= 4; i++) {
Map<String, String> inputs = new HashMap<>();
inputs.put("x", String.valueOf(i));
Proof proof = zk.proofs().generate(GenerateProofRequest.builder()
.circuitId(inner.getCircuitId())
.inputs(inputs)
.build()).get();
proofsToAggregate.add(ProofData.builder()
.proof(proof.getProof())
.publicSignals(proof.getPublicSignals())
.build());
System.out.println(" Proof " + i + ": y = " + proof.getPublicSignals().get(0));
}
// Aggregate proofs recursively
System.out.println("\nAggregating proofs...");
AggregatedProof aggregated = zk.proofs().aggregate(AggregateRequest.builder()
.circuitId(inner.getCircuitId())
.proofs(proofsToAggregate)
.aggregationType("recursive")
.build()).get();
int originalSize = proofsToAggregate.stream()
.mapToInt(p -> p.getProof().length())
.sum();
System.out.println("Aggregated proof:");
System.out.println(" Proof ID: " + aggregated.getProofId());
System.out.println(" Aggregated count: " + aggregated.getAggregatedCount());
System.out.println(" Proof size: " + aggregated.getProof().length() + " bytes");
System.out.println(" Size reduction: " +
String.format("%.1f", (1 - (double) aggregated.getProof().length() / originalSize) * 100) + "%");
// Verify aggregated proof
List<List<String>> publicSignalsList = proofsToAggregate.stream()
.map(ProofData::getPublicSignals)
.toList();
boolean isValid = zk.proofs().verifyAggregated(VerifyAggregatedRequest.builder()
.circuitId(inner.getCircuitId())
.proof(aggregated.getProof())
.publicSignalsList(publicSignalsList)
.build()).get();
System.out.println("\nAggregated proof valid: " + isValid);
// Batch verification
System.out.println("\nBatch verification...");
BatchVerifyResult batchResult = zk.proofs().batchVerify(BatchVerifyRequest.builder()
.circuitId(inner.getCircuitId())
.proofs(proofsToAggregate)
.build()).get();
System.out.println(" All valid: " + batchResult.isAllValid());
System.out.println(" Results: " + batchResult.getResults());
System.out.println();
}
static void onChainVerificationExample(SynorZk zk) throws Exception {
System.out.println("=== On-Chain Verification ===");
// Compile circuit
String circuit = """
pragma circom 2.1.0;
template VoteCommitment() {
signal input vote;
signal input nullifier;
signal input commitment;
signal computed;
computed <== vote * nullifier;
commitment === computed;
}
component main {public [commitment]} = VoteCommitment();
""";
CompiledCircuit compiled = zk.circuits().compile(CompileRequest.builder()
.code(circuit)
.format(CircuitFormat.CIRCOM)
.name("vote_commitment")
.provingSystem(ProvingSystem.GROTH16)
.build()).get();
// Generate Solidity verifier
System.out.println("Generating Solidity verifier...");
GeneratedVerifier solidityVerifier = zk.contracts().generateVerifier(GenerateVerifierRequest.builder()
.circuitId(compiled.getCircuitId())
.language("solidity")
.optimized(true)
.build()).get();
System.out.println("Solidity verifier generated: " + solidityVerifier.getCode().length() + " bytes");
System.out.println(" Contract name: " + solidityVerifier.getContractName());
System.out.println(" Gas estimate: " + solidityVerifier.getGasEstimate());
// Generate proof
Map<String, String> inputs = new HashMap<>();
inputs.put("vote", "1");
inputs.put("nullifier", "12345");
inputs.put("commitment", "12345");
Proof proof = zk.proofs().generate(GenerateProofRequest.builder()
.circuitId(compiled.getCircuitId())
.inputs(inputs)
.build()).get();
// Format proof for on-chain verification
System.out.println("\nFormatting proof for on-chain...");
FormattedProof onChainProof = zk.contracts().formatProof(FormatProofRequest.builder()
.circuitId(compiled.getCircuitId())
.proof(proof.getProof())
.publicSignals(proof.getPublicSignals())
.format("calldata")
.build()).get();
String calldataPreview = onChainProof.getCalldata().substring(0,
Math.min(100, onChainProof.getCalldata().length()));
System.out.println(" Calldata: " + calldataPreview + "...");
System.out.println(" Estimated gas: " + onChainProof.getGasEstimate());
// Deploy verifier contract
System.out.println("\nDeploying verifier contract...");
Deployment deployment = zk.contracts().deployVerifier(DeployRequest.builder()
.circuitId(compiled.getCircuitId())
.network("synor-testnet")
.build()).get();
System.out.println(" Contract address: " + deployment.getAddress());
System.out.println(" TX hash: " + deployment.getTxHash());
System.out.println(" Gas used: " + deployment.getGasUsed());
// Verify on-chain
System.out.println("\nVerifying on-chain...");
OnChainVerifyResult onChainResult = zk.contracts().verifyOnChain(OnChainVerifyRequest.builder()
.contractAddress(deployment.getAddress())
.proof(proof.getProof())
.publicSignals(proof.getPublicSignals())
.network("synor-testnet")
.build()).get();
System.out.println(" TX hash: " + onChainResult.getTxHash());
System.out.println(" Verified: " + onChainResult.isVerified());
System.out.println(" Gas used: " + onChainResult.getGasUsed());
// Generate verifier for other targets
System.out.println("\nGenerating verifiers for other targets:");
String[] targets = {"cairo", "noir", "ink"};
for (String target : targets) {
GeneratedVerifier verifier = zk.contracts().generateVerifier(GenerateVerifierRequest.builder()
.circuitId(compiled.getCircuitId())
.language(target)
.build()).get();
System.out.println(" " + target + ": " + verifier.getCode().length() + " bytes");
}
System.out.println();
}
static void setupExample(SynorZk zk) throws Exception {
System.out.println("=== Trusted Setup ===");
// Get available ceremonies
List<Ceremony> ceremonies = zk.setup().listCeremonies().get();
System.out.println("Active ceremonies: " + ceremonies.size());
for (Ceremony ceremony : ceremonies) {
System.out.println(" " + ceremony.getName() + ":");
System.out.println(" Status: " + ceremony.getStatus());
System.out.println(" Participants: " + ceremony.getParticipantCount());
System.out.println(" Current round: " + ceremony.getCurrentRound());
}
// Create a new circuit setup
String circuit = """
pragma circom 2.1.0;
template NewCircuit() {
signal input a;
signal output b;
b <== a + 1;
}
component main {public [b]} = NewCircuit();
""";
System.out.println("\nInitializing setup for new circuit...");
SetupResult setup = zk.setup().initialize(SetupInitRequest.builder()
.circuit(circuit)
.format(CircuitFormat.CIRCOM)
.name("new_circuit_setup")
.provingSystem(ProvingSystem.GROTH16)
.ceremonyType("powers_of_tau")
.build()).get();
System.out.println("Setup initialized:");
System.out.println(" Ceremony ID: " + setup.getCeremonyId());
System.out.println(" Powers of Tau required: " + setup.getPowersRequired());
System.out.println(" Current phase: " + setup.getPhase());
// Contribute to ceremony
System.out.println("\nContributing to ceremony...");
Contribution contribution = zk.setup().contribute(ContributeRequest.builder()
.ceremonyId(setup.getCeremonyId())
.entropy(bytesToHex("random-entropy-from-user".getBytes()))
.build()).get();
System.out.println("Contribution submitted:");
System.out.println(" Participant: " + contribution.getParticipantId());
System.out.println(" Contribution hash: " + contribution.getHash());
System.out.println(" Verification status: " + contribution.isVerified());
// Get ceremony status
CeremonyStatus status = zk.setup().getStatus(setup.getCeremonyId()).get();
System.out.println("\nCeremony status:");
System.out.println(" Phase: " + status.getPhase());
System.out.println(" Total contributions: " + status.getTotalContributions());
System.out.println(" Verified contributions: " + status.getVerifiedContributions());
System.out.println(" Ready for finalization: " + status.isReadyForFinalization());
// Finalize setup (when enough contributions)
if (status.isReadyForFinalization()) {
System.out.println("\nFinalizing setup...");
FinalizedSetup finalized = zk.setup().finalize(setup.getCeremonyId()).get();
System.out.println("Setup finalized:");
System.out.println(" Proving key hash: " + finalized.getProvingKeyHash());
System.out.println(" Verification key hash: " + finalized.getVerificationKeyHash());
System.out.println(" Contribution transcript: " + finalized.getTranscriptCid());
}
// Download ceremony transcript
byte[] transcript = zk.setup().getTranscript(setup.getCeremonyId()).get();
System.out.println("\nCeremony transcript: " + transcript.length + " bytes");
System.out.println();
}
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}