synor/sdk/c/examples/zk_example.c
Gulshan Yadav cf5130d9e4 feat(sdk): Add comprehensive examples for C, C++, C#, and Ruby SDKs
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
2026-01-28 14:44:04 +05:30

495 lines
17 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <synor/zk.h>
void circuit_example(synor_zk_t* zk) {
printf("=== Circuit Compilation ===\n");
synor_error_t err;
// Simple Circom circuit: prove knowledge of factors
const char* circom_code =
"pragma circom 2.1.0;\n"
"\n"
"template Multiplier() {\n"
" signal input a;\n"
" signal input b;\n"
" signal output c;\n"
"\n"
" c <== a * b;\n"
"}\n"
"\n"
"component main = Multiplier();\n";
// Compile the circuit
printf("Compiling circuit...\n");
synor_circuit_source_t source = {
.code = circom_code,
.language = SYNOR_CIRCUIT_LANGUAGE_CIRCOM
};
synor_circuit_t* circuit = NULL;
err = synor_circuits_compile(zk, &source, &circuit);
if (err != SYNOR_OK) {
fprintf(stderr, "Failed to compile circuit\n");
return;
}
printf("Circuit compiled:\n");
printf(" Circuit ID: %s\n", synor_circuit_get_id(circuit));
printf(" Constraints: %zu\n", synor_circuit_get_constraints(circuit));
printf(" Public inputs: %zu\n", synor_circuit_get_public_inputs(circuit));
printf(" Private inputs: %zu\n", synor_circuit_get_private_inputs(circuit));
printf(" Outputs: %zu\n", synor_circuit_get_outputs(circuit));
// Get circuit info
synor_circuit_info_t* info = NULL;
err = synor_circuits_get(zk, synor_circuit_get_id(circuit), &info);
if (err == SYNOR_OK) {
printf("\nCircuit info:\n");
printf(" Name: %s\n", synor_circuit_info_get_name(info));
printf(" Version: %s\n", synor_circuit_info_get_version(info));
printf(" Wires: %zu\n", synor_circuit_info_get_wire_count(info));
printf(" Labels: %zu\n", synor_circuit_info_get_label_count(info));
synor_circuit_info_free(info);
}
// List available circuits
synor_circuit_list_t* circuits = NULL;
err = synor_circuits_list(zk, &circuits);
if (err == SYNOR_OK) {
printf("\nAvailable circuits: %zu\n", synor_circuit_list_count(circuits));
for (size_t i = 0; i < 3 && i < synor_circuit_list_count(circuits); i++) {
synor_circuit_t* c = synor_circuit_list_get(circuits, i);
printf(" %s: %s (%zu constraints)\n",
synor_circuit_get_id(c),
synor_circuit_get_name(c),
synor_circuit_get_constraints(c));
}
synor_circuit_list_free(circuits);
}
synor_circuit_free(circuit);
printf("\n");
}
void groth16_example(synor_zk_t* zk) {
printf("=== Groth16 Proving System ===\n");
synor_error_t err;
const char* circuit_id = "multiplier-v1";
// Generate proving/verification keys (trusted setup)
printf("Generating keys...\n");
synor_groth16_keys_t* keys = NULL;
err = synor_groth16_setup(zk, circuit_id, &keys);
if (err != SYNOR_OK) {
fprintf(stderr, "Failed to generate keys\n");
return;
}
printf("Keys generated:\n");
printf(" Proving key size: %zu bytes\n", synor_groth16_keys_get_pk_size(keys));
printf(" Verification key size: %zu bytes\n", synor_groth16_keys_get_vk_size(keys));
// Prepare witness (private inputs)
synor_witness_t* witness = synor_witness_create();
synor_witness_set(witness, "a", "3");
synor_witness_set(witness, "b", "7");
// Generate proof
printf("\nGenerating proof...\n");
synor_prove_request_t prove_req = {
.circuit_id = circuit_id,
.witness = witness,
.proving_key = synor_groth16_keys_get_pk(keys),
.proving_key_len = synor_groth16_keys_get_pk_size(keys)
};
synor_proof_t* proof = NULL;
err = synor_groth16_prove(zk, &prove_req, &proof);
if (err != SYNOR_OK) {
fprintf(stderr, "Failed to generate proof\n");
synor_witness_free(witness);
synor_groth16_keys_free(keys);
return;
}
printf("Proof generated:\n");
printf(" Proof size: %zu bytes\n", synor_proof_get_size(proof));
printf(" Public signals: %zu\n", synor_proof_get_public_signal_count(proof));
printf(" Proving time: %lums\n", synor_proof_get_proving_time_ms(proof));
// Verify proof
printf("\nVerifying proof...\n");
synor_verify_request_t verify_req = {
.proof = synor_proof_get_bytes(proof),
.proof_len = synor_proof_get_size(proof),
.public_signals = synor_proof_get_public_signals(proof),
.public_signal_count = synor_proof_get_public_signal_count(proof),
.verification_key = synor_groth16_keys_get_vk(keys),
.verification_key_len = synor_groth16_keys_get_vk_size(keys)
};
bool verified;
err = synor_groth16_verify(zk, &verify_req, &verified);
printf("Verification result: %s\n", verified ? "true" : "false");
// Export proof for on-chain verification
char* solidity_calldata = NULL;
err = synor_groth16_export_calldata(zk, proof, &solidity_calldata);
if (err == SYNOR_OK && solidity_calldata) {
printf("\nSolidity calldata: %.100s...\n", solidity_calldata);
free(solidity_calldata);
}
synor_proof_free(proof);
synor_witness_free(witness);
synor_groth16_keys_free(keys);
printf("\n");
}
void plonk_example(synor_zk_t* zk) {
printf("=== PLONK Proving System ===\n");
synor_error_t err;
const char* circuit_id = "multiplier-v1";
// PLONK uses universal trusted setup
printf("Getting universal setup...\n");
synor_srs_t* srs = NULL;
err = synor_plonk_get_universal_setup(zk, 14, &srs); // 2^14 constraints
if (err != SYNOR_OK) {
fprintf(stderr, "Failed to get SRS\n");
return;
}
printf("SRS loaded: %zu bytes\n", synor_srs_get_size(srs));
// Generate circuit-specific keys
printf("\nGenerating circuit keys...\n");
synor_plonk_keys_t* keys = NULL;
err = synor_plonk_setup(zk, circuit_id, srs, &keys);
if (err != SYNOR_OK) {
fprintf(stderr, "Failed to generate keys\n");
synor_srs_free(srs);
return;
}
printf("Keys generated\n");
// Generate proof
synor_witness_t* witness = synor_witness_create();
synor_witness_set(witness, "a", "5");
synor_witness_set(witness, "b", "9");
printf("\nGenerating PLONK proof...\n");
synor_plonk_prove_request_t prove_req = {
.circuit_id = circuit_id,
.witness = witness,
.proving_key = synor_plonk_keys_get_pk(keys),
.proving_key_len = synor_plonk_keys_get_pk_size(keys)
};
synor_proof_t* proof = NULL;
err = synor_plonk_prove(zk, &prove_req, &proof);
if (err == SYNOR_OK) {
printf("Proof generated:\n");
printf(" Proof size: %zu bytes\n", synor_proof_get_size(proof));
printf(" Proving time: %lums\n", synor_proof_get_proving_time_ms(proof));
// Verify proof
synor_plonk_verify_request_t verify_req = {
.proof = synor_proof_get_bytes(proof),
.proof_len = synor_proof_get_size(proof),
.public_signals = synor_proof_get_public_signals(proof),
.public_signal_count = synor_proof_get_public_signal_count(proof),
.verification_key = synor_plonk_keys_get_vk(keys),
.verification_key_len = synor_plonk_keys_get_vk_size(keys)
};
bool verified;
synor_plonk_verify(zk, &verify_req, &verified);
printf("Verification result: %s\n", verified ? "true" : "false");
synor_proof_free(proof);
}
// Compare with Groth16
printf("\nPLONK advantages:\n");
printf(" - Universal trusted setup\n");
printf(" - Larger proofs (~2.5 KB vs ~200 bytes)\n");
printf(" - Faster proving for some circuits\n");
synor_witness_free(witness);
synor_plonk_keys_free(keys);
synor_srs_free(srs);
printf("\n");
}
void stark_example(synor_zk_t* zk) {
printf("=== STARK Proving System ===\n");
synor_error_t err;
const char* circuit_id = "multiplier-v1";
// STARKs don't need trusted setup
printf("Configuring STARK parameters...\n");
synor_stark_config_t config = {
.field_size = 256,
.hash_function = SYNOR_HASH_FUNCTION_POSEIDON,
.blowup_factor = 8,
.num_queries = 30,
.folding_factor = 8
};
// Generate proof
synor_witness_t* witness = synor_witness_create();
synor_witness_set(witness, "a", "11");
synor_witness_set(witness, "b", "13");
printf("\nGenerating STARK proof...\n");
synor_stark_prove_request_t prove_req = {
.circuit_id = circuit_id,
.witness = witness,
.config = &config
};
synor_stark_proof_t* proof = NULL;
err = synor_stark_prove(zk, &prove_req, &proof);
if (err == SYNOR_OK) {
printf("Proof generated:\n");
printf(" Proof size: %zu bytes\n", synor_stark_proof_get_size(proof));
printf(" Proving time: %lums\n", synor_stark_proof_get_proving_time_ms(proof));
printf(" FRI layers: %zu\n", synor_stark_proof_get_fri_layers(proof));
// Verify proof
printf("\nVerifying STARK proof...\n");
synor_stark_verify_request_t verify_req = {
.proof = synor_stark_proof_get_bytes(proof),
.proof_len = synor_stark_proof_get_size(proof),
.public_signals = synor_stark_proof_get_public_signals(proof),
.public_signal_count = synor_stark_proof_get_public_signal_count(proof),
.config = &config
};
bool verified;
synor_stark_verify(zk, &verify_req, &verified);
printf("Verification result: %s\n", verified ? "true" : "false");
synor_stark_proof_free(proof);
}
// Compare with SNARKs
printf("\nSTARK advantages:\n");
printf(" - No trusted setup needed\n");
printf(" - Post-quantum secure\n");
printf(" - Larger proofs (~100 KB)\n");
printf(" - Faster proving for complex computations\n");
synor_witness_free(witness);
printf("\n");
}
void recursive_example(synor_zk_t* zk) {
printf("=== Recursive Proof Composition ===\n");
synor_error_t err;
// Create inner proofs
printf("Generating inner proofs...\n");
synor_recursive_proof_list_t* inner_proofs = synor_recursive_proof_list_create();
for (int i = 1; i <= 3; i++) {
synor_witness_t* witness = synor_witness_create();
char a_str[16], b_str[16];
snprintf(a_str, sizeof(a_str), "%d", i);
snprintf(b_str, sizeof(b_str), "%d", i + 1);
synor_witness_set(witness, "a", a_str);
synor_witness_set(witness, "b", b_str);
synor_recursive_prove_request_t prove_req = {
.circuit_id = "multiplier-v1",
.witness = witness,
.level = 0
};
synor_recursive_proof_t* proof = NULL;
err = synor_recursive_prove_inner(zk, &prove_req, &proof);
if (err == SYNOR_OK) {
synor_recursive_proof_list_add(inner_proofs, proof);
printf(" Inner proof %d generated\n", i);
}
synor_witness_free(witness);
}
// Aggregate proofs recursively
printf("\nAggregating proofs...\n");
synor_aggregate_request_t aggregate_req = {
.proofs = inner_proofs,
.aggregation_circuit = "recursive-aggregator-v1"
};
synor_aggregated_proof_t* aggregated = NULL;
err = synor_recursive_aggregate(zk, &aggregate_req, &aggregated);
if (err == SYNOR_OK) {
printf("Aggregated proof:\n");
printf(" Proof size: %zu bytes\n", synor_aggregated_proof_get_size(aggregated));
printf(" Proofs aggregated: %zu\n", synor_aggregated_proof_get_count(aggregated));
printf(" Recursion depth: %zu\n", synor_aggregated_proof_get_depth(aggregated));
// Verify aggregated proof
printf("\nVerifying aggregated proof...\n");
bool verified;
err = synor_recursive_verify_aggregated(zk, aggregated, &verified);
printf("Verification result: %s\n", verified ? "true" : "false");
synor_aggregated_proof_free(aggregated);
}
// Use cases
printf("\nRecursive proof use cases:\n");
printf(" - Rollup batch verification\n");
printf(" - Incremental computation proofs\n");
printf(" - Cross-chain state proofs\n");
synor_recursive_proof_list_free(inner_proofs);
printf("\n");
}
void ceremony_example(synor_zk_t* zk) {
printf("=== Trusted Setup Ceremony ===\n");
synor_error_t err;
// List active ceremonies
synor_ceremony_list_t* ceremonies = NULL;
err = synor_ceremony_list(zk, SYNOR_CEREMONY_STATUS_ACTIVE, &ceremonies);
if (err == SYNOR_OK) {
printf("Active ceremonies: %zu\n", synor_ceremony_list_count(ceremonies));
for (size_t i = 0; i < 3 && i < synor_ceremony_list_count(ceremonies); i++) {
synor_ceremony_t* ceremony = synor_ceremony_list_get(ceremonies, i);
printf("\n %s:\n", synor_ceremony_get_id(ceremony));
printf(" Circuit: %s\n", synor_ceremony_get_circuit_id(ceremony));
printf(" Participants: %zu\n", synor_ceremony_get_participant_count(ceremony));
printf(" Current round: %zu\n", synor_ceremony_get_current_round(ceremony));
printf(" Status: %s\n", synor_ceremony_get_status(ceremony));
}
synor_ceremony_list_free(ceremonies);
}
// Create a new ceremony
printf("\nCreating new ceremony...\n");
synor_ceremony_config_t config = {
.circuit_id = "new-circuit-v1",
.min_participants = 10,
.max_participants = 100,
.round_duration = 3600, // 1 hour per round
.verify_contributions = true
};
synor_ceremony_t* new_ceremony = NULL;
err = synor_ceremony_create(zk, &config, &new_ceremony);
if (err == SYNOR_OK) {
printf("Ceremony created:\n");
printf(" Ceremony ID: %s\n", synor_ceremony_get_id(new_ceremony));
printf(" Join URL: %s\n", synor_ceremony_get_join_url(new_ceremony));
// Participate in ceremony
printf("\nParticipating in ceremony...\n");
uint8_t entropy[32];
// In real code, use secure random: arc4random_buf(entropy, sizeof(entropy));
memset(entropy, 0x42, sizeof(entropy)); // Example only
synor_contribution_request_t contrib_req = {
.ceremony_id = synor_ceremony_get_id(new_ceremony),
.entropy = entropy,
.entropy_len = sizeof(entropy)
};
synor_contribution_t* contribution = NULL;
err = synor_ceremony_contribute(zk, &contrib_req, &contribution);
if (err == SYNOR_OK) {
printf("Contribution made:\n");
printf(" Contribution ID: %s\n", synor_contribution_get_id(contribution));
printf(" Position: %zu\n", synor_contribution_get_position(contribution));
printf(" Hash: %s\n", synor_contribution_get_hash(contribution));
// Verify contribution
printf("\nVerifying contribution...\n");
bool valid;
synor_ceremony_verify_contribution(zk, synor_contribution_get_id(contribution), &valid);
printf("Contribution valid: %s\n", valid ? "true" : "false");
synor_contribution_free(contribution);
}
// Get ceremony transcript
synor_transcript_t* transcript = NULL;
err = synor_ceremony_get_transcript(zk, synor_ceremony_get_id(new_ceremony), &transcript);
if (err == SYNOR_OK) {
printf("\nCeremony transcript:\n");
printf(" Total contributions: %zu\n", synor_transcript_get_contribution_count(transcript));
printf(" Start time: %s\n", synor_transcript_get_start_time(transcript));
const char* final_hash = synor_transcript_get_final_hash(transcript);
printf(" Final hash: %s\n", final_hash ? final_hash : "pending");
synor_transcript_free(transcript);
}
synor_ceremony_free(new_ceremony);
}
printf("\n");
}
int main(int argc, char** argv) {
synor_error_t err;
// Initialize client
synor_zk_config_t config = {
.api_key = getenv("SYNOR_API_KEY") ? getenv("SYNOR_API_KEY") : "your-api-key",
.endpoint = "https://zk.synor.io/v1",
.timeout_ms = 120000, // ZK operations can be slow
.retries = 3,
.debug = false,
.default_proving_system = SYNOR_PROVING_SYSTEM_GROTH16,
.prove_timeout_ms = 300000,
.verify_timeout_ms = 30000
};
synor_zk_t* zk = NULL;
err = synor_zk_init(&config, &zk);
if (err != SYNOR_OK) {
fprintf(stderr, "Failed to initialize ZK client: %s\n", synor_error_string(err));
return 1;
}
// Check service health
bool healthy;
err = synor_zk_health_check(zk, &healthy);
printf("Service healthy: %s\n\n", healthy ? "true" : "false");
// Run examples
circuit_example(zk);
groth16_example(zk);
plonk_example(zk);
stark_example(zk);
recursive_example(zk);
ceremony_example(zk);
// Cleanup
synor_zk_free(zk);
return 0;
}