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
495 lines
17 KiB
C
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;
|
|
}
|