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
359 lines
13 KiB
C++
359 lines
13 KiB
C++
/**
|
|
* 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 <iostream>
|
|
#include <iomanip>
|
|
#include <cstdlib>
|
|
#include <random>
|
|
#include <synor/zk.hpp>
|
|
|
|
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<std::string, std::string> 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<std::string, std::string> 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<std::string, std::string> 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<RecursiveProof> inner_proofs;
|
|
|
|
for (int i = 1; i <= 3; ++i) {
|
|
std::map<std::string, std::string> 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<uint8_t> 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;
|
|
}
|