/** * Synor ZK SDK Examples for C++ * * Demonstrates zero-knowledge proof operations: * - Circuit compilation (Circom) * - Proof generation and verification * - Multiple proving systems (Groth16, PLONK, STARK) * - Recursive proof composition * - Trusted setup ceremonies */ #include #include #include #include #include using namespace synor::zk; void circuit_example(SynorZk& zk) { std::cout << "=== Circuit Compilation ===" << std::endl; // Simple Circom circuit: prove knowledge of factors std::string circom_code = R"( pragma circom 2.1.0; template Multiplier() { signal input a; signal input b; signal output c; c <== a * b; } component main = Multiplier(); )"; // Compile the circuit std::cout << "Compiling circuit..." << std::endl; auto circuit = zk.circuits().compile({ .code = circom_code, .language = CircuitLanguage::Circom }); std::cout << "Circuit compiled:" << std::endl; std::cout << " Circuit ID: " << circuit.circuit_id() << std::endl; std::cout << " Constraints: " << circuit.constraints() << std::endl; std::cout << " Public inputs: " << circuit.public_inputs() << std::endl; std::cout << " Private inputs: " << circuit.private_inputs() << std::endl; std::cout << " Outputs: " << circuit.outputs() << std::endl; // Get circuit info auto info = zk.circuits().get(circuit.circuit_id()); std::cout << "\nCircuit info:" << std::endl; std::cout << " Name: " << info.name() << std::endl; std::cout << " Version: " << info.version() << std::endl; std::cout << " Wires: " << info.wire_count() << std::endl; std::cout << " Labels: " << info.label_count() << std::endl; // List available circuits auto circuits = zk.circuits().list(); std::cout << "\nAvailable circuits: " << circuits.size() << std::endl; for (size_t i = 0; i < std::min(circuits.size(), size_t(3)); ++i) { const auto& c = circuits[i]; std::cout << " " << c.circuit_id() << ": " << c.name() << " (" << c.constraints() << " constraints)" << std::endl; } std::cout << std::endl; } void groth16_example(SynorZk& zk) { std::cout << "=== Groth16 Proving System ===" << std::endl; std::string circuit_id = "multiplier-v1"; // Generate proving/verification keys (trusted setup) std::cout << "Generating keys..." << std::endl; auto keys = zk.groth16().setup(circuit_id); std::cout << "Keys generated:" << std::endl; std::cout << " Proving key size: " << keys.proving_key().size() << " bytes" << std::endl; std::cout << " Verification key size: " << keys.verification_key().size() << " bytes" << std::endl; // Prepare witness (private inputs) std::map witness = { {"a", "3"}, {"b", "7"} }; // Generate proof std::cout << "\nGenerating proof..." << std::endl; auto proof = zk.groth16().prove({ .circuit_id = circuit_id, .witness = witness, .proving_key = keys.proving_key() }); std::cout << "Proof generated:" << std::endl; std::cout << " Proof size: " << proof.proof_bytes().size() << " bytes" << std::endl; std::cout << " Public signals: " << proof.public_signals().size() << std::endl; std::cout << " Proving time: " << proof.proving_time_ms() << "ms" << std::endl; // Verify proof std::cout << "\nVerifying proof..." << std::endl; bool verified = zk.groth16().verify({ .proof = proof.proof_bytes(), .public_signals = proof.public_signals(), .verification_key = keys.verification_key() }); std::cout << "Verification result: " << (verified ? "true" : "false") << std::endl; // Export proof for on-chain verification auto solidity_calldata = zk.groth16().export_calldata(proof); std::cout << "\nSolidity calldata: " << solidity_calldata.substr(0, 100) << "..." << std::endl; std::cout << std::endl; } void plonk_example(SynorZk& zk) { std::cout << "=== PLONK Proving System ===" << std::endl; std::string circuit_id = "multiplier-v1"; // PLONK uses universal trusted setup std::cout << "Getting universal setup..." << std::endl; auto srs = zk.plonk().get_universal_setup(14); // 2^14 constraints std::cout << "SRS loaded: " << srs.size() << " bytes" << std::endl; // Generate circuit-specific keys std::cout << "\nGenerating circuit keys..." << std::endl; auto keys = zk.plonk().setup(circuit_id, srs); std::cout << "Keys generated" << std::endl; // Generate proof std::map witness = {{"a", "5"}, {"b", "9"}}; std::cout << "\nGenerating PLONK proof..." << std::endl; auto proof = zk.plonk().prove({ .circuit_id = circuit_id, .witness = witness, .proving_key = keys.proving_key() }); std::cout << "Proof generated:" << std::endl; std::cout << " Proof size: " << proof.proof_bytes().size() << " bytes" << std::endl; std::cout << " Proving time: " << proof.proving_time_ms() << "ms" << std::endl; // Verify proof bool verified = zk.plonk().verify({ .proof = proof.proof_bytes(), .public_signals = proof.public_signals(), .verification_key = keys.verification_key() }); std::cout << "Verification result: " << (verified ? "true" : "false") << std::endl; // Compare with Groth16 std::cout << "\nPLONK advantages:" << std::endl; std::cout << " - Universal trusted setup" << std::endl; std::cout << " - Larger proofs (~2.5 KB vs ~200 bytes)" << std::endl; std::cout << " - Faster proving for some circuits" << std::endl; std::cout << std::endl; } void stark_example(SynorZk& zk) { std::cout << "=== STARK Proving System ===" << std::endl; std::string circuit_id = "multiplier-v1"; // STARKs don't need trusted setup std::cout << "Configuring STARK parameters..." << std::endl; StarkConfig config{ .field_size = 256, .hash_function = HashFunction::Poseidon, .blowup_factor = 8, .num_queries = 30, .folding_factor = 8 }; // Generate proof std::map witness = {{"a", "11"}, {"b", "13"}}; std::cout << "\nGenerating STARK proof..." << std::endl; auto proof = zk.stark().prove({ .circuit_id = circuit_id, .witness = witness, .config = config }); std::cout << "Proof generated:" << std::endl; std::cout << " Proof size: " << proof.proof_bytes().size() << " bytes" << std::endl; std::cout << " Proving time: " << proof.proving_time_ms() << "ms" << std::endl; std::cout << " FRI layers: " << proof.fri_layers() << std::endl; // Verify proof std::cout << "\nVerifying STARK proof..." << std::endl; bool verified = zk.stark().verify({ .proof = proof.proof_bytes(), .public_signals = proof.public_signals(), .config = config }); std::cout << "Verification result: " << (verified ? "true" : "false") << std::endl; // Compare with SNARKs std::cout << "\nSTARK advantages:" << std::endl; std::cout << " - No trusted setup needed" << std::endl; std::cout << " - Post-quantum secure" << std::endl; std::cout << " - Larger proofs (~100 KB)" << std::endl; std::cout << " - Faster proving for complex computations" << std::endl; std::cout << std::endl; } void recursive_example(SynorZk& zk) { std::cout << "=== Recursive Proof Composition ===" << std::endl; // Create inner proofs std::cout << "Generating inner proofs..." << std::endl; std::vector inner_proofs; for (int i = 1; i <= 3; ++i) { std::map witness = { {"a", std::to_string(i)}, {"b", std::to_string(i + 1)} }; auto proof = zk.recursive().prove_inner({ .circuit_id = "multiplier-v1", .witness = witness, .level = 0 }); inner_proofs.push_back(proof); std::cout << " Inner proof " << i << " generated" << std::endl; } // Aggregate proofs recursively std::cout << "\nAggregating proofs..." << std::endl; auto aggregated_proof = zk.recursive().aggregate({ .proofs = inner_proofs, .aggregation_circuit = "recursive-aggregator-v1" }); std::cout << "Aggregated proof:" << std::endl; std::cout << " Proof size: " << aggregated_proof.proof_bytes().size() << " bytes" << std::endl; std::cout << " Proofs aggregated: " << aggregated_proof.proofs_aggregated() << std::endl; std::cout << " Recursion depth: " << aggregated_proof.recursion_depth() << std::endl; // Verify aggregated proof (verifies all inner proofs at once) std::cout << "\nVerifying aggregated proof..." << std::endl; bool verified = zk.recursive().verify_aggregated(aggregated_proof); std::cout << "Verification result: " << (verified ? "true" : "false") << std::endl; // Use cases std::cout << "\nRecursive proof use cases:" << std::endl; std::cout << " - Rollup batch verification" << std::endl; std::cout << " - Incremental computation proofs" << std::endl; std::cout << " - Cross-chain state proofs" << std::endl; std::cout << std::endl; } void ceremony_example(SynorZk& zk) { std::cout << "=== Trusted Setup Ceremony ===" << std::endl; // List active ceremonies auto ceremonies = zk.ceremony().list(CeremonyStatus::Active); std::cout << "Active ceremonies: " << ceremonies.size() << std::endl; for (size_t i = 0; i < std::min(ceremonies.size(), size_t(3)); ++i) { const auto& ceremony = ceremonies[i]; std::cout << "\n " << ceremony.ceremony_id() << ":" << std::endl; std::cout << " Circuit: " << ceremony.circuit_id() << std::endl; std::cout << " Participants: " << ceremony.participant_count() << std::endl; std::cout << " Current round: " << ceremony.current_round() << std::endl; std::cout << " Status: " << ceremony.status() << std::endl; } // Create a new ceremony std::cout << "\nCreating new ceremony..." << std::endl; auto 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 }); std::cout << "Ceremony created:" << std::endl; std::cout << " Ceremony ID: " << new_ceremony.ceremony_id() << std::endl; std::cout << " Join URL: " << new_ceremony.join_url() << std::endl; // Participate in a ceremony std::cout << "\nParticipating in ceremony..." << std::endl; // Generate entropy std::vector entropy(32); std::random_device rd; std::generate(entropy.begin(), entropy.end(), std::ref(rd)); auto contribution = zk.ceremony().contribute({ .ceremony_id = new_ceremony.ceremony_id(), .entropy = entropy }); std::cout << "Contribution made:" << std::endl; std::cout << " Contribution ID: " << contribution.contribution_id() << std::endl; std::cout << " Position: " << contribution.position() << std::endl; std::cout << " Hash: " << contribution.hash() << std::endl; // Verify a contribution std::cout << "\nVerifying contribution..." << std::endl; bool valid = zk.ceremony().verify_contribution(contribution.contribution_id()); std::cout << "Contribution valid: " << (valid ? "true" : "false") << std::endl; // Get ceremony transcript (for auditability) auto transcript = zk.ceremony().get_transcript(new_ceremony.ceremony_id()); std::cout << "\nCeremony transcript:" << std::endl; std::cout << " Total contributions: " << transcript.contributions().size() << std::endl; std::cout << " Start time: " << transcript.start_time() << std::endl; std::cout << " Final hash: " << (transcript.final_hash().empty() ? "pending" : transcript.final_hash()) << std::endl; std::cout << std::endl; } int main(int argc, char** argv) { // Initialize client const char* api_key = std::getenv("SYNOR_API_KEY"); ZkConfig config{ .api_key = api_key ? api_key : "your-api-key", .endpoint = "https://zk.synor.io/v1", .timeout = std::chrono::seconds(120), // ZK operations can be slow .retries = 3, .debug = false, .default_proving_system = ProvingSystem::Groth16, .prove_timeout = std::chrono::seconds(300), .verify_timeout = std::chrono::seconds(30) }; SynorZk zk(config); try { // Check service health bool healthy = zk.health_check(); std::cout << "Service healthy: " << (healthy ? "true" : "false") << std::endl << std::endl; // Run examples circuit_example(zk); groth16_example(zk); plonk_example(zk); stark_example(zk); recursive_example(zk); ceremony_example(zk); } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; return 1; } return 0; }