feat(sdk): Add ZK SDK for all 12 languages

Implement Zero-Knowledge proof SDK for ZK-Rollups and privacy:
- Proof systems: Groth16, PLONK, STARK
- Circuit types: Transfer, Batch, Deposit, Withdraw
- Rollup batch processing and state management
- Trusted setup ceremony operations
- Merkle proof verification

Languages: JS/TS, Python, Go, Rust, Flutter, Java, Kotlin, Swift, C, C++, C#, Ruby
This commit is contained in:
Gulshan Yadav 2026-01-28 13:11:06 +05:30
parent 97add23062
commit eab599767c
22 changed files with 8881 additions and 0 deletions

527
sdk/c/include/synor/zk.h Normal file
View file

@ -0,0 +1,527 @@
/**
* Synor ZK SDK for C
*
* Zero-Knowledge proof systems for ZK-Rollups and privacy.
*/
#ifndef SYNOR_ZK_H
#define SYNOR_ZK_H
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================
* Opaque Types
* ============================================================================ */
typedef struct synor_zk_client synor_zk_client_t;
typedef struct synor_zk_proof synor_zk_proof_t;
typedef struct synor_zk_verification_key synor_zk_verification_key_t;
typedef struct synor_zk_proving_key synor_zk_proving_key_t;
typedef struct synor_zk_batch synor_zk_batch_t;
/* ============================================================================
* Enumerations
* ============================================================================ */
/** Proof system backends */
typedef enum {
SYNOR_ZK_PROOF_SYSTEM_GROTH16 = 0, /**< Smallest proofs (~192 bytes), fastest verification */
SYNOR_ZK_PROOF_SYSTEM_PLONK = 1, /**< Universal trusted setup, medium proofs (~512 bytes) */
SYNOR_ZK_PROOF_SYSTEM_STARK = 2 /**< No trusted setup, largest proofs (~50KB) */
} synor_zk_proof_system_t;
/** Circuit types for different operations */
typedef enum {
SYNOR_ZK_CIRCUIT_TRANSFER = 0, /**< Single transfer between accounts */
SYNOR_ZK_CIRCUIT_BATCH = 1, /**< Batch of multiple transfers */
SYNOR_ZK_CIRCUIT_DEPOSIT = 2, /**< Deposit from L1 to L2 */
SYNOR_ZK_CIRCUIT_WITHDRAW = 3 /**< Withdrawal from L2 to L1 */
} synor_zk_circuit_type_t;
/** Rollup state */
typedef enum {
SYNOR_ZK_ROLLUP_STATE_ACTIVE = 0,
SYNOR_ZK_ROLLUP_STATE_PAUSED = 1,
SYNOR_ZK_ROLLUP_STATE_FINALIZING = 2,
SYNOR_ZK_ROLLUP_STATE_FINALIZED = 3
} synor_zk_rollup_state_t;
/** Proof status */
typedef enum {
SYNOR_ZK_PROOF_STATUS_GENERATING = 0,
SYNOR_ZK_PROOF_STATUS_COMPLETED = 1,
SYNOR_ZK_PROOF_STATUS_FAILED = 2,
SYNOR_ZK_PROOF_STATUS_VERIFIED = 3
} synor_zk_proof_status_t;
/** Error codes */
typedef enum {
SYNOR_ZK_OK = 0,
SYNOR_ZK_ERROR_INVALID_ARGUMENT = 1,
SYNOR_ZK_ERROR_NETWORK = 2,
SYNOR_ZK_ERROR_AUTH = 3,
SYNOR_ZK_ERROR_NOT_FOUND = 4,
SYNOR_ZK_ERROR_TIMEOUT = 5,
SYNOR_ZK_ERROR_INTERNAL = 6,
SYNOR_ZK_ERROR_CLIENT_CLOSED = 7,
SYNOR_ZK_ERROR_PROOF_INVALID = 8,
SYNOR_ZK_ERROR_CIRCUIT_ERROR = 9
} synor_zk_error_t;
/* ============================================================================
* Structures
* ============================================================================ */
/** SDK configuration */
typedef struct {
const char* api_key;
const char* endpoint; /**< Default: "https://zk.synor.io/v1" */
const char* ws_endpoint; /**< Default: "wss://zk.synor.io/v1/ws" */
uint32_t timeout_ms; /**< Default: 60000 */
uint32_t retries; /**< Default: 3 */
synor_zk_proof_system_t default_proof_system; /**< Default: GROTH16 */
bool debug; /**< Default: false */
} synor_zk_config_t;
/** Zero-knowledge proof */
typedef struct {
char id[64];
synor_zk_proof_system_t system;
synor_zk_circuit_type_t circuit_type;
uint8_t* data;
size_t data_len;
char** public_inputs;
size_t public_inputs_count;
size_t size;
uint64_t generation_time_ms;
uint64_t created_at;
} synor_zk_proof_info_t;
/** Verification result */
typedef struct {
bool valid;
uint64_t verification_time_ms;
char* error;
} synor_zk_verification_result_t;
/** Account state */
typedef struct {
char address[64];
char balance[32];
uint64_t nonce;
char pubkey_hash[66];
} synor_zk_account_state_t;
/** Transfer operation */
typedef struct {
char from[64];
char to[64];
char amount[32];
char fee[32];
uint64_t nonce;
char* signature; /**< Optional */
} synor_zk_transfer_t;
/** Deposit operation */
typedef struct {
char l1_tx_hash[66];
char recipient[64];
char amount[32];
char* token; /**< Optional */
} synor_zk_deposit_t;
/** Withdrawal operation */
typedef struct {
char sender[64];
char recipient[64];
char amount[32];
char* token; /**< Optional */
uint64_t nonce;
char* signature; /**< Optional */
} synor_zk_withdrawal_t;
/** Rollup statistics */
typedef struct {
uint64_t current_batch;
uint64_t total_transactions;
uint64_t total_proofs;
uint64_t avg_proof_time_ms;
char state_root[66];
uint64_t account_count;
char tvl[32];
} synor_zk_rollup_stats_t;
/** Proof request */
typedef struct {
synor_zk_circuit_type_t circuit_type;
char** public_inputs;
size_t public_inputs_count;
char** private_inputs;
size_t private_inputs_count;
synor_zk_proof_system_t* system; /**< Optional, uses default if NULL */
} synor_zk_proof_request_t;
/** Merkle proof */
typedef struct {
char leaf[66];
char** path;
size_t path_len;
uint8_t* indices;
size_t indices_len;
char root[66];
} synor_zk_merkle_proof_t;
/** Ceremony contribution */
typedef struct {
char contributor_id[64];
char hash[66];
uint64_t timestamp;
bool verified;
} synor_zk_ceremony_contribution_t;
/** Trusted setup ceremony */
typedef struct {
char id[64];
synor_zk_circuit_type_t circuit_type;
synor_zk_proof_system_t system;
size_t contribution_count;
char latest_hash[66];
bool complete;
synor_zk_ceremony_contribution_t* contributions;
size_t contributions_count;
} synor_zk_trusted_setup_t;
/** Proof system characteristics */
typedef struct {
const char* name;
size_t proof_size;
uint32_t verification_time_ms;
bool trusted_setup;
bool universal;
} synor_zk_proof_system_info_t;
/* ============================================================================
* Client Lifecycle
* ============================================================================ */
/**
* Create a new ZK SDK client
*
* @param config Configuration options
* @return New client handle, or NULL on error
*/
synor_zk_client_t* synor_zk_client_new(const synor_zk_config_t* config);
/**
* Close and free a client
*
* @param client Client to close
*/
void synor_zk_client_free(synor_zk_client_t* client);
/**
* Check if client is closed
*
* @param client Client handle
* @return true if closed
*/
bool synor_zk_client_is_closed(const synor_zk_client_t* client);
/**
* Health check
*
* @param client Client handle
* @param healthy Output parameter for health status
* @return Error code
*/
synor_zk_error_t synor_zk_health_check(synor_zk_client_t* client, bool* healthy);
/* ============================================================================
* Proof Operations
* ============================================================================ */
/**
* Generate a zero-knowledge proof
*
* @param client Client handle
* @param request Proof request parameters
* @param proof Output parameter for generated proof
* @return Error code
*/
synor_zk_error_t synor_zk_proof_generate(
synor_zk_client_t* client,
const synor_zk_proof_request_t* request,
synor_zk_proof_t** proof
);
/**
* Verify a proof
*
* @param client Client handle
* @param proof Proof to verify
* @param result Output parameter for verification result
* @return Error code
*/
synor_zk_error_t synor_zk_proof_verify(
synor_zk_client_t* client,
const synor_zk_proof_t* proof,
synor_zk_verification_result_t* result
);
/**
* Get a proof by ID
*
* @param client Client handle
* @param proof_id Proof identifier
* @param proof Output parameter for proof
* @return Error code
*/
synor_zk_error_t synor_zk_proof_get(
synor_zk_client_t* client,
const char* proof_id,
synor_zk_proof_t** proof
);
/**
* Free a proof
*/
void synor_zk_proof_free(synor_zk_proof_t* proof);
/**
* Get proof info
*/
synor_zk_error_t synor_zk_proof_get_info(
const synor_zk_proof_t* proof,
synor_zk_proof_info_t* info
);
/* ============================================================================
* Circuit Operations
* ============================================================================ */
/**
* Get verification key for a circuit
*/
synor_zk_error_t synor_zk_circuit_get_vk(
synor_zk_client_t* client,
synor_zk_circuit_type_t circuit_type,
synor_zk_proof_system_t system,
synor_zk_verification_key_t** vk
);
/**
* Get proving key for a circuit
*/
synor_zk_error_t synor_zk_circuit_get_pk(
synor_zk_client_t* client,
synor_zk_circuit_type_t circuit_type,
synor_zk_proof_system_t system,
synor_zk_proving_key_t** pk
);
/**
* Free verification key
*/
void synor_zk_verification_key_free(synor_zk_verification_key_t* vk);
/**
* Free proving key
*/
void synor_zk_proving_key_free(synor_zk_proving_key_t* pk);
/* ============================================================================
* Rollup Operations
* ============================================================================ */
/**
* Get rollup statistics
*/
synor_zk_error_t synor_zk_rollup_get_stats(
synor_zk_client_t* client,
synor_zk_rollup_stats_t* stats
);
/**
* Get current batch
*/
synor_zk_error_t synor_zk_rollup_get_current_batch(
synor_zk_client_t* client,
synor_zk_batch_t** batch
);
/**
* Get batch by number
*/
synor_zk_error_t synor_zk_rollup_get_batch(
synor_zk_client_t* client,
uint64_t batch_number,
synor_zk_batch_t** batch
);
/**
* Submit a transfer
*/
synor_zk_error_t synor_zk_rollup_submit_transfer(
synor_zk_client_t* client,
const synor_zk_transfer_t* transfer,
char* tx_id,
size_t tx_id_len
);
/**
* Submit a deposit
*/
synor_zk_error_t synor_zk_rollup_submit_deposit(
synor_zk_client_t* client,
const synor_zk_deposit_t* deposit,
char* tx_id,
size_t tx_id_len
);
/**
* Submit a withdrawal
*/
synor_zk_error_t synor_zk_rollup_submit_withdrawal(
synor_zk_client_t* client,
const synor_zk_withdrawal_t* withdrawal,
char* tx_id,
size_t tx_id_len
);
/**
* Finalize current batch
*/
synor_zk_error_t synor_zk_rollup_finalize_batch(
synor_zk_client_t* client,
synor_zk_batch_t** batch
);
/**
* Free batch
*/
void synor_zk_batch_free(synor_zk_batch_t* batch);
/* ============================================================================
* State Operations
* ============================================================================ */
/**
* Get current state root
*/
synor_zk_error_t synor_zk_state_get_root(
synor_zk_client_t* client,
char* root,
size_t root_len
);
/**
* Get account state
*/
synor_zk_error_t synor_zk_state_get_account(
synor_zk_client_t* client,
const char* address,
synor_zk_account_state_t* account
);
/**
* Get merkle proof for account inclusion
*/
synor_zk_error_t synor_zk_state_get_merkle_proof(
synor_zk_client_t* client,
const char* address,
synor_zk_merkle_proof_t* proof
);
/**
* Verify merkle proof
*/
synor_zk_error_t synor_zk_state_verify_merkle_proof(
synor_zk_client_t* client,
const synor_zk_merkle_proof_t* proof,
bool* valid
);
/**
* Free merkle proof
*/
void synor_zk_merkle_proof_free(synor_zk_merkle_proof_t* proof);
/* ============================================================================
* Ceremony Operations
* ============================================================================ */
/**
* Get ceremony status
*/
synor_zk_error_t synor_zk_ceremony_get_status(
synor_zk_client_t* client,
synor_zk_circuit_type_t circuit_type,
synor_zk_proof_system_t system,
synor_zk_trusted_setup_t* setup
);
/**
* Contribute to ceremony
*/
synor_zk_error_t synor_zk_ceremony_contribute(
synor_zk_client_t* client,
synor_zk_circuit_type_t circuit_type,
const uint8_t* entropy,
size_t entropy_len,
synor_zk_proof_system_t system,
synor_zk_ceremony_contribution_t* contribution
);
/**
* Verify a contribution
*/
synor_zk_error_t synor_zk_ceremony_verify_contribution(
synor_zk_client_t* client,
synor_zk_circuit_type_t circuit_type,
const char* contribution_hash,
bool* valid
);
/**
* Free trusted setup
*/
void synor_zk_trusted_setup_free(synor_zk_trusted_setup_t* setup);
/* ============================================================================
* Utility Functions
* ============================================================================ */
/**
* Get proof system info
*/
synor_zk_proof_system_info_t synor_zk_get_proof_system_info(synor_zk_proof_system_t system);
/**
* Get error message
*/
const char* synor_zk_error_message(synor_zk_error_t error);
/**
* Free verification result
*/
void synor_zk_verification_result_free(synor_zk_verification_result_t* result);
/* ============================================================================
* Constants
* ============================================================================ */
#define SYNOR_ZK_MAX_BATCH_SIZE 1000
#define SYNOR_ZK_STATE_TREE_DEPTH 32
#define SYNOR_ZK_PROOF_EXPIRY_BLOCKS 100
#ifdef __cplusplus
}
#endif
#endif /* SYNOR_ZK_H */

View file

@ -0,0 +1,429 @@
/**
* Synor ZK SDK for C++
*
* Zero-Knowledge proof systems for ZK-Rollups and privacy.
*/
#ifndef SYNOR_ZK_HPP
#define SYNOR_ZK_HPP
#include <string>
#include <vector>
#include <memory>
#include <optional>
#include <chrono>
#include <future>
#include <stdexcept>
#include <map>
#include <cstdint>
namespace synor {
namespace zk {
/* ============================================================================
* Enumerations
* ============================================================================ */
/** Proof system backends */
enum class ProofSystem {
Groth16, ///< Smallest proofs (~192 bytes), fastest verification
Plonk, ///< Universal trusted setup, medium proofs (~512 bytes)
Stark ///< No trusted setup, largest proofs (~50KB)
};
/** Circuit types for different operations */
enum class CircuitType {
Transfer, ///< Single transfer between accounts
Batch, ///< Batch of multiple transfers
Deposit, ///< Deposit from L1 to L2
Withdraw ///< Withdrawal from L2 to L1
};
/** Rollup state */
enum class RollupState {
Active,
Paused,
Finalizing,
Finalized
};
/** Proof status */
enum class ProofStatus {
Generating,
Completed,
Failed,
Verified
};
/* ============================================================================
* Exception
* ============================================================================ */
class ZkError : public std::runtime_error {
public:
ZkError(const std::string& message,
const std::optional<std::string>& code = std::nullopt,
const std::optional<int>& status = std::nullopt)
: std::runtime_error(message), code_(code), status_(status) {}
const std::optional<std::string>& code() const { return code_; }
const std::optional<int>& status() const { return status_; }
private:
std::optional<std::string> code_;
std::optional<int> status_;
};
/* ============================================================================
* Data Types
* ============================================================================ */
/** Zero-knowledge proof */
struct Proof {
std::string id;
ProofSystem system;
CircuitType circuit_type;
std::vector<uint8_t> data;
std::vector<std::string> public_inputs;
size_t size;
uint64_t generation_time_ms;
uint64_t created_at;
};
/** Verification key for a circuit */
struct VerificationKey {
std::string circuit_id;
CircuitType circuit_type;
ProofSystem system;
std::vector<uint8_t> data;
size_t size;
};
/** Proving key for generating proofs */
struct ProvingKey {
std::string circuit_id;
CircuitType circuit_type;
ProofSystem system;
std::vector<uint8_t> data;
size_t size;
};
/** Circuit configuration */
struct CircuitConfig {
CircuitType type;
std::optional<size_t> max_batch_size;
std::optional<size_t> tree_depth;
std::optional<bool> verify_signatures;
std::optional<std::map<std::string, std::string>> custom_constraints;
};
/** Account state in the rollup */
struct AccountState {
std::string address;
std::string balance;
uint64_t nonce;
std::string pubkey_hash;
};
/** Transfer operation */
struct Transfer {
std::string from;
std::string to;
std::string amount;
std::string fee;
uint64_t nonce;
std::optional<std::string> signature;
};
/** Deposit operation (L1 -> L2) */
struct Deposit {
std::string l1_tx_hash;
std::string recipient;
std::string amount;
std::optional<std::string> token;
};
/** Withdrawal operation (L2 -> L1) */
struct Withdrawal {
std::string sender;
std::string recipient;
std::string amount;
std::optional<std::string> token;
uint64_t nonce;
std::optional<std::string> signature;
};
/** Rollup batch */
struct Batch {
uint64_t batch_number;
std::string prev_state_root;
std::string new_state_root;
std::vector<Transfer> transfers;
std::vector<Deposit> deposits;
std::vector<Withdrawal> withdrawals;
std::optional<Proof> proof;
uint64_t timestamp;
};
/** Rollup statistics */
struct RollupStats {
uint64_t current_batch;
uint64_t total_transactions;
uint64_t total_proofs;
uint64_t avg_proof_time_ms;
std::string state_root;
uint64_t account_count;
std::string tvl;
};
/** Proof request */
struct ProofRequest {
CircuitType circuit_type;
std::vector<std::string> public_inputs;
std::vector<std::string> private_inputs;
std::optional<ProofSystem> system;
};
/** Verification result */
struct VerificationResult {
bool valid;
uint64_t verification_time_ms;
std::optional<std::string> error;
};
/** Merkle proof for state inclusion */
struct MerkleProof {
std::string leaf;
std::vector<std::string> path;
std::vector<uint8_t> indices;
std::string root;
};
/** Ceremony contribution */
struct CeremonyContribution {
std::string contributor_id;
std::string hash;
uint64_t timestamp;
bool verified;
};
/** Trusted setup ceremony */
struct TrustedSetup {
std::string id;
CircuitType circuit_type;
ProofSystem system;
size_t contribution_count;
std::string latest_hash;
bool complete;
std::vector<CeremonyContribution> contributions;
};
/** SDK configuration */
struct ZkConfig {
std::string api_key;
std::string endpoint = "https://zk.synor.io/v1";
std::string ws_endpoint = "wss://zk.synor.io/v1/ws";
std::chrono::milliseconds timeout{60000};
int retries = 3;
ProofSystem default_proof_system = ProofSystem::Groth16;
bool debug = false;
};
/** Proof system characteristics */
struct ProofSystemInfo {
std::string name;
size_t proof_size;
uint32_t verification_time_ms;
bool trusted_setup;
bool universal;
};
/* ============================================================================
* Client Classes
* ============================================================================ */
class SynorZk;
/** Proofs sub-client */
class ProofsClient {
public:
explicit ProofsClient(SynorZk& zk) : zk_(zk) {}
std::future<Proof> generate(const ProofRequest& request);
std::future<VerificationResult> verify(const Proof& proof);
std::future<Proof> get(const std::string& proof_id);
std::future<std::vector<Proof>> list(std::optional<int> limit = std::nullopt,
std::optional<int> offset = std::nullopt);
std::future<std::vector<uint8_t>> serialize(const Proof& proof);
std::future<Proof> deserialize(const std::vector<uint8_t>& data, ProofSystem system);
private:
SynorZk& zk_;
};
/** Circuits sub-client */
class CircuitsClient {
public:
explicit CircuitsClient(SynorZk& zk) : zk_(zk) {}
std::future<VerificationKey> getVerificationKey(CircuitType circuit_type,
std::optional<ProofSystem> system = std::nullopt);
std::future<ProvingKey> getProvingKey(CircuitType circuit_type,
std::optional<ProofSystem> system = std::nullopt);
std::future<std::vector<CircuitConfig>> list();
std::future<CircuitConfig> getConfig(CircuitType circuit_type);
std::future<std::string> compile(const CircuitConfig& config);
private:
SynorZk& zk_;
};
/** Rollup sub-client */
class RollupClient {
public:
explicit RollupClient(SynorZk& zk) : zk_(zk) {}
std::future<RollupStats> getStats();
std::future<Batch> getCurrentBatch();
std::future<Batch> getBatch(uint64_t batch_number);
std::future<std::string> submitTransfer(const Transfer& transfer);
std::future<std::string> submitDeposit(const Deposit& deposit);
std::future<std::string> submitWithdrawal(const Withdrawal& withdrawal);
std::future<Batch> finalizeBatch();
std::future<std::vector<Transfer>> getPendingTransactions();
private:
SynorZk& zk_;
};
/** State sub-client */
class StateClient {
public:
explicit StateClient(SynorZk& zk) : zk_(zk) {}
std::future<std::string> getRoot();
std::future<AccountState> getAccount(const std::string& address);
std::future<MerkleProof> getMerkleProof(const std::string& address);
std::future<bool> verifyMerkleProof(const MerkleProof& proof);
std::future<std::map<std::string, std::string>> getStateAtBatch(uint64_t batch_number);
private:
SynorZk& zk_;
};
/** Ceremony sub-client */
class CeremonyClient {
public:
explicit CeremonyClient(SynorZk& zk) : zk_(zk) {}
std::future<TrustedSetup> getStatus(CircuitType circuit_type,
std::optional<ProofSystem> system = std::nullopt);
std::future<CeremonyContribution> contribute(CircuitType circuit_type,
const std::vector<uint8_t>& entropy,
std::optional<ProofSystem> system = std::nullopt);
std::future<bool> verifyContribution(CircuitType circuit_type,
const std::string& contribution_hash);
std::future<std::vector<CeremonyContribution>> listContributions(CircuitType circuit_type);
private:
SynorZk& zk_;
};
/**
* Synor ZK SDK Client
*
* Zero-Knowledge proof systems for ZK-Rollups and privacy.
*
* Example:
* @code
* synor::zk::ZkConfig config;
* config.api_key = "your-api-key";
* synor::zk::SynorZk zk(config);
*
* // Generate a proof
* synor::zk::ProofRequest request;
* request.circuit_type = synor::zk::CircuitType::Transfer;
* request.public_inputs = {...};
* request.private_inputs = {...};
* auto proof = zk.proofs().generate(request).get();
*
* // Verify the proof
* auto result = zk.proofs().verify(proof).get();
* std::cout << "Valid: " << result.valid << std::endl;
* @endcode
*/
class SynorZk {
public:
explicit SynorZk(const ZkConfig& config);
~SynorZk();
// Non-copyable
SynorZk(const SynorZk&) = delete;
SynorZk& operator=(const SynorZk&) = delete;
// Movable
SynorZk(SynorZk&&) noexcept;
SynorZk& operator=(SynorZk&&) noexcept;
/** Get the default proof system */
ProofSystem defaultProofSystem() const { return config_.default_proof_system; }
/** Health check */
std::future<bool> healthCheck();
/** Get service info */
std::future<std::map<std::string, std::string>> getInfo();
/** Close the client */
void close();
/** Check if client is closed */
bool isClosed() const { return closed_; }
/** Sub-clients */
ProofsClient& proofs() { return proofs_; }
CircuitsClient& circuits() { return circuits_; }
RollupClient& rollup() { return rollup_; }
StateClient& state() { return state_; }
CeremonyClient& ceremony() { return ceremony_; }
// Internal HTTP methods (public for sub-clients)
std::future<std::map<std::string, std::string>> get(const std::string& path);
std::future<std::map<std::string, std::string>> post(const std::string& path,
const std::map<std::string, std::string>& body);
private:
ZkConfig config_;
bool closed_ = false;
ProofsClient proofs_;
CircuitsClient circuits_;
RollupClient rollup_;
StateClient state_;
CeremonyClient ceremony_;
};
/* ============================================================================
* Utility Functions
* ============================================================================ */
/** Get proof system info */
ProofSystemInfo getProofSystemInfo(ProofSystem system);
/** Convert proof system to string */
std::string proofSystemToString(ProofSystem system);
/** Convert circuit type to string */
std::string circuitTypeToString(CircuitType type);
/* ============================================================================
* Constants
* ============================================================================ */
constexpr size_t MAX_BATCH_SIZE = 1000;
constexpr size_t STATE_TREE_DEPTH = 32;
constexpr uint64_t PROOF_EXPIRY_BLOCKS = 100;
} // namespace zk
} // namespace synor
#endif // SYNOR_ZK_HPP

View file

@ -0,0 +1,339 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
namespace Synor.Zk;
/// <summary>
/// Synor ZK SDK for C#/.NET
///
/// Zero-Knowledge proof systems for ZK-Rollups and privacy.
/// </summary>
public class SynorZk : IDisposable
{
private readonly ZkConfig _config;
private readonly HttpClient _httpClient;
private readonly JsonSerializerOptions _jsonOptions;
private bool _closed;
public ProofsClient Proofs { get; }
public CircuitsClient Circuits { get; }
public RollupClient Rollup { get; }
public StateClient State { get; }
public CeremonyClient Ceremony { get; }
public SynorZk(ZkConfig config)
{
_config = config;
_httpClient = new HttpClient
{
BaseAddress = new Uri(config.Endpoint),
Timeout = TimeSpan.FromMilliseconds(config.Timeout)
};
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {config.ApiKey}");
_httpClient.DefaultRequestHeaders.Add("X-SDK-Version", "csharp/0.1.0");
_jsonOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
Converters = { new JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseLower) }
};
Proofs = new ProofsClient(this);
Circuits = new CircuitsClient(this);
Rollup = new RollupClient(this);
State = new StateClient(this);
Ceremony = new CeremonyClient(this);
}
public ProofSystem DefaultProofSystem => _config.DefaultProofSystem;
public async Task<bool> HealthCheckAsync(CancellationToken ct = default)
{
try
{
var result = await GetAsync<Dictionary<string, object>>("/health", ct);
return result.TryGetValue("status", out var status) && status?.ToString() == "healthy";
}
catch
{
return false;
}
}
public Task<Dictionary<string, object>> GetInfoAsync(CancellationToken ct = default) =>
GetAsync<Dictionary<string, object>>("/info", ct);
public void Close()
{
_closed = true;
_httpClient.Dispose();
}
public bool IsClosed => _closed;
public void Dispose()
{
Close();
GC.SuppressFinalize(this);
}
internal async Task<T> GetAsync<T>(string path, CancellationToken ct = default)
{
CheckClosed();
var response = await _httpClient.GetAsync(path, ct);
return await HandleResponseAsync<T>(response);
}
internal async Task<T> PostAsync<T>(string path, object? body = null, CancellationToken ct = default)
{
CheckClosed();
var content = body != null
? JsonContent.Create(body, options: _jsonOptions)
: JsonContent.Create(new { });
var response = await _httpClient.PostAsync(path, content, ct);
return await HandleResponseAsync<T>(response);
}
private async Task<T> HandleResponseAsync<T>(HttpResponseMessage response)
{
var json = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
var error = JsonSerializer.Deserialize<Dictionary<string, object>>(json, _jsonOptions) ?? new();
throw new ZkException(
error.TryGetValue("message", out var msg) ? msg?.ToString() ?? $"HTTP {(int)response.StatusCode}" : $"HTTP {(int)response.StatusCode}",
error.TryGetValue("code", out var code) ? code?.ToString() : null,
(int)response.StatusCode
);
}
return JsonSerializer.Deserialize<T>(json, _jsonOptions)!;
}
private void CheckClosed()
{
if (_closed) throw new ZkException("Client has been closed", "CLIENT_CLOSED");
}
}
/// <summary>Proofs sub-client</summary>
public class ProofsClient
{
private readonly SynorZk _zk;
internal ProofsClient(SynorZk zk) => _zk = zk;
public async Task<Proof> GenerateAsync(ProofRequest request, CancellationToken ct = default)
{
var body = new Dictionary<string, object>
{
["circuit_type"] = request.CircuitType.ToApiString(),
["public_inputs"] = request.PublicInputs,
["private_inputs"] = request.PrivateInputs,
["system"] = (request.System ?? _zk.DefaultProofSystem).ToApiString()
};
return await _zk.PostAsync<Proof>("/proofs/generate", body, ct);
}
public async Task<VerificationResult> VerifyAsync(Proof proof, CancellationToken ct = default)
{
var body = new Dictionary<string, object>
{
["proof_id"] = proof.Id,
["data"] = proof.Data,
["public_inputs"] = proof.PublicInputs,
["system"] = proof.System.ToApiString(),
["circuit_type"] = proof.CircuitType.ToApiString()
};
return await _zk.PostAsync<VerificationResult>("/proofs/verify", body, ct);
}
public Task<Proof> GetAsync(string proofId, CancellationToken ct = default) =>
_zk.GetAsync<Proof>($"/proofs/{proofId}", ct);
public async Task<List<Proof>> ListAsync(int? limit = null, int? offset = null, CancellationToken ct = default)
{
var path = "/proofs";
var qs = new List<string>();
if (limit.HasValue) qs.Add($"limit={limit}");
if (offset.HasValue) qs.Add($"offset={offset}");
if (qs.Count > 0) path += "?" + string.Join("&", qs);
var result = await _zk.GetAsync<ProofsListResponse>(path, ct);
return result.Proofs ?? new List<Proof>();
}
public async Task<byte[]> SerializeAsync(Proof proof, CancellationToken ct = default)
{
var result = await _zk.PostAsync<SerializeResponse>("/proofs/serialize", new { proof_id = proof.Id }, ct);
return Convert.FromBase64String(result.Data);
}
public Task<Proof> DeserializeAsync(byte[] data, ProofSystem system, CancellationToken ct = default) =>
_zk.PostAsync<Proof>("/proofs/deserialize", new { data = Convert.ToBase64String(data), system = system.ToApiString() }, ct);
}
/// <summary>Circuits sub-client</summary>
public class CircuitsClient
{
private readonly SynorZk _zk;
internal CircuitsClient(SynorZk zk) => _zk = zk;
public Task<VerificationKey> GetVerificationKeyAsync(CircuitType circuitType, ProofSystem? system = null, CancellationToken ct = default)
{
var sys = system ?? _zk.DefaultProofSystem;
return _zk.GetAsync<VerificationKey>($"/circuits/{circuitType.ToApiString()}/vk?system={sys.ToApiString()}", ct);
}
public Task<ProvingKey> GetProvingKeyAsync(CircuitType circuitType, ProofSystem? system = null, CancellationToken ct = default)
{
var sys = system ?? _zk.DefaultProofSystem;
return _zk.GetAsync<ProvingKey>($"/circuits/{circuitType.ToApiString()}/pk?system={sys.ToApiString()}", ct);
}
public async Task<List<CircuitConfig>> ListAsync(CancellationToken ct = default)
{
var result = await _zk.GetAsync<CircuitsListResponse>("/circuits", ct);
return result.Circuits ?? new List<CircuitConfig>();
}
public Task<CircuitConfig> GetConfigAsync(CircuitType circuitType, CancellationToken ct = default) =>
_zk.GetAsync<CircuitConfig>($"/circuits/{circuitType.ToApiString()}/config", ct);
public async Task<string> CompileAsync(CircuitConfig config, CancellationToken ct = default)
{
var result = await _zk.PostAsync<CircuitIdResponse>("/circuits/compile", config, ct);
return result.CircuitId;
}
}
/// <summary>Rollup sub-client</summary>
public class RollupClient
{
private readonly SynorZk _zk;
internal RollupClient(SynorZk zk) => _zk = zk;
public Task<RollupStats> GetStatsAsync(CancellationToken ct = default) =>
_zk.GetAsync<RollupStats>("/rollup/stats", ct);
public Task<Batch> GetCurrentBatchAsync(CancellationToken ct = default) =>
_zk.GetAsync<Batch>("/rollup/batch/current", ct);
public Task<Batch> GetBatchAsync(long batchNumber, CancellationToken ct = default) =>
_zk.GetAsync<Batch>($"/rollup/batch/{batchNumber}", ct);
public async Task<string> SubmitTransferAsync(Transfer transfer, CancellationToken ct = default)
{
var result = await _zk.PostAsync<TxIdResponse>("/rollup/transfer", transfer, ct);
return result.TxId;
}
public async Task<string> SubmitDepositAsync(Deposit deposit, CancellationToken ct = default)
{
var result = await _zk.PostAsync<TxIdResponse>("/rollup/deposit", deposit, ct);
return result.TxId;
}
public async Task<string> SubmitWithdrawalAsync(Withdrawal withdrawal, CancellationToken ct = default)
{
var result = await _zk.PostAsync<TxIdResponse>("/rollup/withdraw", withdrawal, ct);
return result.TxId;
}
public Task<Batch> FinalizeBatchAsync(CancellationToken ct = default) =>
_zk.PostAsync<Batch>("/rollup/batch/finalize", null, ct);
public async Task<List<Transfer>> GetPendingTransactionsAsync(CancellationToken ct = default)
{
var result = await _zk.GetAsync<TransactionsListResponse>("/rollup/pending", ct);
return result.Transactions ?? new List<Transfer>();
}
}
/// <summary>State sub-client</summary>
public class StateClient
{
private readonly SynorZk _zk;
internal StateClient(SynorZk zk) => _zk = zk;
public async Task<string> GetRootAsync(CancellationToken ct = default)
{
var result = await _zk.GetAsync<RootResponse>("/state/root", ct);
return result.Root;
}
public Task<AccountState> GetAccountAsync(string address, CancellationToken ct = default) =>
_zk.GetAsync<AccountState>($"/state/account/{address}", ct);
public Task<MerkleProof> GetMerkleProofAsync(string address, CancellationToken ct = default) =>
_zk.GetAsync<MerkleProof>($"/state/proof/{address}", ct);
public async Task<bool> VerifyMerkleProofAsync(MerkleProof proof, CancellationToken ct = default)
{
var result = await _zk.PostAsync<ValidResponse>("/state/proof/verify", proof, ct);
return result.Valid;
}
public Task<Dictionary<string, object>> GetStateAtBatchAsync(long batchNumber, CancellationToken ct = default) =>
_zk.GetAsync<Dictionary<string, object>>($"/state/batch/{batchNumber}", ct);
}
/// <summary>Ceremony sub-client</summary>
public class CeremonyClient
{
private readonly SynorZk _zk;
internal CeremonyClient(SynorZk zk) => _zk = zk;
public Task<TrustedSetup> GetStatusAsync(CircuitType circuitType, ProofSystem? system = null, CancellationToken ct = default)
{
var sys = system ?? _zk.DefaultProofSystem;
return _zk.GetAsync<TrustedSetup>($"/ceremony/{circuitType.ToApiString()}?system={sys.ToApiString()}", ct);
}
public Task<CeremonyContribution> ContributeAsync(CircuitType circuitType, byte[] entropy, ProofSystem? system = null, CancellationToken ct = default)
{
var sys = system ?? _zk.DefaultProofSystem;
return _zk.PostAsync<CeremonyContribution>("/ceremony/contribute", new
{
circuit_type = circuitType.ToApiString(),
entropy = Convert.ToBase64String(entropy),
system = sys.ToApiString()
}, ct);
}
public async Task<bool> VerifyContributionAsync(CircuitType circuitType, string contributionHash, CancellationToken ct = default)
{
var result = await _zk.PostAsync<ValidResponse>("/ceremony/verify", new
{
circuit_type = circuitType.ToApiString(),
contribution_hash = contributionHash
}, ct);
return result.Valid;
}
public async Task<List<CeremonyContribution>> ListContributionsAsync(CircuitType circuitType, CancellationToken ct = default)
{
var result = await _zk.GetAsync<ContributionsListResponse>($"/ceremony/{circuitType.ToApiString()}/contributions", ct);
return result.Contributions ?? new List<CeremonyContribution>();
}
}
// Response helper types
internal record ProofsListResponse(List<Proof>? Proofs);
internal record CircuitsListResponse(List<CircuitConfig>? Circuits);
internal record TransactionsListResponse(List<Transfer>? Transactions);
internal record ContributionsListResponse(List<CeremonyContribution>? Contributions);
internal record SerializeResponse(string Data);
internal record CircuitIdResponse(string CircuitId);
internal record TxIdResponse(string TxId);
internal record RootResponse(string Root);
internal record ValidResponse(bool Valid);

View file

@ -0,0 +1,246 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Synor.Zk;
/// <summary>Proof system backends</summary>
public enum ProofSystem
{
/// <summary>Smallest proofs (~192 bytes), fastest verification</summary>
Groth16,
/// <summary>Universal trusted setup, medium proofs (~512 bytes)</summary>
Plonk,
/// <summary>No trusted setup, largest proofs (~50KB)</summary>
Stark
}
/// <summary>Circuit types for different operations</summary>
public enum CircuitType
{
/// <summary>Single transfer between accounts</summary>
Transfer,
/// <summary>Batch of multiple transfers</summary>
Batch,
/// <summary>Deposit from L1 to L2</summary>
Deposit,
/// <summary>Withdrawal from L2 to L1</summary>
Withdraw
}
/// <summary>Rollup state</summary>
public enum RollupState { Active, Paused, Finalizing, Finalized }
/// <summary>Proof status</summary>
public enum ProofStatus { Generating, Completed, Failed, Verified }
/// <summary>Zero-knowledge proof</summary>
public record Proof(
string Id,
ProofSystem System,
CircuitType CircuitType,
string Data,
List<string> PublicInputs,
int Size,
long GenerationTimeMs,
long CreatedAt
);
/// <summary>Verification key for a circuit</summary>
public record VerificationKey(
string CircuitId,
CircuitType CircuitType,
ProofSystem System,
string Data,
int Size
);
/// <summary>Proving key for generating proofs</summary>
public record ProvingKey(
string CircuitId,
CircuitType CircuitType,
ProofSystem System,
string Data,
int Size
);
/// <summary>Circuit configuration</summary>
public record CircuitConfig(
CircuitType Type,
int? MaxBatchSize = null,
int? TreeDepth = null,
bool? VerifySignatures = null,
Dictionary<string, object>? CustomConstraints = null
);
/// <summary>Account state in the rollup</summary>
public record AccountState(
string Address,
string Balance,
long Nonce,
string PubkeyHash
);
/// <summary>Transfer operation</summary>
public record Transfer(
string From,
string To,
string Amount,
string Fee,
long Nonce,
string? Signature = null
);
/// <summary>Deposit operation (L1 -> L2)</summary>
public record Deposit(
string L1TxHash,
string Recipient,
string Amount,
string? Token = null
);
/// <summary>Withdrawal operation (L2 -> L1)</summary>
public record Withdrawal(
string Sender,
string Recipient,
string Amount,
string? Token,
long Nonce,
string? Signature = null
);
/// <summary>Rollup batch</summary>
public record Batch(
long BatchNumber,
string PrevStateRoot,
string NewStateRoot,
List<Transfer> Transfers,
List<Deposit> Deposits,
List<Withdrawal> Withdrawals,
Proof? Proof,
long Timestamp
);
/// <summary>Rollup statistics</summary>
public record RollupStats(
long CurrentBatch,
long TotalTransactions,
long TotalProofs,
long AvgProofTimeMs,
string StateRoot,
long AccountCount,
string Tvl
);
/// <summary>Proof request</summary>
public record ProofRequest(
CircuitType CircuitType,
List<string> PublicInputs,
List<string> PrivateInputs,
ProofSystem? System = null
);
/// <summary>Verification result</summary>
public record VerificationResult(
bool Valid,
long VerificationTimeMs,
string? Error = null
);
/// <summary>Merkle proof for state inclusion</summary>
public record MerkleProof(
string Leaf,
List<string> Path,
List<int> Indices,
string Root
);
/// <summary>Ceremony contribution</summary>
public record CeremonyContribution(
string ContributorId,
string Hash,
long Timestamp,
bool Verified
);
/// <summary>Trusted setup ceremony</summary>
public record TrustedSetup(
string Id,
CircuitType CircuitType,
ProofSystem System,
int ContributionCount,
string LatestHash,
bool Complete,
List<CeremonyContribution> Contributions
);
/// <summary>ZK SDK configuration</summary>
public record ZkConfig(
string ApiKey,
string Endpoint = "https://zk.synor.io/v1",
string WsEndpoint = "wss://zk.synor.io/v1/ws",
int Timeout = 60000,
int Retries = 3,
ProofSystem DefaultProofSystem = ProofSystem.Groth16,
bool Debug = false
);
/// <summary>ZK SDK exception</summary>
public class ZkException : Exception
{
public string? Code { get; }
public int? Status { get; }
public ZkException(string message, string? code = null, int? status = null)
: base(message)
{
Code = code;
Status = status;
}
}
/// <summary>Proof system characteristics</summary>
public record ProofSystemInfo(
string Name,
int ProofSize,
int VerificationTimeMs,
bool TrustedSetup,
bool Universal
);
/// <summary>Extension methods</summary>
public static class ZkExtensions
{
public static string ToApiString(this ProofSystem system) => system switch
{
ProofSystem.Groth16 => "groth16",
ProofSystem.Plonk => "plonk",
ProofSystem.Stark => "stark",
_ => "groth16"
};
public static string ToApiString(this CircuitType type) => type switch
{
CircuitType.Transfer => "transfer",
CircuitType.Batch => "batch",
CircuitType.Deposit => "deposit",
CircuitType.Withdraw => "withdraw",
_ => "transfer"
};
public static ProofSystemInfo GetInfo(this ProofSystem system) => system switch
{
ProofSystem.Groth16 => new ProofSystemInfo("Groth16", 192, 10, true, false),
ProofSystem.Plonk => new ProofSystemInfo("PLONK", 512, 15, true, true),
ProofSystem.Stark => new ProofSystemInfo("STARK", 50000, 30, false, true),
_ => throw new ArgumentOutOfRangeException(nameof(system))
};
}
/// <summary>Constants</summary>
public static class ZkConstants
{
public const int MaxBatchSize = 1000;
public const int StateTreeDepth = 32;
public const int ProofExpiryBlocks = 100;
}

View file

@ -0,0 +1,415 @@
/// Synor ZK SDK Client for Flutter/Dart
///
/// Zero-Knowledge proof systems for ZK-Rollups and privacy.
library synor_zk_client;
import 'dart:convert';
import 'dart:typed_data';
import 'package:http/http.dart' as http;
import 'types.dart';
export 'types.dart';
/// Synor ZK SDK Client
///
/// Provides zero-knowledge proof generation and verification for ZK-Rollups.
///
/// Example:
/// ```dart
/// final zk = SynorZk(ZkConfig(apiKey: 'your-api-key'));
///
/// // Generate a proof
/// final proof = await zk.proofs.generate(ProofRequest(
/// circuitType: CircuitType.transfer,
/// publicInputs: [...],
/// privateInputs: [...],
/// ));
///
/// // Verify the proof
/// final result = await zk.proofs.verify(proof);
/// print('Valid: ${result.valid}');
/// ```
class SynorZk {
final ZkConfig config;
final http.Client _client;
bool _closed = false;
late final ProofsClient proofs;
late final CircuitsClient circuits;
late final RollupClient rollup;
late final StateClient state;
late final CeremonyClient ceremony;
SynorZk(this.config, {http.Client? client})
: _client = client ?? http.Client() {
proofs = ProofsClient(this);
circuits = CircuitsClient(this);
rollup = RollupClient(this);
state = StateClient(this);
ceremony = CeremonyClient(this);
}
/// Get the default proof system
ProofSystem get defaultProofSystem => config.defaultProofSystem;
/// Health check
Future<bool> healthCheck() async {
try {
final result = await _get('/health');
return result['status'] == 'healthy';
} catch (_) {
return false;
}
}
/// Get service info
Future<Map<String, dynamic>> getInfo() async {
return _get('/info');
}
/// Close the client
void close() {
_closed = true;
_client.close();
}
/// Check if client is closed
bool get isClosed => _closed;
// Internal HTTP methods
Future<Map<String, dynamic>> _get(String path) async {
return _request('GET', path);
}
Future<Map<String, dynamic>> _post(String path, [Map<String, dynamic>? body]) async {
return _request('POST', path, body);
}
Future<Map<String, dynamic>> _delete(String path) async {
return _request('DELETE', path);
}
Future<Map<String, dynamic>> _request(
String method,
String path, [
Map<String, dynamic>? body,
]) async {
if (_closed) {
throw const ZkError('Client has been closed', code: 'CLIENT_CLOSED');
}
final url = Uri.parse('${config.endpoint}$path');
final headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${config.apiKey}',
'X-SDK-Version': 'flutter/0.1.0',
};
Exception? lastError;
for (var attempt = 0; attempt <= config.retries; attempt++) {
try {
http.Response response;
switch (method) {
case 'GET':
response = await _client
.get(url, headers: headers)
.timeout(config.timeout);
break;
case 'POST':
response = await _client
.post(url, headers: headers, body: body != null ? jsonEncode(body) : null)
.timeout(config.timeout);
break;
case 'DELETE':
response = await _client
.delete(url, headers: headers)
.timeout(config.timeout);
break;
default:
throw ArgumentError('Unknown method: $method');
}
if (response.statusCode >= 400) {
final error = response.body.isNotEmpty
? jsonDecode(response.body) as Map<String, dynamic>
: <String, dynamic>{};
throw ZkError(
error['message'] as String? ?? 'HTTP ${response.statusCode}',
code: error['code'] as String?,
status: response.statusCode,
);
}
return jsonDecode(response.body) as Map<String, dynamic>;
} on ZkError {
rethrow;
} catch (e) {
lastError = e as Exception;
if (attempt < config.retries) {
await Future.delayed(Duration(milliseconds: 100 * (1 << attempt)));
}
}
}
throw ZkError(
lastError?.toString() ?? 'Request failed',
code: 'NETWORK_ERROR',
);
}
}
/// Proofs sub-client
class ProofsClient {
final SynorZk _zk;
ProofsClient(this._zk);
/// Generate a zero-knowledge proof
Future<Proof> generate(ProofRequest request) async {
final body = request.toJson();
body['system'] ??= _zk.defaultProofSystem.value;
final result = await _zk._post('/proofs/generate', body);
return Proof.fromJson(result);
}
/// Verify a proof
Future<VerificationResult> verify(Proof proof) async {
final result = await _zk._post('/proofs/verify', {
'proof_id': proof.id,
'data': proof.data,
'public_inputs': proof.publicInputs,
'system': proof.system.value,
'circuit_type': proof.circuitType.value,
});
return VerificationResult.fromJson(result);
}
/// Get a proof by ID
Future<Proof> get(String proofId) async {
final result = await _zk._get('/proofs/$proofId');
return Proof.fromJson(result);
}
/// List recent proofs
Future<List<Proof>> list({int? limit, int? offset}) async {
var path = '/proofs';
final params = <String>[];
if (limit != null) params.add('limit=$limit');
if (offset != null) params.add('offset=$offset');
if (params.isNotEmpty) path += '?${params.join('&')}';
final result = await _zk._get(path);
final proofs = result['proofs'] as List?;
return proofs?.map((p) => Proof.fromJson(p as Map<String, dynamic>)).toList() ?? [];
}
/// Serialize a proof to bytes
Future<Uint8List> serialize(Proof proof) async {
final result = await _zk._post('/proofs/serialize', {'proof_id': proof.id});
return base64Decode(result['data'] as String);
}
/// Deserialize bytes to a proof
Future<Proof> deserialize(Uint8List data, ProofSystem system) async {
final result = await _zk._post('/proofs/deserialize', {
'data': base64Encode(data),
'system': system.value,
});
return Proof.fromJson(result);
}
}
/// Circuits sub-client
class CircuitsClient {
final SynorZk _zk;
CircuitsClient(this._zk);
/// Get verification key for a circuit
Future<VerificationKey> getVerificationKey(
CircuitType circuitType, [
ProofSystem? system,
]) async {
final sys = system ?? _zk.defaultProofSystem;
final result = await _zk._get('/circuits/${circuitType.value}/vk?system=${sys.value}');
return VerificationKey.fromJson(result);
}
/// Get proving key for a circuit
Future<ProvingKey> getProvingKey(
CircuitType circuitType, [
ProofSystem? system,
]) async {
final sys = system ?? _zk.defaultProofSystem;
final result = await _zk._get('/circuits/${circuitType.value}/pk?system=${sys.value}');
return ProvingKey.fromJson(result);
}
/// List available circuits
Future<List<CircuitConfig>> list() async {
final result = await _zk._get('/circuits');
final circuits = result['circuits'] as List?;
return circuits?.map((c) => CircuitConfig.fromJson(c as Map<String, dynamic>)).toList() ?? [];
}
/// Get circuit configuration
Future<CircuitConfig> getConfig(CircuitType circuitType) async {
final result = await _zk._get('/circuits/${circuitType.value}/config');
return CircuitConfig.fromJson(result);
}
/// Compile a custom circuit
Future<String> compile(CircuitConfig config) async {
final result = await _zk._post('/circuits/compile', config.toJson());
return result['circuit_id'] as String;
}
}
/// Rollup sub-client
class RollupClient {
final SynorZk _zk;
RollupClient(this._zk);
/// Get rollup statistics
Future<RollupStats> getStats() async {
final result = await _zk._get('/rollup/stats');
return RollupStats.fromJson(result);
}
/// Get current batch
Future<Batch> getCurrentBatch() async {
final result = await _zk._get('/rollup/batch/current');
return Batch.fromJson(result);
}
/// Get batch by number
Future<Batch> getBatch(int batchNumber) async {
final result = await _zk._get('/rollup/batch/$batchNumber');
return Batch.fromJson(result);
}
/// Submit a transfer
Future<String> submitTransfer(Transfer transfer) async {
final result = await _zk._post('/rollup/transfer', transfer.toJson());
return result['tx_id'] as String;
}
/// Submit a deposit
Future<String> submitDeposit(Deposit deposit) async {
final result = await _zk._post('/rollup/deposit', deposit.toJson());
return result['tx_id'] as String;
}
/// Submit a withdrawal
Future<String> submitWithdrawal(Withdrawal withdrawal) async {
final result = await _zk._post('/rollup/withdraw', withdrawal.toJson());
return result['tx_id'] as String;
}
/// Finalize current batch
Future<Batch> finalizeBatch() async {
final result = await _zk._post('/rollup/batch/finalize', {});
return Batch.fromJson(result);
}
/// Get pending transactions
Future<List<Transfer>> getPendingTransactions() async {
final result = await _zk._get('/rollup/pending');
final transactions = result['transactions'] as List?;
return transactions?.map((t) => Transfer.fromJson(t as Map<String, dynamic>)).toList() ?? [];
}
}
/// State sub-client
class StateClient {
final SynorZk _zk;
StateClient(this._zk);
/// Get current state root
Future<String> getRoot() async {
final result = await _zk._get('/state/root');
return result['root'] as String;
}
/// Get account state
Future<AccountState> getAccount(String address) async {
final result = await _zk._get('/state/account/$address');
return AccountState.fromJson(result);
}
/// Get merkle proof for account inclusion
Future<MerkleProof> getMerkleProof(String address) async {
final result = await _zk._get('/state/proof/$address');
return MerkleProof.fromJson(result);
}
/// Verify merkle proof
Future<bool> verifyMerkleProof(MerkleProof proof) async {
final result = await _zk._post('/state/proof/verify', proof.toJson());
return result['valid'] as bool;
}
/// Get state at specific batch
Future<Map<String, dynamic>> getStateAtBatch(int batchNumber) async {
return _zk._get('/state/batch/$batchNumber');
}
}
/// Ceremony sub-client (trusted setup)
class CeremonyClient {
final SynorZk _zk;
CeremonyClient(this._zk);
/// Get ceremony status
Future<TrustedSetup> getStatus(
CircuitType circuitType, [
ProofSystem? system,
]) async {
final sys = system ?? _zk.defaultProofSystem;
final result = await _zk._get('/ceremony/${circuitType.value}?system=${sys.value}');
return TrustedSetup.fromJson(result);
}
/// Contribute to ceremony
Future<CeremonyContribution> contribute(
CircuitType circuitType,
Uint8List entropy, [
ProofSystem? system,
]) async {
final sys = system ?? _zk.defaultProofSystem;
final result = await _zk._post('/ceremony/contribute', {
'circuit_type': circuitType.value,
'entropy': base64Encode(entropy),
'system': sys.value,
});
return CeremonyContribution.fromJson(result);
}
/// Verify a contribution
Future<bool> verifyContribution(
CircuitType circuitType,
String contributionHash,
) async {
final result = await _zk._post('/ceremony/verify', {
'circuit_type': circuitType.value,
'contribution_hash': contributionHash,
});
return result['valid'] as bool;
}
/// List contributions
Future<List<CeremonyContribution>> listContributions(
CircuitType circuitType,
) async {
final result = await _zk._get('/ceremony/${circuitType.value}/contributions');
final contributions = result['contributions'] as List?;
return contributions
?.map((c) => CeremonyContribution.fromJson(c as Map<String, dynamic>))
.toList() ??
[];
}
}

View file

@ -0,0 +1,682 @@
/// Synor ZK SDK Types for Flutter/Dart
///
/// Zero-Knowledge proof systems for ZK-Rollups and privacy.
library synor_zk_types;
import 'dart:convert';
import 'dart:typed_data';
/// Proof system backends
enum ProofSystem {
/// Groth16 - smallest proofs (~192 bytes), fastest verification
groth16,
/// PLONK - universal trusted setup, medium proofs (~512 bytes)
plonk,
/// STARK - no trusted setup, largest proofs (~50KB)
stark,
}
extension ProofSystemExtension on ProofSystem {
String get value {
switch (this) {
case ProofSystem.groth16:
return 'groth16';
case ProofSystem.plonk:
return 'plonk';
case ProofSystem.stark:
return 'stark';
}
}
static ProofSystem fromString(String value) {
switch (value) {
case 'groth16':
return ProofSystem.groth16;
case 'plonk':
return ProofSystem.plonk;
case 'stark':
return ProofSystem.stark;
default:
return ProofSystem.groth16;
}
}
}
/// Circuit types for different operations
enum CircuitType {
/// Single transfer between accounts
transfer,
/// Batch of multiple transfers
batch,
/// Deposit from L1 to L2
deposit,
/// Withdrawal from L2 to L1
withdraw,
}
extension CircuitTypeExtension on CircuitType {
String get value {
switch (this) {
case CircuitType.transfer:
return 'transfer';
case CircuitType.batch:
return 'batch';
case CircuitType.deposit:
return 'deposit';
case CircuitType.withdraw:
return 'withdraw';
}
}
static CircuitType fromString(String value) {
switch (value) {
case 'transfer':
return CircuitType.transfer;
case 'batch':
return CircuitType.batch;
case 'deposit':
return CircuitType.deposit;
case 'withdraw':
return CircuitType.withdraw;
default:
return CircuitType.transfer;
}
}
}
/// Rollup state
enum RollupState {
active,
paused,
finalizing,
finalized,
}
/// Proof status
enum ProofStatus {
generating,
completed,
failed,
verified,
}
/// Zero-knowledge proof
class Proof {
final String id;
final ProofSystem system;
final CircuitType circuitType;
final String data; // Base64 encoded
final List<String> publicInputs;
final int size;
final int generationTimeMs;
final int createdAt;
const Proof({
required this.id,
required this.system,
required this.circuitType,
required this.data,
required this.publicInputs,
required this.size,
required this.generationTimeMs,
required this.createdAt,
});
factory Proof.fromJson(Map<String, dynamic> json) {
return Proof(
id: json['id'] as String,
system: ProofSystemExtension.fromString(json['system'] as String),
circuitType: CircuitTypeExtension.fromString(json['circuit_type'] as String),
data: json['data'] as String,
publicInputs: List<String>.from(json['public_inputs'] ?? []),
size: json['size'] as int? ?? 0,
generationTimeMs: json['generation_time_ms'] as int? ?? 0,
createdAt: json['created_at'] as int? ?? 0,
);
}
Map<String, dynamic> toJson() => {
'id': id,
'system': system.value,
'circuit_type': circuitType.value,
'data': data,
'public_inputs': publicInputs,
'size': size,
'generation_time_ms': generationTimeMs,
'created_at': createdAt,
};
}
/// Verification key for a circuit
class VerificationKey {
final String circuitId;
final CircuitType circuitType;
final ProofSystem system;
final String data; // Base64 encoded
final int size;
const VerificationKey({
required this.circuitId,
required this.circuitType,
required this.system,
required this.data,
required this.size,
});
factory VerificationKey.fromJson(Map<String, dynamic> json) {
return VerificationKey(
circuitId: json['circuit_id'] as String,
circuitType: CircuitTypeExtension.fromString(json['circuit_type'] as String),
system: ProofSystemExtension.fromString(json['system'] as String),
data: json['data'] as String,
size: json['size'] as int? ?? 0,
);
}
}
/// Proving key for generating proofs
class ProvingKey {
final String circuitId;
final CircuitType circuitType;
final ProofSystem system;
final String data; // Base64 encoded
final int size;
const ProvingKey({
required this.circuitId,
required this.circuitType,
required this.system,
required this.data,
required this.size,
});
factory ProvingKey.fromJson(Map<String, dynamic> json) {
return ProvingKey(
circuitId: json['circuit_id'] as String,
circuitType: CircuitTypeExtension.fromString(json['circuit_type'] as String),
system: ProofSystemExtension.fromString(json['system'] as String),
data: json['data'] as String,
size: json['size'] as int? ?? 0,
);
}
}
/// Circuit configuration
class CircuitConfig {
final CircuitType type;
final int? maxBatchSize;
final int? treeDepth;
final bool? verifySignatures;
final Map<String, dynamic>? customConstraints;
const CircuitConfig({
required this.type,
this.maxBatchSize,
this.treeDepth,
this.verifySignatures,
this.customConstraints,
});
factory CircuitConfig.fromJson(Map<String, dynamic> json) {
return CircuitConfig(
type: CircuitTypeExtension.fromString(json['type'] as String),
maxBatchSize: json['max_batch_size'] as int?,
treeDepth: json['tree_depth'] as int?,
verifySignatures: json['verify_signatures'] as bool?,
customConstraints: json['custom_constraints'] as Map<String, dynamic>?,
);
}
Map<String, dynamic> toJson() {
final result = <String, dynamic>{'type': type.value};
if (maxBatchSize != null) result['max_batch_size'] = maxBatchSize;
if (treeDepth != null) result['tree_depth'] = treeDepth;
if (verifySignatures != null) result['verify_signatures'] = verifySignatures;
if (customConstraints != null) result['custom_constraints'] = customConstraints;
return result;
}
}
/// Account state in the rollup
class AccountState {
final String address;
final String balance;
final int nonce;
final String pubkeyHash;
const AccountState({
required this.address,
required this.balance,
required this.nonce,
required this.pubkeyHash,
});
factory AccountState.fromJson(Map<String, dynamic> json) {
return AccountState(
address: json['address'] as String,
balance: json['balance'] as String,
nonce: json['nonce'] as int? ?? 0,
pubkeyHash: json['pubkey_hash'] as String? ?? '',
);
}
}
/// Transfer operation
class Transfer {
final String from;
final String to;
final String amount;
final String fee;
final int nonce;
final String? signature;
const Transfer({
required this.from,
required this.to,
required this.amount,
required this.fee,
required this.nonce,
this.signature,
});
factory Transfer.fromJson(Map<String, dynamic> json) {
return Transfer(
from: json['from'] as String,
to: json['to'] as String,
amount: json['amount'] as String,
fee: json['fee'] as String,
nonce: json['nonce'] as int? ?? 0,
signature: json['signature'] as String?,
);
}
Map<String, dynamic> toJson() {
final result = <String, dynamic>{
'from': from,
'to': to,
'amount': amount,
'fee': fee,
'nonce': nonce,
};
if (signature != null) result['signature'] = signature;
return result;
}
}
/// Deposit operation (L1 -> L2)
class Deposit {
final String l1TxHash;
final String recipient;
final String amount;
final String? token;
const Deposit({
required this.l1TxHash,
required this.recipient,
required this.amount,
this.token,
});
factory Deposit.fromJson(Map<String, dynamic> json) {
return Deposit(
l1TxHash: json['l1_tx_hash'] as String,
recipient: json['recipient'] as String,
amount: json['amount'] as String,
token: json['token'] as String?,
);
}
Map<String, dynamic> toJson() {
final result = <String, dynamic>{
'l1_tx_hash': l1TxHash,
'recipient': recipient,
'amount': amount,
};
if (token != null) result['token'] = token;
return result;
}
}
/// Withdrawal operation (L2 -> L1)
class Withdrawal {
final String sender;
final String recipient;
final String amount;
final String? token;
final int nonce;
final String? signature;
const Withdrawal({
required this.sender,
required this.recipient,
required this.amount,
this.token,
required this.nonce,
this.signature,
});
factory Withdrawal.fromJson(Map<String, dynamic> json) {
return Withdrawal(
sender: json['sender'] as String,
recipient: json['recipient'] as String,
amount: json['amount'] as String,
token: json['token'] as String?,
nonce: json['nonce'] as int? ?? 0,
signature: json['signature'] as String?,
);
}
Map<String, dynamic> toJson() {
final result = <String, dynamic>{
'sender': sender,
'recipient': recipient,
'amount': amount,
'nonce': nonce,
};
if (token != null) result['token'] = token;
if (signature != null) result['signature'] = signature;
return result;
}
}
/// Rollup batch
class Batch {
final int batchNumber;
final String prevStateRoot;
final String newStateRoot;
final List<Transfer> transfers;
final List<Deposit> deposits;
final List<Withdrawal> withdrawals;
final Proof? proof;
final int timestamp;
const Batch({
required this.batchNumber,
required this.prevStateRoot,
required this.newStateRoot,
required this.transfers,
required this.deposits,
required this.withdrawals,
this.proof,
required this.timestamp,
});
factory Batch.fromJson(Map<String, dynamic> json) {
return Batch(
batchNumber: json['batch_number'] as int,
prevStateRoot: json['prev_state_root'] as String,
newStateRoot: json['new_state_root'] as String,
transfers: (json['transfers'] as List?)
?.map((t) => Transfer.fromJson(t as Map<String, dynamic>))
.toList() ??
[],
deposits: (json['deposits'] as List?)
?.map((d) => Deposit.fromJson(d as Map<String, dynamic>))
.toList() ??
[],
withdrawals: (json['withdrawals'] as List?)
?.map((w) => Withdrawal.fromJson(w as Map<String, dynamic>))
.toList() ??
[],
proof: json['proof'] != null
? Proof.fromJson(json['proof'] as Map<String, dynamic>)
: null,
timestamp: json['timestamp'] as int? ?? 0,
);
}
}
/// Rollup statistics
class RollupStats {
final int currentBatch;
final int totalTransactions;
final int totalProofs;
final int avgProofTimeMs;
final String stateRoot;
final int accountCount;
final String tvl;
const RollupStats({
required this.currentBatch,
required this.totalTransactions,
required this.totalProofs,
required this.avgProofTimeMs,
required this.stateRoot,
required this.accountCount,
required this.tvl,
});
factory RollupStats.fromJson(Map<String, dynamic> json) {
return RollupStats(
currentBatch: json['current_batch'] as int,
totalTransactions: json['total_transactions'] as int? ?? 0,
totalProofs: json['total_proofs'] as int? ?? 0,
avgProofTimeMs: json['avg_proof_time_ms'] as int? ?? 0,
stateRoot: json['state_root'] as String,
accountCount: json['account_count'] as int? ?? 0,
tvl: json['tvl'] as String? ?? '0',
);
}
}
/// Proof generation request
class ProofRequest {
final CircuitType circuitType;
final List<String> publicInputs;
final List<String> privateInputs;
final ProofSystem? system;
const ProofRequest({
required this.circuitType,
required this.publicInputs,
required this.privateInputs,
this.system,
});
Map<String, dynamic> toJson() {
final result = <String, dynamic>{
'circuit_type': circuitType.value,
'public_inputs': publicInputs,
'private_inputs': privateInputs,
};
if (system != null) result['system'] = system!.value;
return result;
}
}
/// Proof verification result
class VerificationResult {
final bool valid;
final int verificationTimeMs;
final String? error;
const VerificationResult({
required this.valid,
required this.verificationTimeMs,
this.error,
});
factory VerificationResult.fromJson(Map<String, dynamic> json) {
return VerificationResult(
valid: json['valid'] as bool,
verificationTimeMs: json['verification_time_ms'] as int? ?? 0,
error: json['error'] as String?,
);
}
}
/// Merkle proof for state inclusion
class MerkleProof {
final String leaf;
final List<String> path;
final List<int> indices;
final String root;
const MerkleProof({
required this.leaf,
required this.path,
required this.indices,
required this.root,
});
factory MerkleProof.fromJson(Map<String, dynamic> json) {
return MerkleProof(
leaf: json['leaf'] as String,
path: List<String>.from(json['path']),
indices: List<int>.from(json['indices']),
root: json['root'] as String,
);
}
Map<String, dynamic> toJson() => {
'leaf': leaf,
'path': path,
'indices': indices,
'root': root,
};
}
/// Trusted setup ceremony contribution
class CeremonyContribution {
final String contributorId;
final String hash;
final int timestamp;
final bool verified;
const CeremonyContribution({
required this.contributorId,
required this.hash,
required this.timestamp,
required this.verified,
});
factory CeremonyContribution.fromJson(Map<String, dynamic> json) {
return CeremonyContribution(
contributorId: json['contributor_id'] as String,
hash: json['hash'] as String,
timestamp: json['timestamp'] as int? ?? 0,
verified: json['verified'] as bool? ?? false,
);
}
}
/// Trusted setup ceremony
class TrustedSetup {
final String id;
final CircuitType circuitType;
final ProofSystem system;
final int contributionCount;
final String latestHash;
final bool complete;
final List<CeremonyContribution> contributions;
const TrustedSetup({
required this.id,
required this.circuitType,
required this.system,
required this.contributionCount,
required this.latestHash,
required this.complete,
required this.contributions,
});
factory TrustedSetup.fromJson(Map<String, dynamic> json) {
return TrustedSetup(
id: json['id'] as String,
circuitType: CircuitTypeExtension.fromString(json['circuit_type'] as String),
system: ProofSystemExtension.fromString(json['system'] as String),
contributionCount: json['contribution_count'] as int? ?? 0,
latestHash: json['latest_hash'] as String? ?? '',
complete: json['complete'] as bool? ?? false,
contributions: (json['contributions'] as List?)
?.map((c) => CeremonyContribution.fromJson(c as Map<String, dynamic>))
.toList() ??
[],
);
}
}
/// ZK SDK configuration
class ZkConfig {
final String apiKey;
final String endpoint;
final String wsEndpoint;
final Duration timeout;
final int retries;
final ProofSystem defaultProofSystem;
final bool debug;
const ZkConfig({
required this.apiKey,
this.endpoint = 'https://zk.synor.io/v1',
this.wsEndpoint = 'wss://zk.synor.io/v1/ws',
this.timeout = const Duration(seconds: 60),
this.retries = 3,
this.defaultProofSystem = ProofSystem.groth16,
this.debug = false,
});
}
/// ZK SDK error
class ZkError implements Exception {
final String message;
final String? code;
final int? status;
const ZkError(this.message, {this.code, this.status});
@override
String toString() => code != null ? 'ZkError: $message ($code)' : 'ZkError: $message';
}
/// Proof system characteristics
class ProofSystemInfo {
final String name;
final int proofSize;
final int verificationTimeMs;
final bool trustedSetup;
final bool universal;
const ProofSystemInfo({
required this.name,
required this.proofSize,
required this.verificationTimeMs,
required this.trustedSetup,
required this.universal,
});
}
/// Get proof system info
ProofSystemInfo getProofSystemInfo(ProofSystem system) {
switch (system) {
case ProofSystem.groth16:
return const ProofSystemInfo(
name: 'Groth16',
proofSize: 192,
verificationTimeMs: 10,
trustedSetup: true,
universal: false,
);
case ProofSystem.plonk:
return const ProofSystemInfo(
name: 'PLONK',
proofSize: 512,
verificationTimeMs: 15,
trustedSetup: true,
universal: true,
);
case ProofSystem.stark:
return const ProofSystemInfo(
name: 'STARK',
proofSize: 50000,
verificationTimeMs: 30,
trustedSetup: false,
universal: true,
);
}
}
/// Constants
const int maxBatchSize = 1000;
const int stateTreeDepth = 32;
const int proofExpiryBlocks = 100;

496
sdk/go/zk/client.go Normal file
View file

@ -0,0 +1,496 @@
// Package zk provides the Synor ZK SDK for Go.
package zk
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"sync/atomic"
"time"
)
// Client is the main ZK SDK client
type Client struct {
config Config
httpClient *http.Client
closed atomic.Bool
Proofs *ProofsClient
Circuits *CircuitsClient
Rollup *RollupClient
State *StateClient
Ceremony *CeremonyClient
}
// New creates a new ZK SDK client
func New(config Config) *Client {
c := &Client{
config: config,
httpClient: &http.Client{
Timeout: config.Timeout,
},
}
c.Proofs = &ProofsClient{client: c}
c.Circuits = &CircuitsClient{client: c}
c.Rollup = &RollupClient{client: c}
c.State = &StateClient{client: c}
c.Ceremony = &CeremonyClient{client: c}
return c
}
// DefaultProofSystem returns the default proof system
func (c *Client) DefaultProofSystem() ProofSystem {
return c.config.DefaultProofSystem
}
// HealthCheck checks if the service is healthy
func (c *Client) HealthCheck(ctx context.Context) (bool, error) {
var result map[string]interface{}
if err := c.get(ctx, "/health", &result); err != nil {
return false, nil
}
return result["status"] == "healthy", nil
}
// GetInfo returns service info
func (c *Client) GetInfo(ctx context.Context) (map[string]interface{}, error) {
var result map[string]interface{}
err := c.get(ctx, "/info", &result)
return result, err
}
// Close closes the client
func (c *Client) Close() {
c.closed.Store(true)
}
// IsClosed returns whether the client is closed
func (c *Client) IsClosed() bool {
return c.closed.Load()
}
// Internal HTTP methods
func (c *Client) get(ctx context.Context, path string, result interface{}) error {
return c.request(ctx, "GET", path, nil, result)
}
func (c *Client) post(ctx context.Context, path string, body, result interface{}) error {
return c.request(ctx, "POST", path, body, result)
}
func (c *Client) delete(ctx context.Context, path string, result interface{}) error {
return c.request(ctx, "DELETE", path, nil, result)
}
func (c *Client) request(ctx context.Context, method, path string, body, result interface{}) error {
if c.closed.Load() {
return &Error{Message: "Client has been closed", Code: "CLIENT_CLOSED"}
}
url := c.config.Endpoint + path
var bodyReader io.Reader
if body != nil {
data, err := json.Marshal(body)
if err != nil {
return err
}
bodyReader = bytes.NewReader(data)
}
var lastErr error
for attempt := 0; attempt <= c.config.Retries; attempt++ {
req, err := http.NewRequestWithContext(ctx, method, url, bodyReader)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+c.config.APIKey)
req.Header.Set("X-SDK-Version", "go/0.1.0")
resp, err := c.httpClient.Do(req)
if err != nil {
lastErr = err
if attempt < c.config.Retries {
time.Sleep(time.Duration(100*(1<<attempt)) * time.Millisecond)
continue
}
break
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
if resp.StatusCode >= 400 {
var errResp struct {
Message string `json:"message"`
Code string `json:"code"`
}
json.Unmarshal(respBody, &errResp)
return &Error{
Message: errResp.Message,
Code: errResp.Code,
Status: resp.StatusCode,
}
}
if result != nil {
return json.Unmarshal(respBody, result)
}
return nil
}
return &Error{
Message: fmt.Sprintf("request failed: %v", lastErr),
Code: "NETWORK_ERROR",
}
}
// ProofsClient handles proof operations
type ProofsClient struct {
client *Client
}
// Generate generates a zero-knowledge proof
func (p *ProofsClient) Generate(ctx context.Context, req ProofRequest) (*Proof, error) {
system := req.System
if system == nil {
s := p.client.DefaultProofSystem()
system = &s
}
body := map[string]interface{}{
"circuit_type": req.CircuitType,
"public_inputs": req.PublicInputs,
"private_inputs": req.PrivateInputs,
"system": *system,
}
var result Proof
if err := p.client.post(ctx, "/proofs/generate", body, &result); err != nil {
return nil, err
}
return &result, nil
}
// Verify verifies a proof
func (p *ProofsClient) Verify(ctx context.Context, proof *Proof) (*VerificationResult, error) {
body := map[string]interface{}{
"proof_id": proof.ID,
"data": proof.Data,
"public_inputs": proof.PublicInputs,
"system": proof.System,
"circuit_type": proof.CircuitType,
}
var result VerificationResult
if err := p.client.post(ctx, "/proofs/verify", body, &result); err != nil {
return nil, err
}
return &result, nil
}
// Get retrieves a proof by ID
func (p *ProofsClient) Get(ctx context.Context, proofID string) (*Proof, error) {
var result Proof
if err := p.client.get(ctx, "/proofs/"+proofID, &result); err != nil {
return nil, err
}
return &result, nil
}
// List lists recent proofs
func (p *ProofsClient) List(ctx context.Context, limit, offset int) ([]Proof, error) {
path := "/proofs"
if limit > 0 || offset > 0 {
path = fmt.Sprintf("/proofs?limit=%d&offset=%d", limit, offset)
}
var result proofsResponse
if err := p.client.get(ctx, path, &result); err != nil {
return nil, err
}
return result.Proofs, nil
}
// Serialize serializes a proof to bytes
func (p *ProofsClient) Serialize(ctx context.Context, proof *Proof) ([]byte, error) {
var result serializeResponse
if err := p.client.post(ctx, "/proofs/serialize", map[string]string{"proof_id": proof.ID}, &result); err != nil {
return nil, err
}
return base64.StdEncoding.DecodeString(result.Data)
}
// Deserialize deserializes bytes to a proof
func (p *ProofsClient) Deserialize(ctx context.Context, data []byte, system ProofSystem) (*Proof, error) {
body := map[string]interface{}{
"data": base64.StdEncoding.EncodeToString(data),
"system": system,
}
var result Proof
if err := p.client.post(ctx, "/proofs/deserialize", body, &result); err != nil {
return nil, err
}
return &result, nil
}
// CircuitsClient handles circuit operations
type CircuitsClient struct {
client *Client
}
// GetVerificationKey gets the verification key for a circuit
func (c *CircuitsClient) GetVerificationKey(ctx context.Context, circuitType CircuitType, system *ProofSystem) (*VerificationKey, error) {
sys := c.client.DefaultProofSystem()
if system != nil {
sys = *system
}
var result VerificationKey
if err := c.client.get(ctx, fmt.Sprintf("/circuits/%s/vk?system=%s", circuitType, sys), &result); err != nil {
return nil, err
}
return &result, nil
}
// GetProvingKey gets the proving key for a circuit
func (c *CircuitsClient) GetProvingKey(ctx context.Context, circuitType CircuitType, system *ProofSystem) (*ProvingKey, error) {
sys := c.client.DefaultProofSystem()
if system != nil {
sys = *system
}
var result ProvingKey
if err := c.client.get(ctx, fmt.Sprintf("/circuits/%s/pk?system=%s", circuitType, sys), &result); err != nil {
return nil, err
}
return &result, nil
}
// List lists available circuits
func (c *CircuitsClient) List(ctx context.Context) ([]CircuitConfig, error) {
var result circuitsResponse
if err := c.client.get(ctx, "/circuits", &result); err != nil {
return nil, err
}
return result.Circuits, nil
}
// GetConfig gets circuit configuration
func (c *CircuitsClient) GetConfig(ctx context.Context, circuitType CircuitType) (*CircuitConfig, error) {
var result CircuitConfig
if err := c.client.get(ctx, fmt.Sprintf("/circuits/%s/config", circuitType), &result); err != nil {
return nil, err
}
return &result, nil
}
// Compile compiles a custom circuit
func (c *CircuitsClient) Compile(ctx context.Context, config CircuitConfig) (string, error) {
var result circuitIDResponse
if err := c.client.post(ctx, "/circuits/compile", config, &result); err != nil {
return "", err
}
return result.CircuitID, nil
}
// RollupClient handles rollup operations
type RollupClient struct {
client *Client
}
// GetStats gets rollup statistics
func (r *RollupClient) GetStats(ctx context.Context) (*RollupStats, error) {
var result RollupStats
if err := r.client.get(ctx, "/rollup/stats", &result); err != nil {
return nil, err
}
return &result, nil
}
// GetCurrentBatch gets the current batch
func (r *RollupClient) GetCurrentBatch(ctx context.Context) (*Batch, error) {
var result Batch
if err := r.client.get(ctx, "/rollup/batch/current", &result); err != nil {
return nil, err
}
return &result, nil
}
// GetBatch gets a batch by number
func (r *RollupClient) GetBatch(ctx context.Context, batchNumber uint64) (*Batch, error) {
var result Batch
if err := r.client.get(ctx, fmt.Sprintf("/rollup/batch/%d", batchNumber), &result); err != nil {
return nil, err
}
return &result, nil
}
// SubmitTransfer submits a transfer
func (r *RollupClient) SubmitTransfer(ctx context.Context, transfer Transfer) (string, error) {
var result txIDResponse
if err := r.client.post(ctx, "/rollup/transfer", transfer, &result); err != nil {
return "", err
}
return result.TxID, nil
}
// SubmitDeposit submits a deposit
func (r *RollupClient) SubmitDeposit(ctx context.Context, deposit Deposit) (string, error) {
var result txIDResponse
if err := r.client.post(ctx, "/rollup/deposit", deposit, &result); err != nil {
return "", err
}
return result.TxID, nil
}
// SubmitWithdrawal submits a withdrawal
func (r *RollupClient) SubmitWithdrawal(ctx context.Context, withdrawal Withdrawal) (string, error) {
var result txIDResponse
if err := r.client.post(ctx, "/rollup/withdraw", withdrawal, &result); err != nil {
return "", err
}
return result.TxID, nil
}
// FinalizeBatch finalizes the current batch
func (r *RollupClient) FinalizeBatch(ctx context.Context) (*Batch, error) {
var result Batch
if err := r.client.post(ctx, "/rollup/batch/finalize", struct{}{}, &result); err != nil {
return nil, err
}
return &result, nil
}
// GetPendingTransactions gets pending transactions
func (r *RollupClient) GetPendingTransactions(ctx context.Context) ([]Transfer, error) {
var result transactionsResponse
if err := r.client.get(ctx, "/rollup/pending", &result); err != nil {
return nil, err
}
return result.Transactions, nil
}
// StateClient handles state operations
type StateClient struct {
client *Client
}
// GetRoot gets the current state root
func (s *StateClient) GetRoot(ctx context.Context) (string, error) {
var result rootResponse
if err := s.client.get(ctx, "/state/root", &result); err != nil {
return "", err
}
return result.Root, nil
}
// GetAccount gets account state
func (s *StateClient) GetAccount(ctx context.Context, address string) (*AccountState, error) {
var result AccountState
if err := s.client.get(ctx, "/state/account/"+address, &result); err != nil {
return nil, err
}
return &result, nil
}
// GetMerkleProof gets merkle proof for account inclusion
func (s *StateClient) GetMerkleProof(ctx context.Context, address string) (*MerkleProof, error) {
var result MerkleProof
if err := s.client.get(ctx, "/state/proof/"+address, &result); err != nil {
return nil, err
}
return &result, nil
}
// VerifyMerkleProof verifies a merkle proof
func (s *StateClient) VerifyMerkleProof(ctx context.Context, proof MerkleProof) (bool, error) {
var result validResponse
if err := s.client.post(ctx, "/state/proof/verify", proof, &result); err != nil {
return false, err
}
return result.Valid, nil
}
// GetStateAtBatch gets state at specific batch
func (s *StateClient) GetStateAtBatch(ctx context.Context, batchNumber uint64) (map[string]interface{}, error) {
var result map[string]interface{}
if err := s.client.get(ctx, fmt.Sprintf("/state/batch/%d", batchNumber), &result); err != nil {
return nil, err
}
return result, nil
}
// CeremonyClient handles ceremony operations
type CeremonyClient struct {
client *Client
}
// GetStatus gets ceremony status
func (c *CeremonyClient) GetStatus(ctx context.Context, circuitType CircuitType, system *ProofSystem) (*TrustedSetup, error) {
sys := c.client.DefaultProofSystem()
if system != nil {
sys = *system
}
var result TrustedSetup
if err := c.client.get(ctx, fmt.Sprintf("/ceremony/%s?system=%s", circuitType, sys), &result); err != nil {
return nil, err
}
return &result, nil
}
// Contribute contributes to ceremony
func (c *CeremonyClient) Contribute(ctx context.Context, circuitType CircuitType, entropy []byte, system *ProofSystem) (*CeremonyContribution, error) {
sys := c.client.DefaultProofSystem()
if system != nil {
sys = *system
}
body := map[string]interface{}{
"circuit_type": circuitType,
"entropy": base64.StdEncoding.EncodeToString(entropy),
"system": sys,
}
var result CeremonyContribution
if err := c.client.post(ctx, "/ceremony/contribute", body, &result); err != nil {
return nil, err
}
return &result, nil
}
// VerifyContribution verifies a contribution
func (c *CeremonyClient) VerifyContribution(ctx context.Context, circuitType CircuitType, contributionHash string) (bool, error) {
body := map[string]interface{}{
"circuit_type": circuitType,
"contribution_hash": contributionHash,
}
var result validResponse
if err := c.client.post(ctx, "/ceremony/verify", body, &result); err != nil {
return false, err
}
return result.Valid, nil
}
// ListContributions lists contributions
func (c *CeremonyClient) ListContributions(ctx context.Context, circuitType CircuitType) ([]CeremonyContribution, error) {
var result contributionsResponse
if err := c.client.get(ctx, fmt.Sprintf("/ceremony/%s/contributions", circuitType), &result); err != nil {
return nil, err
}
return result.Contributions, nil
}

323
sdk/go/zk/types.go Normal file
View file

@ -0,0 +1,323 @@
// Package zk provides the Synor ZK SDK for Go.
//
// Zero-Knowledge proof systems for ZK-Rollups and privacy.
package zk
import (
"encoding/json"
"fmt"
"time"
)
// ProofSystem represents available proof system backends
type ProofSystem string
const (
// Groth16 - smallest proofs (~192 bytes), fastest verification
ProofSystemGroth16 ProofSystem = "groth16"
// Plonk - universal trusted setup, medium proofs (~512 bytes)
ProofSystemPlonk ProofSystem = "plonk"
// Stark - no trusted setup, largest proofs (~50KB)
ProofSystemStark ProofSystem = "stark"
)
// CircuitType represents the type of circuit
type CircuitType string
const (
// CircuitTransfer - single transfer between accounts
CircuitTransfer CircuitType = "transfer"
// CircuitBatch - batch of multiple transfers
CircuitBatch CircuitType = "batch"
// CircuitDeposit - deposit from L1 to L2
CircuitDeposit CircuitType = "deposit"
// CircuitWithdraw - withdrawal from L2 to L1
CircuitWithdraw CircuitType = "withdraw"
)
// RollupState represents the state of a rollup
type RollupState string
const (
RollupStateActive RollupState = "active"
RollupStatePaused RollupState = "paused"
RollupStateFinalizing RollupState = "finalizing"
RollupStateFinalized RollupState = "finalized"
)
// ProofStatus represents the status of a proof
type ProofStatus string
const (
ProofStatusGenerating ProofStatus = "generating"
ProofStatusCompleted ProofStatus = "completed"
ProofStatusFailed ProofStatus = "failed"
ProofStatusVerified ProofStatus = "verified"
)
// Proof represents a zero-knowledge proof
type Proof struct {
ID string `json:"id"`
System ProofSystem `json:"system"`
CircuitType CircuitType `json:"circuit_type"`
Data string `json:"data"` // Base64 encoded
PublicInputs []string `json:"public_inputs"`
Size int `json:"size"`
GenerationTimeMs int64 `json:"generation_time_ms"`
CreatedAt int64 `json:"created_at"`
}
// VerificationKey represents a verification key for a circuit
type VerificationKey struct {
CircuitID string `json:"circuit_id"`
CircuitType CircuitType `json:"circuit_type"`
System ProofSystem `json:"system"`
Data string `json:"data"` // Base64 encoded
Size int `json:"size"`
}
// ProvingKey represents a proving key for generating proofs
type ProvingKey struct {
CircuitID string `json:"circuit_id"`
CircuitType CircuitType `json:"circuit_type"`
System ProofSystem `json:"system"`
Data string `json:"data"` // Base64 encoded
Size int `json:"size"`
}
// CircuitConfig represents circuit configuration
type CircuitConfig struct {
Type CircuitType `json:"type"`
MaxBatchSize *int `json:"max_batch_size,omitempty"`
TreeDepth *int `json:"tree_depth,omitempty"`
VerifySignatures *bool `json:"verify_signatures,omitempty"`
CustomConstraints map[string]interface{} `json:"custom_constraints,omitempty"`
}
// AccountState represents account state in the rollup
type AccountState struct {
Address string `json:"address"`
Balance string `json:"balance"`
Nonce uint64 `json:"nonce"`
PubkeyHash string `json:"pubkey_hash"`
}
// Transfer represents a transfer operation
type Transfer struct {
From string `json:"from"`
To string `json:"to"`
Amount string `json:"amount"`
Fee string `json:"fee"`
Nonce uint64 `json:"nonce"`
Signature *string `json:"signature,omitempty"`
}
// Deposit represents a deposit operation (L1 -> L2)
type Deposit struct {
L1TxHash string `json:"l1_tx_hash"`
Recipient string `json:"recipient"`
Amount string `json:"amount"`
Token *string `json:"token,omitempty"`
}
// Withdrawal represents a withdrawal operation (L2 -> L1)
type Withdrawal struct {
Sender string `json:"sender"`
Recipient string `json:"recipient"`
Amount string `json:"amount"`
Token *string `json:"token,omitempty"`
Nonce uint64 `json:"nonce"`
Signature *string `json:"signature,omitempty"`
}
// Batch represents a rollup batch
type Batch struct {
BatchNumber uint64 `json:"batch_number"`
PrevStateRoot string `json:"prev_state_root"`
NewStateRoot string `json:"new_state_root"`
Transfers []Transfer `json:"transfers"`
Deposits []Deposit `json:"deposits"`
Withdrawals []Withdrawal `json:"withdrawals"`
Proof *Proof `json:"proof,omitempty"`
Timestamp int64 `json:"timestamp"`
}
// RollupStats represents rollup statistics
type RollupStats struct {
CurrentBatch uint64 `json:"current_batch"`
TotalTransactions uint64 `json:"total_transactions"`
TotalProofs uint64 `json:"total_proofs"`
AvgProofTimeMs int64 `json:"avg_proof_time_ms"`
StateRoot string `json:"state_root"`
AccountCount uint64 `json:"account_count"`
TVL string `json:"tvl"`
}
// ProofRequest represents a proof generation request
type ProofRequest struct {
CircuitType CircuitType `json:"circuit_type"`
PublicInputs []string `json:"public_inputs"`
PrivateInputs []string `json:"private_inputs"`
System *ProofSystem `json:"system,omitempty"`
}
// VerificationResult represents proof verification result
type VerificationResult struct {
Valid bool `json:"valid"`
VerificationTimeMs int64 `json:"verification_time_ms"`
Error *string `json:"error,omitempty"`
}
// MerkleProof represents a merkle proof for state inclusion
type MerkleProof struct {
Leaf string `json:"leaf"`
Path []string `json:"path"`
Indices []int `json:"indices"`
Root string `json:"root"`
}
// CeremonyContribution represents a trusted setup ceremony contribution
type CeremonyContribution struct {
ContributorID string `json:"contributor_id"`
Hash string `json:"hash"`
Timestamp int64 `json:"timestamp"`
Verified bool `json:"verified"`
}
// TrustedSetup represents a trusted setup ceremony
type TrustedSetup struct {
ID string `json:"id"`
CircuitType CircuitType `json:"circuit_type"`
System ProofSystem `json:"system"`
ContributionCount int `json:"contribution_count"`
LatestHash string `json:"latest_hash"`
Complete bool `json:"complete"`
Contributions []CeremonyContribution `json:"contributions"`
}
// Config represents ZK SDK configuration
type Config struct {
APIKey string
Endpoint string
WSEndpoint string
Timeout time.Duration
Retries int
DefaultProofSystem ProofSystem
Debug bool
}
// DefaultConfig returns the default configuration
func DefaultConfig(apiKey string) Config {
return Config{
APIKey: apiKey,
Endpoint: "https://zk.synor.io/v1",
WSEndpoint: "wss://zk.synor.io/v1/ws",
Timeout: 60 * time.Second,
Retries: 3,
DefaultProofSystem: ProofSystemGroth16,
Debug: false,
}
}
// Error represents a ZK SDK error
type Error struct {
Message string
Code string
Status int
}
func (e *Error) Error() string {
if e.Code != "" {
return fmt.Sprintf("%s (%s)", e.Message, e.Code)
}
return e.Message
}
// ProofSystemInfo contains information about a proof system
type ProofSystemInfo struct {
Name string
ProofSize int
VerificationTimeMs int
TrustedSetup bool
Universal bool
}
// GetProofSystemInfo returns information about a proof system
func GetProofSystemInfo(system ProofSystem) ProofSystemInfo {
switch system {
case ProofSystemGroth16:
return ProofSystemInfo{
Name: "Groth16",
ProofSize: 192,
VerificationTimeMs: 10,
TrustedSetup: true,
Universal: false,
}
case ProofSystemPlonk:
return ProofSystemInfo{
Name: "PLONK",
ProofSize: 512,
VerificationTimeMs: 15,
TrustedSetup: true,
Universal: true,
}
case ProofSystemStark:
return ProofSystemInfo{
Name: "STARK",
ProofSize: 50000,
VerificationTimeMs: 30,
TrustedSetup: false,
Universal: true,
}
default:
return ProofSystemInfo{}
}
}
// Constants
const (
MaxBatchSize = 1000
StateTreeDepth = 32
ProofExpiryBlocks = 100
)
// Helper for JSON responses
type jsonResponse struct {
Data json.RawMessage `json:"data,omitempty"`
}
type proofsResponse struct {
Proofs []Proof `json:"proofs"`
}
type circuitsResponse struct {
Circuits []CircuitConfig `json:"circuits"`
}
type transactionsResponse struct {
Transactions []Transfer `json:"transactions"`
}
type contributionsResponse struct {
Contributions []CeremonyContribution `json:"contributions"`
}
type rootResponse struct {
Root string `json:"root"`
}
type validResponse struct {
Valid bool `json:"valid"`
}
type txIDResponse struct {
TxID string `json:"tx_id"`
}
type circuitIDResponse struct {
CircuitID string `json:"circuit_id"`
}
type serializeResponse struct {
Data string `json:"data"`
}

View file

@ -0,0 +1,321 @@
package io.synor.zk;
import io.synor.zk.Types.*;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.lang.reflect.Type;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Synor ZK SDK Client for Java
*
* Zero-Knowledge proof systems for ZK-Rollups and privacy.
*/
public class SynorZk {
private final ZkConfig config;
private final HttpClient httpClient;
private final Gson gson;
private final AtomicBoolean closed = new AtomicBoolean(false);
public final ProofsClient proofs;
public final CircuitsClient circuits;
public final RollupClient rollup;
public final StateClient state;
public final CeremonyClient ceremony;
public SynorZk(ZkConfig config) {
this.config = config;
this.httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofMillis(config.getTimeout()))
.build();
this.gson = new GsonBuilder().create();
this.proofs = new ProofsClient(this);
this.circuits = new CircuitsClient(this);
this.rollup = new RollupClient(this);
this.state = new StateClient(this);
this.ceremony = new CeremonyClient(this);
}
public ProofSystem getDefaultProofSystem() {
return config.getDefaultProofSystem();
}
public CompletableFuture<Boolean> healthCheck() {
return get("/health", Map.class)
.thenApply(result -> "healthy".equals(result.get("status")))
.exceptionally(e -> false);
}
public CompletableFuture<Map<String, Object>> getInfo() {
return get("/info", new TypeToken<Map<String, Object>>(){}.getType());
}
public void close() {
closed.set(true);
}
public boolean isClosed() {
return closed.get();
}
// Internal HTTP methods
<T> CompletableFuture<T> get(String path, Type type) {
return request("GET", path, null, type);
}
<T> CompletableFuture<T> post(String path, Object body, Type type) {
return request("POST", path, body, type);
}
private <T> CompletableFuture<T> request(String method, String path, Object body, Type type) {
if (closed.get()) {
return CompletableFuture.failedFuture(
new ZkException("Client has been closed", "CLIENT_CLOSED"));
}
String url = config.getEndpoint() + path;
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + config.getApiKey())
.header("X-SDK-Version", "java/0.1.0")
.timeout(Duration.ofMillis(config.getTimeout()));
if ("GET".equals(method)) {
requestBuilder.GET();
} else if ("POST".equals(method)) {
String jsonBody = body != null ? gson.toJson(body) : "{}";
requestBuilder.POST(HttpRequest.BodyPublishers.ofString(jsonBody));
} else if ("DELETE".equals(method)) {
requestBuilder.DELETE();
}
return httpClient.sendAsync(requestBuilder.build(), HttpResponse.BodyHandlers.ofString())
.thenApply(response -> {
if (response.statusCode() >= 400) {
Map<String, Object> error = gson.fromJson(response.body(), Map.class);
throw new ZkException(
(String) error.getOrDefault("message", "HTTP " + response.statusCode()),
(String) error.get("code"),
response.statusCode()
);
}
return gson.fromJson(response.body(), type);
});
}
/** Proofs sub-client */
public static class ProofsClient {
private final SynorZk zk;
ProofsClient(SynorZk zk) {
this.zk = zk;
}
public CompletableFuture<Proof> generate(ProofRequest request) {
Map<String, Object> body = new HashMap<>();
body.put("circuit_type", request.getCircuitType().getValue());
body.put("public_inputs", request.getPublicInputs());
body.put("private_inputs", request.getPrivateInputs());
body.put("system", (request.getSystem() != null ? request.getSystem() : zk.getDefaultProofSystem()).getValue());
return zk.post("/proofs/generate", body, Proof.class);
}
public CompletableFuture<VerificationResult> verify(Proof proof) {
Map<String, Object> body = new HashMap<>();
body.put("proof_id", proof.getId());
body.put("data", proof.getData());
body.put("public_inputs", proof.getPublicInputs());
body.put("system", proof.getSystem().getValue());
body.put("circuit_type", proof.getCircuitType().getValue());
return zk.post("/proofs/verify", body, VerificationResult.class);
}
public CompletableFuture<Proof> get(String proofId) {
return zk.get("/proofs/" + proofId, Proof.class);
}
public CompletableFuture<List<Proof>> list(Integer limit, Integer offset) {
StringBuilder path = new StringBuilder("/proofs");
if (limit != null || offset != null) {
path.append("?");
if (limit != null) path.append("limit=").append(limit);
if (limit != null && offset != null) path.append("&");
if (offset != null) path.append("offset=").append(offset);
}
return zk.get(path.toString(), new TypeToken<Map<String, List<Proof>>>(){}.getType())
.thenApply(result -> ((Map<String, List<Proof>>) result).getOrDefault("proofs", Collections.emptyList()));
}
public CompletableFuture<byte[]> serialize(Proof proof) {
Map<String, Object> body = new HashMap<>();
body.put("proof_id", proof.getId());
return zk.post("/proofs/serialize", body, new TypeToken<Map<String, String>>(){}.getType())
.thenApply(result -> Base64.getDecoder().decode(((Map<String, String>) result).get("data")));
}
public CompletableFuture<Proof> deserialize(byte[] data, ProofSystem system) {
Map<String, Object> body = new HashMap<>();
body.put("data", Base64.getEncoder().encodeToString(data));
body.put("system", system.getValue());
return zk.post("/proofs/deserialize", body, Proof.class);
}
}
/** Circuits sub-client */
public static class CircuitsClient {
private final SynorZk zk;
CircuitsClient(SynorZk zk) {
this.zk = zk;
}
public CompletableFuture<VerificationKey> getVerificationKey(CircuitType circuitType, ProofSystem system) {
ProofSystem sys = system != null ? system : zk.getDefaultProofSystem();
return zk.get("/circuits/" + circuitType.getValue() + "/vk?system=" + sys.getValue(), VerificationKey.class);
}
public CompletableFuture<ProvingKey> getProvingKey(CircuitType circuitType, ProofSystem system) {
ProofSystem sys = system != null ? system : zk.getDefaultProofSystem();
return zk.get("/circuits/" + circuitType.getValue() + "/pk?system=" + sys.getValue(), ProvingKey.class);
}
public CompletableFuture<List<CircuitConfig>> list() {
return zk.get("/circuits", new TypeToken<Map<String, List<CircuitConfig>>>(){}.getType())
.thenApply(result -> ((Map<String, List<CircuitConfig>>) result).getOrDefault("circuits", Collections.emptyList()));
}
public CompletableFuture<CircuitConfig> getConfig(CircuitType circuitType) {
return zk.get("/circuits/" + circuitType.getValue() + "/config", CircuitConfig.class);
}
public CompletableFuture<String> compile(CircuitConfig config) {
return zk.post("/circuits/compile", config, new TypeToken<Map<String, String>>(){}.getType())
.thenApply(result -> ((Map<String, String>) result).get("circuit_id"));
}
}
/** Rollup sub-client */
public static class RollupClient {
private final SynorZk zk;
RollupClient(SynorZk zk) {
this.zk = zk;
}
public CompletableFuture<RollupStats> getStats() {
return zk.get("/rollup/stats", RollupStats.class);
}
public CompletableFuture<Batch> getCurrentBatch() {
return zk.get("/rollup/batch/current", Batch.class);
}
public CompletableFuture<Batch> getBatch(long batchNumber) {
return zk.get("/rollup/batch/" + batchNumber, Batch.class);
}
public CompletableFuture<String> submitTransfer(Transfer transfer) {
return zk.post("/rollup/transfer", transfer, new TypeToken<Map<String, String>>(){}.getType())
.thenApply(result -> ((Map<String, String>) result).get("tx_id"));
}
public CompletableFuture<String> submitDeposit(Deposit deposit) {
return zk.post("/rollup/deposit", deposit, new TypeToken<Map<String, String>>(){}.getType())
.thenApply(result -> ((Map<String, String>) result).get("tx_id"));
}
public CompletableFuture<String> submitWithdrawal(Withdrawal withdrawal) {
return zk.post("/rollup/withdraw", withdrawal, new TypeToken<Map<String, String>>(){}.getType())
.thenApply(result -> ((Map<String, String>) result).get("tx_id"));
}
public CompletableFuture<Batch> finalizeBatch() {
return zk.post("/rollup/batch/finalize", Collections.emptyMap(), Batch.class);
}
public CompletableFuture<List<Transfer>> getPendingTransactions() {
return zk.get("/rollup/pending", new TypeToken<Map<String, List<Transfer>>>(){}.getType())
.thenApply(result -> ((Map<String, List<Transfer>>) result).getOrDefault("transactions", Collections.emptyList()));
}
}
/** State sub-client */
public static class StateClient {
private final SynorZk zk;
StateClient(SynorZk zk) {
this.zk = zk;
}
public CompletableFuture<String> getRoot() {
return zk.get("/state/root", new TypeToken<Map<String, String>>(){}.getType())
.thenApply(result -> ((Map<String, String>) result).get("root"));
}
public CompletableFuture<AccountState> getAccount(String address) {
return zk.get("/state/account/" + address, AccountState.class);
}
public CompletableFuture<MerkleProof> getMerkleProof(String address) {
return zk.get("/state/proof/" + address, MerkleProof.class);
}
public CompletableFuture<Boolean> verifyMerkleProof(MerkleProof proof) {
return zk.post("/state/proof/verify", proof, new TypeToken<Map<String, Boolean>>(){}.getType())
.thenApply(result -> ((Map<String, Boolean>) result).get("valid"));
}
public CompletableFuture<Map<String, Object>> getStateAtBatch(long batchNumber) {
return zk.get("/state/batch/" + batchNumber, new TypeToken<Map<String, Object>>(){}.getType());
}
}
/** Ceremony sub-client */
public static class CeremonyClient {
private final SynorZk zk;
CeremonyClient(SynorZk zk) {
this.zk = zk;
}
public CompletableFuture<TrustedSetup> getStatus(CircuitType circuitType, ProofSystem system) {
ProofSystem sys = system != null ? system : zk.getDefaultProofSystem();
return zk.get("/ceremony/" + circuitType.getValue() + "?system=" + sys.getValue(), TrustedSetup.class);
}
public CompletableFuture<CeremonyContribution> contribute(CircuitType circuitType, byte[] entropy, ProofSystem system) {
ProofSystem sys = system != null ? system : zk.getDefaultProofSystem();
Map<String, Object> body = new HashMap<>();
body.put("circuit_type", circuitType.getValue());
body.put("entropy", Base64.getEncoder().encodeToString(entropy));
body.put("system", sys.getValue());
return zk.post("/ceremony/contribute", body, CeremonyContribution.class);
}
public CompletableFuture<Boolean> verifyContribution(CircuitType circuitType, String contributionHash) {
Map<String, Object> body = new HashMap<>();
body.put("circuit_type", circuitType.getValue());
body.put("contribution_hash", contributionHash);
return zk.post("/ceremony/verify", body, new TypeToken<Map<String, Boolean>>(){}.getType())
.thenApply(result -> ((Map<String, Boolean>) result).get("valid"));
}
public CompletableFuture<List<CeremonyContribution>> listContributions(CircuitType circuitType) {
return zk.get("/ceremony/" + circuitType.getValue() + "/contributions", new TypeToken<Map<String, List<CeremonyContribution>>>(){}.getType())
.thenApply(result -> ((Map<String, List<CeremonyContribution>>) result).getOrDefault("contributions", Collections.emptyList()));
}
}
}

View file

@ -0,0 +1,539 @@
package io.synor.zk;
import java.util.List;
import java.util.Map;
/**
* Synor ZK SDK Types for Java
*
* Zero-Knowledge proof systems for ZK-Rollups and privacy.
*/
public class Types {
/** Proof system backends */
public enum ProofSystem {
/** Groth16 - smallest proofs (~192 bytes), fastest verification */
GROTH16("groth16"),
/** PLONK - universal trusted setup, medium proofs (~512 bytes) */
PLONK("plonk"),
/** STARK - no trusted setup, largest proofs (~50KB) */
STARK("stark");
private final String value;
ProofSystem(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static ProofSystem fromString(String value) {
for (ProofSystem system : values()) {
if (system.value.equals(value)) {
return system;
}
}
return GROTH16;
}
}
/** Circuit types for different operations */
public enum CircuitType {
/** Single transfer between accounts */
TRANSFER("transfer"),
/** Batch of multiple transfers */
BATCH("batch"),
/** Deposit from L1 to L2 */
DEPOSIT("deposit"),
/** Withdrawal from L2 to L1 */
WITHDRAW("withdraw");
private final String value;
CircuitType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static CircuitType fromString(String value) {
for (CircuitType type : values()) {
if (type.value.equals(value)) {
return type;
}
}
return TRANSFER;
}
}
/** Rollup state */
public enum RollupState {
ACTIVE, PAUSED, FINALIZING, FINALIZED
}
/** Proof status */
public enum ProofStatus {
GENERATING, COMPLETED, FAILED, VERIFIED
}
/** Zero-knowledge proof */
public static class Proof {
private String id;
private ProofSystem system;
private CircuitType circuitType;
private String data;
private List<String> publicInputs;
private int size;
private long generationTimeMs;
private long createdAt;
public Proof() {}
public Proof(String id, ProofSystem system, CircuitType circuitType, String data,
List<String> publicInputs, int size, long generationTimeMs, long createdAt) {
this.id = id;
this.system = system;
this.circuitType = circuitType;
this.data = data;
this.publicInputs = publicInputs;
this.size = size;
this.generationTimeMs = generationTimeMs;
this.createdAt = createdAt;
}
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public ProofSystem getSystem() { return system; }
public void setSystem(ProofSystem system) { this.system = system; }
public CircuitType getCircuitType() { return circuitType; }
public void setCircuitType(CircuitType circuitType) { this.circuitType = circuitType; }
public String getData() { return data; }
public void setData(String data) { this.data = data; }
public List<String> getPublicInputs() { return publicInputs; }
public void setPublicInputs(List<String> publicInputs) { this.publicInputs = publicInputs; }
public int getSize() { return size; }
public void setSize(int size) { this.size = size; }
public long getGenerationTimeMs() { return generationTimeMs; }
public void setGenerationTimeMs(long generationTimeMs) { this.generationTimeMs = generationTimeMs; }
public long getCreatedAt() { return createdAt; }
public void setCreatedAt(long createdAt) { this.createdAt = createdAt; }
}
/** Verification key for a circuit */
public static class VerificationKey {
private String circuitId;
private CircuitType circuitType;
private ProofSystem system;
private String data;
private int size;
public String getCircuitId() { return circuitId; }
public void setCircuitId(String circuitId) { this.circuitId = circuitId; }
public CircuitType getCircuitType() { return circuitType; }
public void setCircuitType(CircuitType circuitType) { this.circuitType = circuitType; }
public ProofSystem getSystem() { return system; }
public void setSystem(ProofSystem system) { this.system = system; }
public String getData() { return data; }
public void setData(String data) { this.data = data; }
public int getSize() { return size; }
public void setSize(int size) { this.size = size; }
}
/** Proving key for generating proofs */
public static class ProvingKey {
private String circuitId;
private CircuitType circuitType;
private ProofSystem system;
private String data;
private int size;
public String getCircuitId() { return circuitId; }
public void setCircuitId(String circuitId) { this.circuitId = circuitId; }
public CircuitType getCircuitType() { return circuitType; }
public void setCircuitType(CircuitType circuitType) { this.circuitType = circuitType; }
public ProofSystem getSystem() { return system; }
public void setSystem(ProofSystem system) { this.system = system; }
public String getData() { return data; }
public void setData(String data) { this.data = data; }
public int getSize() { return size; }
public void setSize(int size) { this.size = size; }
}
/** Circuit configuration */
public static class CircuitConfig {
private CircuitType type;
private Integer maxBatchSize;
private Integer treeDepth;
private Boolean verifySignatures;
private Map<String, Object> customConstraints;
public CircuitType getType() { return type; }
public void setType(CircuitType type) { this.type = type; }
public Integer getMaxBatchSize() { return maxBatchSize; }
public void setMaxBatchSize(Integer maxBatchSize) { this.maxBatchSize = maxBatchSize; }
public Integer getTreeDepth() { return treeDepth; }
public void setTreeDepth(Integer treeDepth) { this.treeDepth = treeDepth; }
public Boolean getVerifySignatures() { return verifySignatures; }
public void setVerifySignatures(Boolean verifySignatures) { this.verifySignatures = verifySignatures; }
public Map<String, Object> getCustomConstraints() { return customConstraints; }
public void setCustomConstraints(Map<String, Object> customConstraints) { this.customConstraints = customConstraints; }
}
/** Account state in the rollup */
public static class AccountState {
private String address;
private String balance;
private long nonce;
private String pubkeyHash;
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
public String getBalance() { return balance; }
public void setBalance(String balance) { this.balance = balance; }
public long getNonce() { return nonce; }
public void setNonce(long nonce) { this.nonce = nonce; }
public String getPubkeyHash() { return pubkeyHash; }
public void setPubkeyHash(String pubkeyHash) { this.pubkeyHash = pubkeyHash; }
}
/** Transfer operation */
public static class Transfer {
private String from;
private String to;
private String amount;
private String fee;
private long nonce;
private String signature;
public Transfer() {}
public Transfer(String from, String to, String amount, String fee, long nonce) {
this.from = from;
this.to = to;
this.amount = amount;
this.fee = fee;
this.nonce = nonce;
}
public String getFrom() { return from; }
public void setFrom(String from) { this.from = from; }
public String getTo() { return to; }
public void setTo(String to) { this.to = to; }
public String getAmount() { return amount; }
public void setAmount(String amount) { this.amount = amount; }
public String getFee() { return fee; }
public void setFee(String fee) { this.fee = fee; }
public long getNonce() { return nonce; }
public void setNonce(long nonce) { this.nonce = nonce; }
public String getSignature() { return signature; }
public void setSignature(String signature) { this.signature = signature; }
}
/** Deposit operation (L1 -> L2) */
public static class Deposit {
private String l1TxHash;
private String recipient;
private String amount;
private String token;
public Deposit() {}
public Deposit(String l1TxHash, String recipient, String amount) {
this.l1TxHash = l1TxHash;
this.recipient = recipient;
this.amount = amount;
}
public String getL1TxHash() { return l1TxHash; }
public void setL1TxHash(String l1TxHash) { this.l1TxHash = l1TxHash; }
public String getRecipient() { return recipient; }
public void setRecipient(String recipient) { this.recipient = recipient; }
public String getAmount() { return amount; }
public void setAmount(String amount) { this.amount = amount; }
public String getToken() { return token; }
public void setToken(String token) { this.token = token; }
}
/** Withdrawal operation (L2 -> L1) */
public static class Withdrawal {
private String sender;
private String recipient;
private String amount;
private String token;
private long nonce;
private String signature;
public Withdrawal() {}
public Withdrawal(String sender, String recipient, String amount, long nonce) {
this.sender = sender;
this.recipient = recipient;
this.amount = amount;
this.nonce = nonce;
}
public String getSender() { return sender; }
public void setSender(String sender) { this.sender = sender; }
public String getRecipient() { return recipient; }
public void setRecipient(String recipient) { this.recipient = recipient; }
public String getAmount() { return amount; }
public void setAmount(String amount) { this.amount = amount; }
public String getToken() { return token; }
public void setToken(String token) { this.token = token; }
public long getNonce() { return nonce; }
public void setNonce(long nonce) { this.nonce = nonce; }
public String getSignature() { return signature; }
public void setSignature(String signature) { this.signature = signature; }
}
/** Rollup batch */
public static class Batch {
private long batchNumber;
private String prevStateRoot;
private String newStateRoot;
private List<Transfer> transfers;
private List<Deposit> deposits;
private List<Withdrawal> withdrawals;
private Proof proof;
private long timestamp;
public long getBatchNumber() { return batchNumber; }
public void setBatchNumber(long batchNumber) { this.batchNumber = batchNumber; }
public String getPrevStateRoot() { return prevStateRoot; }
public void setPrevStateRoot(String prevStateRoot) { this.prevStateRoot = prevStateRoot; }
public String getNewStateRoot() { return newStateRoot; }
public void setNewStateRoot(String newStateRoot) { this.newStateRoot = newStateRoot; }
public List<Transfer> getTransfers() { return transfers; }
public void setTransfers(List<Transfer> transfers) { this.transfers = transfers; }
public List<Deposit> getDeposits() { return deposits; }
public void setDeposits(List<Deposit> deposits) { this.deposits = deposits; }
public List<Withdrawal> getWithdrawals() { return withdrawals; }
public void setWithdrawals(List<Withdrawal> withdrawals) { this.withdrawals = withdrawals; }
public Proof getProof() { return proof; }
public void setProof(Proof proof) { this.proof = proof; }
public long getTimestamp() { return timestamp; }
public void setTimestamp(long timestamp) { this.timestamp = timestamp; }
}
/** Rollup statistics */
public static class RollupStats {
private long currentBatch;
private long totalTransactions;
private long totalProofs;
private long avgProofTimeMs;
private String stateRoot;
private long accountCount;
private String tvl;
public long getCurrentBatch() { return currentBatch; }
public void setCurrentBatch(long currentBatch) { this.currentBatch = currentBatch; }
public long getTotalTransactions() { return totalTransactions; }
public void setTotalTransactions(long totalTransactions) { this.totalTransactions = totalTransactions; }
public long getTotalProofs() { return totalProofs; }
public void setTotalProofs(long totalProofs) { this.totalProofs = totalProofs; }
public long getAvgProofTimeMs() { return avgProofTimeMs; }
public void setAvgProofTimeMs(long avgProofTimeMs) { this.avgProofTimeMs = avgProofTimeMs; }
public String getStateRoot() { return stateRoot; }
public void setStateRoot(String stateRoot) { this.stateRoot = stateRoot; }
public long getAccountCount() { return accountCount; }
public void setAccountCount(long accountCount) { this.accountCount = accountCount; }
public String getTvl() { return tvl; }
public void setTvl(String tvl) { this.tvl = tvl; }
}
/** Proof generation request */
public static class ProofRequest {
private CircuitType circuitType;
private List<String> publicInputs;
private List<String> privateInputs;
private ProofSystem system;
public ProofRequest() {}
public ProofRequest(CircuitType circuitType, List<String> publicInputs, List<String> privateInputs) {
this.circuitType = circuitType;
this.publicInputs = publicInputs;
this.privateInputs = privateInputs;
}
public CircuitType getCircuitType() { return circuitType; }
public void setCircuitType(CircuitType circuitType) { this.circuitType = circuitType; }
public List<String> getPublicInputs() { return publicInputs; }
public void setPublicInputs(List<String> publicInputs) { this.publicInputs = publicInputs; }
public List<String> getPrivateInputs() { return privateInputs; }
public void setPrivateInputs(List<String> privateInputs) { this.privateInputs = privateInputs; }
public ProofSystem getSystem() { return system; }
public void setSystem(ProofSystem system) { this.system = system; }
}
/** Proof verification result */
public static class VerificationResult {
private boolean valid;
private long verificationTimeMs;
private String error;
public boolean isValid() { return valid; }
public void setValid(boolean valid) { this.valid = valid; }
public long getVerificationTimeMs() { return verificationTimeMs; }
public void setVerificationTimeMs(long verificationTimeMs) { this.verificationTimeMs = verificationTimeMs; }
public String getError() { return error; }
public void setError(String error) { this.error = error; }
}
/** Merkle proof for state inclusion */
public static class MerkleProof {
private String leaf;
private List<String> path;
private List<Integer> indices;
private String root;
public String getLeaf() { return leaf; }
public void setLeaf(String leaf) { this.leaf = leaf; }
public List<String> getPath() { return path; }
public void setPath(List<String> path) { this.path = path; }
public List<Integer> getIndices() { return indices; }
public void setIndices(List<Integer> indices) { this.indices = indices; }
public String getRoot() { return root; }
public void setRoot(String root) { this.root = root; }
}
/** Trusted setup ceremony contribution */
public static class CeremonyContribution {
private String contributorId;
private String hash;
private long timestamp;
private boolean verified;
public String getContributorId() { return contributorId; }
public void setContributorId(String contributorId) { this.contributorId = contributorId; }
public String getHash() { return hash; }
public void setHash(String hash) { this.hash = hash; }
public long getTimestamp() { return timestamp; }
public void setTimestamp(long timestamp) { this.timestamp = timestamp; }
public boolean isVerified() { return verified; }
public void setVerified(boolean verified) { this.verified = verified; }
}
/** Trusted setup ceremony */
public static class TrustedSetup {
private String id;
private CircuitType circuitType;
private ProofSystem system;
private int contributionCount;
private String latestHash;
private boolean complete;
private List<CeremonyContribution> contributions;
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public CircuitType getCircuitType() { return circuitType; }
public void setCircuitType(CircuitType circuitType) { this.circuitType = circuitType; }
public ProofSystem getSystem() { return system; }
public void setSystem(ProofSystem system) { this.system = system; }
public int getContributionCount() { return contributionCount; }
public void setContributionCount(int contributionCount) { this.contributionCount = contributionCount; }
public String getLatestHash() { return latestHash; }
public void setLatestHash(String latestHash) { this.latestHash = latestHash; }
public boolean isComplete() { return complete; }
public void setComplete(boolean complete) { this.complete = complete; }
public List<CeremonyContribution> getContributions() { return contributions; }
public void setContributions(List<CeremonyContribution> contributions) { this.contributions = contributions; }
}
/** ZK SDK configuration */
public static class ZkConfig {
private String apiKey;
private String endpoint = "https://zk.synor.io/v1";
private String wsEndpoint = "wss://zk.synor.io/v1/ws";
private int timeout = 60000;
private int retries = 3;
private ProofSystem defaultProofSystem = ProofSystem.GROTH16;
private boolean debug = false;
public ZkConfig(String apiKey) {
this.apiKey = apiKey;
}
public String getApiKey() { return apiKey; }
public void setApiKey(String apiKey) { this.apiKey = apiKey; }
public String getEndpoint() { return endpoint; }
public void setEndpoint(String endpoint) { this.endpoint = endpoint; }
public String getWsEndpoint() { return wsEndpoint; }
public void setWsEndpoint(String wsEndpoint) { this.wsEndpoint = wsEndpoint; }
public int getTimeout() { return timeout; }
public void setTimeout(int timeout) { this.timeout = timeout; }
public int getRetries() { return retries; }
public void setRetries(int retries) { this.retries = retries; }
public ProofSystem getDefaultProofSystem() { return defaultProofSystem; }
public void setDefaultProofSystem(ProofSystem defaultProofSystem) { this.defaultProofSystem = defaultProofSystem; }
public boolean isDebug() { return debug; }
public void setDebug(boolean debug) { this.debug = debug; }
}
/** ZK SDK exception */
public static class ZkException extends RuntimeException {
private final String code;
private final Integer status;
public ZkException(String message) {
super(message);
this.code = null;
this.status = null;
}
public ZkException(String message, String code) {
super(message);
this.code = code;
this.status = null;
}
public ZkException(String message, String code, Integer status) {
super(message);
this.code = code;
this.status = status;
}
public String getCode() { return code; }
public Integer getStatus() { return status; }
}
/** Proof system characteristics */
public static class ProofSystemInfo {
public final String name;
public final int proofSize;
public final int verificationTimeMs;
public final boolean trustedSetup;
public final boolean universal;
public ProofSystemInfo(String name, int proofSize, int verificationTimeMs,
boolean trustedSetup, boolean universal) {
this.name = name;
this.proofSize = proofSize;
this.verificationTimeMs = verificationTimeMs;
this.trustedSetup = trustedSetup;
this.universal = universal;
}
}
public static ProofSystemInfo getProofSystemInfo(ProofSystem system) {
switch (system) {
case GROTH16:
return new ProofSystemInfo("Groth16", 192, 10, true, false);
case PLONK:
return new ProofSystemInfo("PLONK", 512, 15, true, true);
case STARK:
return new ProofSystemInfo("STARK", 50000, 30, false, true);
default:
return null;
}
}
// Constants
public static final int MAX_BATCH_SIZE = 1000;
public static final int STATE_TREE_DEPTH = 32;
public static final int PROOF_EXPIRY_BLOCKS = 100;
}

455
sdk/js/src/zk/index.ts Normal file
View file

@ -0,0 +1,455 @@
// Synor ZK SDK for JavaScript/TypeScript
//
// Zero-Knowledge proof systems for ZK-Rollups and privacy.
import {
ZkConfig,
ZkError,
DEFAULT_CONFIG,
ProofSystem,
CircuitType,
Proof,
VerificationKey,
ProvingKey,
CircuitConfig,
ProofRequest,
VerificationResult,
Batch,
RollupStats,
Transfer,
Deposit,
Withdrawal,
AccountState,
MerkleProof,
TrustedSetup,
CeremonyContribution,
} from './types';
export * from './types';
/**
* Synor ZK SDK Client
*
* Provides zero-knowledge proof generation and verification for ZK-Rollups.
*
* @example
* ```typescript
* const zk = new SynorZk({ apiKey: 'your-api-key' });
*
* // Generate a proof
* const proof = await zk.proofs.generate({
* circuitType: CircuitType.Transfer,
* publicInputs: [...],
* privateInputs: [...],
* });
*
* // Verify the proof
* const result = await zk.proofs.verify(proof);
* console.log('Valid:', result.valid);
* ```
*/
export class SynorZk {
private readonly config: Required<ZkConfig>;
private closed = false;
public readonly proofs: ProofsClient;
public readonly circuits: CircuitsClient;
public readonly rollup: RollupClient;
public readonly state: StateClient;
public readonly ceremony: CeremonyClient;
constructor(config: ZkConfig) {
this.config = {
...DEFAULT_CONFIG,
...config,
} as Required<ZkConfig>;
this.proofs = new ProofsClient(this);
this.circuits = new CircuitsClient(this);
this.rollup = new RollupClient(this);
this.state = new StateClient(this);
this.ceremony = new CeremonyClient(this);
}
/**
* Get the default proof system
*/
get defaultProofSystem(): ProofSystem {
return this.config.defaultProofSystem;
}
/**
* Health check
*/
async healthCheck(): Promise<boolean> {
try {
const result = await this.get<{ status: string }>('/health');
return result.status === 'healthy';
} catch {
return false;
}
}
/**
* Get service info
*/
async getInfo(): Promise<Record<string, unknown>> {
return this.get('/info');
}
/**
* Close the client
*/
close(): void {
this.closed = true;
}
/**
* Check if client is closed
*/
get isClosed(): boolean {
return this.closed;
}
// Internal HTTP methods
async get<T>(path: string): Promise<T> {
return this.request<T>('GET', path);
}
async post<T>(path: string, body?: unknown): Promise<T> {
return this.request<T>('POST', path, body);
}
async delete<T>(path: string): Promise<T> {
return this.request<T>('DELETE', path);
}
private async request<T>(method: string, path: string, body?: unknown): Promise<T> {
if (this.closed) {
throw new ZkError('Client has been closed', 'CLIENT_CLOSED');
}
const url = `${this.config.endpoint}${path}`;
const headers: Record<string, string> = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.config.apiKey}`,
'X-SDK-Version': 'js/0.1.0',
};
let lastError: Error | null = null;
for (let attempt = 0; attempt <= this.config.retries; attempt++) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
const response = await fetch(url, {
method,
headers,
body: body ? JSON.stringify(body) : undefined,
signal: controller.signal,
});
clearTimeout(timeoutId);
if (!response.ok) {
const error = await response.json().catch(() => ({}));
throw new ZkError(
error.message || `HTTP ${response.status}`,
error.code,
response.status
);
}
return await response.json();
} catch (error) {
lastError = error as Error;
if (error instanceof ZkError) throw error;
if (attempt < this.config.retries) {
await new Promise((r) => setTimeout(r, 100 * Math.pow(2, attempt)));
}
}
}
throw new ZkError(lastError?.message || 'Request failed', 'NETWORK_ERROR');
}
}
/**
* Proofs sub-client
*/
export class ProofsClient {
constructor(private readonly zk: SynorZk) {}
/**
* Generate a zero-knowledge proof
*/
async generate(request: ProofRequest): Promise<Proof> {
return this.zk.post('/proofs/generate', {
circuit_type: request.circuitType,
public_inputs: request.publicInputs,
private_inputs: request.privateInputs,
system: request.system || this.zk.defaultProofSystem,
});
}
/**
* Verify a proof
*/
async verify(proof: Proof): Promise<VerificationResult> {
return this.zk.post('/proofs/verify', {
proof_id: proof.id,
data: proof.data,
public_inputs: proof.publicInputs,
system: proof.system,
circuit_type: proof.circuitType,
});
}
/**
* Get a proof by ID
*/
async get(proofId: string): Promise<Proof> {
return this.zk.get(`/proofs/${proofId}`);
}
/**
* List recent proofs
*/
async list(options?: { limit?: number; offset?: number }): Promise<Proof[]> {
const params = new URLSearchParams();
if (options?.limit) params.set('limit', options.limit.toString());
if (options?.offset) params.set('offset', options.offset.toString());
const query = params.toString();
const result = await this.zk.get<{ proofs: Proof[] }>(`/proofs${query ? `?${query}` : ''}`);
return result.proofs || [];
}
/**
* Serialize a proof to bytes
*/
async serialize(proof: Proof): Promise<Uint8Array> {
const result = await this.zk.post<{ data: string }>('/proofs/serialize', {
proof_id: proof.id,
});
return Uint8Array.from(atob(result.data), (c) => c.charCodeAt(0));
}
/**
* Deserialize bytes to a proof
*/
async deserialize(data: Uint8Array, system: ProofSystem): Promise<Proof> {
const base64 = btoa(String.fromCharCode(...data));
return this.zk.post('/proofs/deserialize', {
data: base64,
system,
});
}
}
/**
* Circuits sub-client
*/
export class CircuitsClient {
constructor(private readonly zk: SynorZk) {}
/**
* Get verification key for a circuit
*/
async getVerificationKey(circuitType: CircuitType, system?: ProofSystem): Promise<VerificationKey> {
return this.zk.get(`/circuits/${circuitType}/vk?system=${system || this.zk.defaultProofSystem}`);
}
/**
* Get proving key for a circuit
*/
async getProvingKey(circuitType: CircuitType, system?: ProofSystem): Promise<ProvingKey> {
return this.zk.get(`/circuits/${circuitType}/pk?system=${system || this.zk.defaultProofSystem}`);
}
/**
* List available circuits
*/
async list(): Promise<CircuitConfig[]> {
const result = await this.zk.get<{ circuits: CircuitConfig[] }>('/circuits');
return result.circuits || [];
}
/**
* Get circuit configuration
*/
async getConfig(circuitType: CircuitType): Promise<CircuitConfig> {
return this.zk.get(`/circuits/${circuitType}/config`);
}
/**
* Compile a custom circuit
*/
async compile(config: CircuitConfig): Promise<{ circuitId: string }> {
return this.zk.post('/circuits/compile', config);
}
}
/**
* Rollup sub-client
*/
export class RollupClient {
constructor(private readonly zk: SynorZk) {}
/**
* Get rollup statistics
*/
async getStats(): Promise<RollupStats> {
return this.zk.get('/rollup/stats');
}
/**
* Get current batch
*/
async getCurrentBatch(): Promise<Batch> {
return this.zk.get('/rollup/batch/current');
}
/**
* Get batch by number
*/
async getBatch(batchNumber: number): Promise<Batch> {
return this.zk.get(`/rollup/batch/${batchNumber}`);
}
/**
* Submit a transfer
*/
async submitTransfer(transfer: Transfer): Promise<{ txId: string }> {
return this.zk.post('/rollup/transfer', transfer);
}
/**
* Submit a deposit
*/
async submitDeposit(deposit: Deposit): Promise<{ txId: string }> {
return this.zk.post('/rollup/deposit', deposit);
}
/**
* Submit a withdrawal
*/
async submitWithdrawal(withdrawal: Withdrawal): Promise<{ txId: string }> {
return this.zk.post('/rollup/withdraw', withdrawal);
}
/**
* Finalize current batch (generates proof and submits to L1)
*/
async finalizeBatch(): Promise<Batch> {
return this.zk.post('/rollup/batch/finalize', {});
}
/**
* Get pending transactions
*/
async getPendingTransactions(): Promise<Transfer[]> {
const result = await this.zk.get<{ transactions: Transfer[] }>('/rollup/pending');
return result.transactions || [];
}
}
/**
* State sub-client
*/
export class StateClient {
constructor(private readonly zk: SynorZk) {}
/**
* Get current state root
*/
async getRoot(): Promise<string> {
const result = await this.zk.get<{ root: string }>('/state/root');
return result.root;
}
/**
* Get account state
*/
async getAccount(address: string): Promise<AccountState> {
return this.zk.get(`/state/account/${address}`);
}
/**
* Get merkle proof for account inclusion
*/
async getMerkleProof(address: string): Promise<MerkleProof> {
return this.zk.get(`/state/proof/${address}`);
}
/**
* Verify merkle proof
*/
async verifyMerkleProof(proof: MerkleProof): Promise<boolean> {
const result = await this.zk.post<{ valid: boolean }>('/state/proof/verify', proof);
return result.valid;
}
/**
* Get state at specific batch
*/
async getStateAtBatch(batchNumber: number): Promise<{ root: string; accountCount: number }> {
return this.zk.get(`/state/batch/${batchNumber}`);
}
}
/**
* Ceremony sub-client (trusted setup)
*/
export class CeremonyClient {
constructor(private readonly zk: SynorZk) {}
/**
* Get ceremony status
*/
async getStatus(circuitType: CircuitType, system?: ProofSystem): Promise<TrustedSetup> {
return this.zk.get(`/ceremony/${circuitType}?system=${system || this.zk.defaultProofSystem}`);
}
/**
* Contribute to ceremony
*/
async contribute(
circuitType: CircuitType,
entropy: Uint8Array,
system?: ProofSystem
): Promise<CeremonyContribution> {
const entropyBase64 = btoa(String.fromCharCode(...entropy));
return this.zk.post('/ceremony/contribute', {
circuit_type: circuitType,
entropy: entropyBase64,
system: system || this.zk.defaultProofSystem,
});
}
/**
* Verify a contribution
*/
async verifyContribution(
circuitType: CircuitType,
contributionHash: string
): Promise<{ valid: boolean }> {
return this.zk.post('/ceremony/verify', {
circuit_type: circuitType,
contribution_hash: contributionHash,
});
}
/**
* List contributions
*/
async listContributions(circuitType: CircuitType): Promise<CeremonyContribution[]> {
const result = await this.zk.get<{ contributions: CeremonyContribution[] }>(
`/ceremony/${circuitType}/contributions`
);
return result.contributions || [];
}
}
// Default export
export default SynorZk;

401
sdk/js/src/zk/types.ts Normal file
View file

@ -0,0 +1,401 @@
// Synor ZK SDK Types for JavaScript/TypeScript
//
// Zero-Knowledge proof systems for ZK-Rollups and privacy.
/**
* Proof system backends
*/
export enum ProofSystem {
/** Groth16 - smallest proofs (~192 bytes), fastest verification */
Groth16 = 'groth16',
/** PLONK - universal trusted setup, medium proofs (~512 bytes) */
Plonk = 'plonk',
/** STARK - no trusted setup, largest proofs (~50KB) */
Stark = 'stark',
}
/**
* Circuit types for different operations
*/
export enum CircuitType {
/** Single transfer between accounts */
Transfer = 'transfer',
/** Batch of multiple transfers */
Batch = 'batch',
/** Deposit from L1 to L2 */
Deposit = 'deposit',
/** Withdrawal from L2 to L1 */
Withdraw = 'withdraw',
}
/**
* Rollup state
*/
export enum RollupState {
/** Rollup is accepting transactions */
Active = 'active',
/** Rollup is paused */
Paused = 'paused',
/** Rollup is finalizing */
Finalizing = 'finalizing',
/** Rollup has been finalized */
Finalized = 'finalized',
}
/**
* Proof status
*/
export enum ProofStatus {
/** Proof is being generated */
Generating = 'generating',
/** Proof generation completed */
Completed = 'completed',
/** Proof generation failed */
Failed = 'failed',
/** Proof has been verified */
Verified = 'verified',
}
/**
* Zero-knowledge proof
*/
export interface Proof {
/** Unique proof identifier */
id: string;
/** Proof system used */
system: ProofSystem;
/** Circuit type */
circuitType: CircuitType;
/** Serialized proof data (base64) */
data: string;
/** Public inputs (base64 encoded) */
publicInputs: string[];
/** Proof size in bytes */
size: number;
/** Generation time in milliseconds */
generationTimeMs: number;
/** Timestamp when proof was created */
createdAt: number;
}
/**
* Verification key for a circuit
*/
export interface VerificationKey {
/** Circuit identifier */
circuitId: string;
/** Circuit type */
circuitType: CircuitType;
/** Proof system */
system: ProofSystem;
/** Serialized verification key (base64) */
data: string;
/** Key size in bytes */
size: number;
}
/**
* Proving key for generating proofs
*/
export interface ProvingKey {
/** Circuit identifier */
circuitId: string;
/** Circuit type */
circuitType: CircuitType;
/** Proof system */
system: ProofSystem;
/** Serialized proving key (base64) */
data: string;
/** Key size in bytes */
size: number;
}
/**
* Circuit configuration
*/
export interface CircuitConfig {
/** Circuit type */
type: CircuitType;
/** Maximum batch size for batch circuits */
maxBatchSize?: number;
/** State tree depth */
treeDepth?: number;
/** Whether to verify signatures in circuit */
verifySignatures?: boolean;
/** Custom constraints */
customConstraints?: Record<string, unknown>;
}
/**
* State tree node
*/
export interface StateNode {
/** Node hash */
hash: string;
/** Left child hash (if internal node) */
left?: string;
/** Right child hash (if internal node) */
right?: string;
/** Account data (if leaf node) */
account?: AccountState;
}
/**
* Account state in the rollup
*/
export interface AccountState {
/** Account address */
address: string;
/** Account balance */
balance: string;
/** Account nonce */
nonce: number;
/** Public key hash */
pubkeyHash: string;
}
/**
* Transfer operation
*/
export interface Transfer {
/** Sender address */
from: string;
/** Recipient address */
to: string;
/** Amount to transfer */
amount: string;
/** Fee */
fee: string;
/** Nonce */
nonce: number;
/** Signature */
signature?: string;
}
/**
* Deposit operation (L1 -> L2)
*/
export interface Deposit {
/** L1 transaction hash */
l1TxHash: string;
/** Recipient address on L2 */
recipient: string;
/** Amount deposited */
amount: string;
/** Token address (or native if null) */
token?: string;
}
/**
* Withdrawal operation (L2 -> L1)
*/
export interface Withdrawal {
/** Sender address on L2 */
sender: string;
/** Recipient address on L1 */
recipient: string;
/** Amount to withdraw */
amount: string;
/** Token address (or native if null) */
token?: string;
/** Nonce */
nonce: number;
/** Signature */
signature?: string;
}
/**
* Rollup batch
*/
export interface Batch {
/** Batch number */
batchNumber: number;
/** Previous state root */
prevStateRoot: string;
/** New state root after batch */
newStateRoot: string;
/** Transfers in this batch */
transfers: Transfer[];
/** Deposits in this batch */
deposits: Deposit[];
/** Withdrawals in this batch */
withdrawals: Withdrawal[];
/** Batch proof (once generated) */
proof?: Proof;
/** Timestamp */
timestamp: number;
}
/**
* Rollup statistics
*/
export interface RollupStats {
/** Current batch number */
currentBatch: number;
/** Total transactions processed */
totalTransactions: number;
/** Total proofs generated */
totalProofs: number;
/** Average proof generation time (ms) */
avgProofTimeMs: number;
/** Current state root */
stateRoot: string;
/** Number of accounts */
accountCount: number;
/** Total value locked */
tvl: string;
}
/**
* Proof generation request
*/
export interface ProofRequest {
/** Circuit type */
circuitType: CircuitType;
/** Public inputs */
publicInputs: string[];
/** Private inputs (witness) */
privateInputs: string[];
/** Proof system to use */
system?: ProofSystem;
}
/**
* Proof verification result
*/
export interface VerificationResult {
/** Whether the proof is valid */
valid: boolean;
/** Verification time in milliseconds */
verificationTimeMs: number;
/** Error message if invalid */
error?: string;
}
/**
* Setup ceremony contribution
*/
export interface CeremonyContribution {
/** Contributor identifier */
contributorId: string;
/** Contribution hash */
hash: string;
/** Timestamp */
timestamp: number;
/** Verification status */
verified: boolean;
}
/**
* Trusted setup ceremony
*/
export interface TrustedSetup {
/** Ceremony identifier */
id: string;
/** Circuit type */
circuitType: CircuitType;
/** Proof system */
system: ProofSystem;
/** Number of contributions */
contributionCount: number;
/** Latest contribution hash */
latestHash: string;
/** Whether ceremony is complete */
complete: boolean;
/** Contributions */
contributions: CeremonyContribution[];
}
/**
* Merkle proof for state inclusion
*/
export interface MerkleProof {
/** Leaf value */
leaf: string;
/** Path from leaf to root (sibling hashes) */
path: string[];
/** Path indices (0 = left, 1 = right) */
indices: number[];
/** Root hash */
root: string;
}
/**
* ZK SDK configuration
*/
export interface ZkConfig {
/** API key for authentication */
apiKey: string;
/** API endpoint */
endpoint?: string;
/** WebSocket endpoint for subscriptions */
wsEndpoint?: string;
/** Request timeout in milliseconds */
timeout?: number;
/** Number of retries for failed requests */
retries?: number;
/** Default proof system */
defaultProofSystem?: ProofSystem;
/** Enable debug logging */
debug?: boolean;
}
/**
* ZK SDK error
*/
export class ZkError extends Error {
constructor(
message: string,
public readonly code?: string,
public readonly status?: number
) {
super(message);
this.name = 'ZkError';
}
}
/**
* Default configuration values
*/
export const DEFAULT_CONFIG = {
endpoint: 'https://zk.synor.io/v1',
wsEndpoint: 'wss://zk.synor.io/v1/ws',
timeout: 60000, // ZK proofs can take longer
retries: 3,
defaultProofSystem: ProofSystem.Groth16,
debug: false,
} as const;
/**
* Proof system characteristics
*/
export const PROOF_SYSTEM_INFO = {
[ProofSystem.Groth16]: {
name: 'Groth16',
proofSize: 192,
verificationTimeMs: 10,
trustedSetup: true,
universal: false,
},
[ProofSystem.Plonk]: {
name: 'PLONK',
proofSize: 512,
verificationTimeMs: 15,
trustedSetup: true,
universal: true,
},
[ProofSystem.Stark]: {
name: 'STARK',
proofSize: 50000,
verificationTimeMs: 30,
trustedSetup: false,
universal: true,
},
} as const;
/**
* Constants
*/
export const MAX_BATCH_SIZE = 1000;
export const STATE_TREE_DEPTH = 32;
export const PROOF_EXPIRY_BLOCKS = 100;

View file

@ -0,0 +1,449 @@
package io.synor.zk
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.*
import kotlinx.serialization.json.*
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.time.Duration
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
/**
* Synor ZK SDK for Kotlin
*
* Zero-Knowledge proof systems for ZK-Rollups and privacy.
*/
// Enums
enum class ProofSystem(val value: String) {
@SerialName("groth16") GROTH16("groth16"),
@SerialName("plonk") PLONK("plonk"),
@SerialName("stark") STARK("stark");
companion object {
fun fromString(value: String) = entries.find { it.value == value } ?: GROTH16
}
}
enum class CircuitType(val value: String) {
@SerialName("transfer") TRANSFER("transfer"),
@SerialName("batch") BATCH("batch"),
@SerialName("deposit") DEPOSIT("deposit"),
@SerialName("withdraw") WITHDRAW("withdraw");
companion object {
fun fromString(value: String) = entries.find { it.value == value } ?: TRANSFER
}
}
enum class RollupState { ACTIVE, PAUSED, FINALIZING, FINALIZED }
enum class ProofStatus { GENERATING, COMPLETED, FAILED, VERIFIED }
// Data classes
@Serializable
data class Proof(
val id: String,
val system: ProofSystem,
@SerialName("circuit_type") val circuitType: CircuitType,
val data: String,
@SerialName("public_inputs") val publicInputs: List<String>,
val size: Int,
@SerialName("generation_time_ms") val generationTimeMs: Long,
@SerialName("created_at") val createdAt: Long
)
@Serializable
data class VerificationKey(
@SerialName("circuit_id") val circuitId: String,
@SerialName("circuit_type") val circuitType: CircuitType,
val system: ProofSystem,
val data: String,
val size: Int
)
@Serializable
data class ProvingKey(
@SerialName("circuit_id") val circuitId: String,
@SerialName("circuit_type") val circuitType: CircuitType,
val system: ProofSystem,
val data: String,
val size: Int
)
@Serializable
data class CircuitConfig(
val type: CircuitType,
@SerialName("max_batch_size") val maxBatchSize: Int? = null,
@SerialName("tree_depth") val treeDepth: Int? = null,
@SerialName("verify_signatures") val verifySignatures: Boolean? = null,
@SerialName("custom_constraints") val customConstraints: JsonObject? = null
)
@Serializable
data class AccountState(
val address: String,
val balance: String,
val nonce: Long,
@SerialName("pubkey_hash") val pubkeyHash: String
)
@Serializable
data class Transfer(
val from: String,
val to: String,
val amount: String,
val fee: String,
val nonce: Long,
val signature: String? = null
)
@Serializable
data class Deposit(
@SerialName("l1_tx_hash") val l1TxHash: String,
val recipient: String,
val amount: String,
val token: String? = null
)
@Serializable
data class Withdrawal(
val sender: String,
val recipient: String,
val amount: String,
val token: String? = null,
val nonce: Long,
val signature: String? = null
)
@Serializable
data class Batch(
@SerialName("batch_number") val batchNumber: Long,
@SerialName("prev_state_root") val prevStateRoot: String,
@SerialName("new_state_root") val newStateRoot: String,
val transfers: List<Transfer>,
val deposits: List<Deposit>,
val withdrawals: List<Withdrawal>,
val proof: Proof? = null,
val timestamp: Long
)
@Serializable
data class RollupStats(
@SerialName("current_batch") val currentBatch: Long,
@SerialName("total_transactions") val totalTransactions: Long,
@SerialName("total_proofs") val totalProofs: Long,
@SerialName("avg_proof_time_ms") val avgProofTimeMs: Long,
@SerialName("state_root") val stateRoot: String,
@SerialName("account_count") val accountCount: Long,
val tvl: String
)
@Serializable
data class ProofRequest(
@SerialName("circuit_type") val circuitType: CircuitType,
@SerialName("public_inputs") val publicInputs: List<String>,
@SerialName("private_inputs") val privateInputs: List<String>,
val system: ProofSystem? = null
)
@Serializable
data class VerificationResult(
val valid: Boolean,
@SerialName("verification_time_ms") val verificationTimeMs: Long,
val error: String? = null
)
@Serializable
data class MerkleProof(
val leaf: String,
val path: List<String>,
val indices: List<Int>,
val root: String
)
@Serializable
data class CeremonyContribution(
@SerialName("contributor_id") val contributorId: String,
val hash: String,
val timestamp: Long,
val verified: Boolean
)
@Serializable
data class TrustedSetup(
val id: String,
@SerialName("circuit_type") val circuitType: CircuitType,
val system: ProofSystem,
@SerialName("contribution_count") val contributionCount: Int,
@SerialName("latest_hash") val latestHash: String,
val complete: Boolean,
val contributions: List<CeremonyContribution>
)
data class ZkConfig(
val apiKey: String,
val endpoint: String = "https://zk.synor.io/v1",
val wsEndpoint: String = "wss://zk.synor.io/v1/ws",
val timeout: Long = 60000,
val retries: Int = 3,
val defaultProofSystem: ProofSystem = ProofSystem.GROTH16,
val debug: Boolean = false
)
class ZkException(
message: String,
val code: String? = null,
val status: Int? = null
) : RuntimeException(message)
data class ProofSystemInfo(
val name: String,
val proofSize: Int,
val verificationTimeMs: Int,
val trustedSetup: Boolean,
val universal: Boolean
)
fun getProofSystemInfo(system: ProofSystem): ProofSystemInfo = when (system) {
ProofSystem.GROTH16 -> ProofSystemInfo("Groth16", 192, 10, true, false)
ProofSystem.PLONK -> ProofSystemInfo("PLONK", 512, 15, true, true)
ProofSystem.STARK -> ProofSystemInfo("STARK", 50000, 30, false, true)
}
const val MAX_BATCH_SIZE = 1000
const val STATE_TREE_DEPTH = 32
const val PROOF_EXPIRY_BLOCKS = 100
/**
* Main ZK SDK client
*/
class SynorZk(private val config: ZkConfig) {
private val httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofMillis(config.timeout))
.build()
private val json = Json { ignoreUnknownKeys = true }
private val closed = AtomicBoolean(false)
val proofs = ProofsClient(this)
val circuits = CircuitsClient(this)
val rollup = RollupClient(this)
val state = StateClient(this)
val ceremony = CeremonyClient(this)
val defaultProofSystem: ProofSystem get() = config.defaultProofSystem
suspend fun healthCheck(): Boolean = try {
val result = get<JsonObject>("/health")
result["status"]?.jsonPrimitive?.content == "healthy"
} catch (e: Exception) {
false
}
suspend fun getInfo(): JsonObject = get("/info")
fun close() { closed.set(true) }
val isClosed: Boolean get() = closed.get()
internal suspend inline fun <reified T> get(path: String): T = request("GET", path, null)
internal suspend inline fun <reified T> post(path: String, body: Any?): T = request("POST", path, body)
internal suspend inline fun <reified T> request(method: String, path: String, body: Any?): T {
if (closed.get()) throw ZkException("Client has been closed", "CLIENT_CLOSED")
return withContext(Dispatchers.IO) {
val url = "${config.endpoint}$path"
val requestBuilder = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer ${config.apiKey}")
.header("X-SDK-Version", "kotlin/0.1.0")
.timeout(Duration.ofMillis(config.timeout))
when (method) {
"GET" -> requestBuilder.GET()
"POST" -> {
val jsonBody = if (body != null) json.encodeToString(body as? JsonElement ?: buildJsonObject {
(body as? Map<*, *>)?.forEach { (k, v) ->
put(k.toString(), when (v) {
is String -> JsonPrimitive(v)
is Number -> JsonPrimitive(v)
is Boolean -> JsonPrimitive(v)
is List<*> -> JsonArray(v.map { JsonPrimitive(it.toString()) })
else -> JsonPrimitive(v.toString())
})
}
}) else "{}"
requestBuilder.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
}
"DELETE" -> requestBuilder.DELETE()
}
val response = httpClient.send(requestBuilder.build(), HttpResponse.BodyHandlers.ofString())
if (response.statusCode() >= 400) {
val error = json.parseToJsonElement(response.body()).jsonObject
throw ZkException(
error["message"]?.jsonPrimitive?.content ?: "HTTP ${response.statusCode()}",
error["code"]?.jsonPrimitive?.content,
response.statusCode()
)
}
json.decodeFromString(response.body())
}
}
}
class ProofsClient(private val zk: SynorZk) {
suspend fun generate(request: ProofRequest): Proof {
val body = buildJsonObject {
put("circuit_type", request.circuitType.value)
put("public_inputs", JsonArray(request.publicInputs.map { JsonPrimitive(it) }))
put("private_inputs", JsonArray(request.privateInputs.map { JsonPrimitive(it) }))
put("system", (request.system ?: zk.defaultProofSystem).value)
}
return zk.post("/proofs/generate", body)
}
suspend fun verify(proof: Proof): VerificationResult {
val body = buildJsonObject {
put("proof_id", proof.id)
put("data", proof.data)
put("public_inputs", JsonArray(proof.publicInputs.map { JsonPrimitive(it) }))
put("system", proof.system.value)
put("circuit_type", proof.circuitType.value)
}
return zk.post("/proofs/verify", body)
}
suspend fun get(proofId: String): Proof = zk.get("/proofs/$proofId")
suspend fun list(limit: Int? = null, offset: Int? = null): List<Proof> {
val params = listOfNotNull(
limit?.let { "limit=$it" },
offset?.let { "offset=$it" }
).joinToString("&")
val path = if (params.isNotEmpty()) "/proofs?$params" else "/proofs"
val result: JsonObject = zk.get(path)
return result["proofs"]?.jsonArray?.map { Json.decodeFromJsonElement(it) } ?: emptyList()
}
suspend fun serialize(proof: Proof): ByteArray {
val body = buildJsonObject { put("proof_id", proof.id) }
val result: JsonObject = zk.post("/proofs/serialize", body)
return Base64.getDecoder().decode(result["data"]?.jsonPrimitive?.content)
}
suspend fun deserialize(data: ByteArray, system: ProofSystem): Proof {
val body = buildJsonObject {
put("data", Base64.getEncoder().encodeToString(data))
put("system", system.value)
}
return zk.post("/proofs/deserialize", body)
}
}
class CircuitsClient(private val zk: SynorZk) {
suspend fun getVerificationKey(circuitType: CircuitType, system: ProofSystem? = null): VerificationKey {
val sys = system ?: zk.defaultProofSystem
return zk.get("/circuits/${circuitType.value}/vk?system=${sys.value}")
}
suspend fun getProvingKey(circuitType: CircuitType, system: ProofSystem? = null): ProvingKey {
val sys = system ?: zk.defaultProofSystem
return zk.get("/circuits/${circuitType.value}/pk?system=${sys.value}")
}
suspend fun list(): List<CircuitConfig> {
val result: JsonObject = zk.get("/circuits")
return result["circuits"]?.jsonArray?.map { Json.decodeFromJsonElement(it) } ?: emptyList()
}
suspend fun getConfig(circuitType: CircuitType): CircuitConfig =
zk.get("/circuits/${circuitType.value}/config")
suspend fun compile(config: CircuitConfig): String {
val result: JsonObject = zk.post("/circuits/compile", Json.encodeToJsonElement(config))
return result["circuit_id"]?.jsonPrimitive?.content ?: ""
}
}
class RollupClient(private val zk: SynorZk) {
suspend fun getStats(): RollupStats = zk.get("/rollup/stats")
suspend fun getCurrentBatch(): Batch = zk.get("/rollup/batch/current")
suspend fun getBatch(batchNumber: Long): Batch = zk.get("/rollup/batch/$batchNumber")
suspend fun submitTransfer(transfer: Transfer): String {
val result: JsonObject = zk.post("/rollup/transfer", Json.encodeToJsonElement(transfer))
return result["tx_id"]?.jsonPrimitive?.content ?: ""
}
suspend fun submitDeposit(deposit: Deposit): String {
val result: JsonObject = zk.post("/rollup/deposit", Json.encodeToJsonElement(deposit))
return result["tx_id"]?.jsonPrimitive?.content ?: ""
}
suspend fun submitWithdrawal(withdrawal: Withdrawal): String {
val result: JsonObject = zk.post("/rollup/withdraw", Json.encodeToJsonElement(withdrawal))
return result["tx_id"]?.jsonPrimitive?.content ?: ""
}
suspend fun finalizeBatch(): Batch = zk.post("/rollup/batch/finalize", buildJsonObject {})
suspend fun getPendingTransactions(): List<Transfer> {
val result: JsonObject = zk.get("/rollup/pending")
return result["transactions"]?.jsonArray?.map { Json.decodeFromJsonElement(it) } ?: emptyList()
}
}
class StateClient(private val zk: SynorZk) {
suspend fun getRoot(): String {
val result: JsonObject = zk.get("/state/root")
return result["root"]?.jsonPrimitive?.content ?: ""
}
suspend fun getAccount(address: String): AccountState = zk.get("/state/account/$address")
suspend fun getMerkleProof(address: String): MerkleProof = zk.get("/state/proof/$address")
suspend fun verifyMerkleProof(proof: MerkleProof): Boolean {
val result: JsonObject = zk.post("/state/proof/verify", Json.encodeToJsonElement(proof))
return result["valid"]?.jsonPrimitive?.boolean ?: false
}
suspend fun getStateAtBatch(batchNumber: Long): JsonObject = zk.get("/state/batch/$batchNumber")
}
class CeremonyClient(private val zk: SynorZk) {
suspend fun getStatus(circuitType: CircuitType, system: ProofSystem? = null): TrustedSetup {
val sys = system ?: zk.defaultProofSystem
return zk.get("/ceremony/${circuitType.value}?system=${sys.value}")
}
suspend fun contribute(circuitType: CircuitType, entropy: ByteArray, system: ProofSystem? = null): CeremonyContribution {
val sys = system ?: zk.defaultProofSystem
val body = buildJsonObject {
put("circuit_type", circuitType.value)
put("entropy", Base64.getEncoder().encodeToString(entropy))
put("system", sys.value)
}
return zk.post("/ceremony/contribute", body)
}
suspend fun verifyContribution(circuitType: CircuitType, contributionHash: String): Boolean {
val body = buildJsonObject {
put("circuit_type", circuitType.value)
put("contribution_hash", contributionHash)
}
val result: JsonObject = zk.post("/ceremony/verify", body)
return result["valid"]?.jsonPrimitive?.boolean ?: false
}
suspend fun listContributions(circuitType: CircuitType): List<CeremonyContribution> {
val result: JsonObject = zk.get("/ceremony/${circuitType.value}/contributions")
return result["contributions"]?.jsonArray?.map { Json.decodeFromJsonElement(it) } ?: emptyList()
}
}

View file

@ -0,0 +1,62 @@
"""
Synor ZK SDK for Python
Zero-Knowledge proof systems for ZK-Rollups and privacy.
"""
from .types import (
ProofSystem,
CircuitType,
RollupState,
ProofStatus,
Proof,
VerificationKey,
ProvingKey,
CircuitConfig,
AccountState,
Transfer,
Deposit,
Withdrawal,
Batch,
RollupStats,
ProofRequest,
VerificationResult,
MerkleProof,
TrustedSetup,
CeremonyContribution,
ZkConfig,
ZkError,
DEFAULT_CONFIG,
MAX_BATCH_SIZE,
STATE_TREE_DEPTH,
)
from .client import SynorZk
__version__ = "0.1.0"
__all__ = [
"SynorZk",
"ProofSystem",
"CircuitType",
"RollupState",
"ProofStatus",
"Proof",
"VerificationKey",
"ProvingKey",
"CircuitConfig",
"AccountState",
"Transfer",
"Deposit",
"Withdrawal",
"Batch",
"RollupStats",
"ProofRequest",
"VerificationResult",
"MerkleProof",
"TrustedSetup",
"CeremonyContribution",
"ZkConfig",
"ZkError",
"DEFAULT_CONFIG",
"MAX_BATCH_SIZE",
"STATE_TREE_DEPTH",
]

View file

@ -0,0 +1,407 @@
"""
Synor ZK SDK Client for Python
Zero-Knowledge proof systems for ZK-Rollups and privacy.
"""
import asyncio
import base64
from typing import Optional, List, Dict, Any
import httpx
from .types import (
ProofSystem,
CircuitType,
Proof,
VerificationKey,
ProvingKey,
CircuitConfig,
AccountState,
Transfer,
Deposit,
Withdrawal,
Batch,
RollupStats,
ProofRequest,
VerificationResult,
MerkleProof,
TrustedSetup,
CeremonyContribution,
ZkConfig,
ZkError,
)
class SynorZk:
"""
Synor ZK SDK Client
Provides zero-knowledge proof generation and verification for ZK-Rollups.
Example:
```python
async with SynorZk(ZkConfig(api_key="your-api-key")) as zk:
# Generate a proof
proof = await zk.proofs.generate(ProofRequest(
circuit_type=CircuitType.TRANSFER,
public_inputs=[...],
private_inputs=[...],
))
# Verify the proof
result = await zk.proofs.verify(proof)
print(f"Valid: {result.valid}")
```
"""
def __init__(self, config: ZkConfig):
self.config = config
self._client: Optional[httpx.AsyncClient] = None
self._closed = False
self.proofs = ProofsClient(self)
self.circuits = CircuitsClient(self)
self.rollup = RollupClient(self)
self.state = StateClient(self)
self.ceremony = CeremonyClient(self)
async def __aenter__(self) -> "SynorZk":
self._client = httpx.AsyncClient(timeout=self.config.timeout)
return self
async def __aexit__(self, *args) -> None:
await self.close()
@property
def default_proof_system(self) -> ProofSystem:
"""Get the default proof system"""
return self.config.default_proof_system
async def health_check(self) -> bool:
"""Health check"""
try:
result = await self._get("/health")
return result.get("status") == "healthy"
except Exception:
return False
async def get_info(self) -> Dict[str, Any]:
"""Get service info"""
return await self._get("/info")
async def close(self) -> None:
"""Close the client"""
self._closed = True
if self._client:
await self._client.aclose()
self._client = None
@property
def is_closed(self) -> bool:
"""Check if client is closed"""
return self._closed
async def _get(self, path: str) -> Dict[str, Any]:
"""Internal GET request"""
return await self._request("GET", path)
async def _post(self, path: str, body: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""Internal POST request"""
return await self._request("POST", path, body)
async def _delete(self, path: str) -> Dict[str, Any]:
"""Internal DELETE request"""
return await self._request("DELETE", path)
async def _request(
self,
method: str,
path: str,
body: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""Internal HTTP request with retries"""
if self._closed:
raise ZkError("Client has been closed", code="CLIENT_CLOSED")
if not self._client:
self._client = httpx.AsyncClient(timeout=self.config.timeout)
url = f"{self.config.endpoint}{path}"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {self.config.api_key}",
"X-SDK-Version": "python/0.1.0",
}
last_error: Optional[Exception] = None
for attempt in range(self.config.retries + 1):
try:
if method == "GET":
response = await self._client.get(url, headers=headers)
elif method == "POST":
response = await self._client.post(url, headers=headers, json=body)
elif method == "DELETE":
response = await self._client.delete(url, headers=headers)
else:
raise ValueError(f"Unknown method: {method}")
if response.status_code >= 400:
error = response.json() if response.content else {}
raise ZkError(
error.get("message", f"HTTP {response.status_code}"),
code=error.get("code"),
status=response.status_code,
)
return response.json()
except ZkError:
raise
except Exception as e:
last_error = e
if attempt < self.config.retries:
await asyncio.sleep(0.1 * (2 ** attempt))
raise ZkError(
str(last_error) if last_error else "Request failed",
code="NETWORK_ERROR",
)
class ProofsClient:
"""Proofs sub-client"""
def __init__(self, zk: SynorZk):
self._zk = zk
async def generate(self, request: ProofRequest) -> Proof:
"""Generate a zero-knowledge proof"""
body = request.to_dict()
if not body.get("system"):
body["system"] = self._zk.default_proof_system.value
result = await self._zk._post("/proofs/generate", body)
return Proof.from_dict(result)
async def verify(self, proof: Proof) -> VerificationResult:
"""Verify a proof"""
result = await self._zk._post("/proofs/verify", {
"proof_id": proof.id,
"data": proof.data,
"public_inputs": proof.public_inputs,
"system": proof.system.value,
"circuit_type": proof.circuit_type.value,
})
return VerificationResult.from_dict(result)
async def get(self, proof_id: str) -> Proof:
"""Get a proof by ID"""
result = await self._zk._get(f"/proofs/{proof_id}")
return Proof.from_dict(result)
async def list(
self,
limit: Optional[int] = None,
offset: Optional[int] = None,
) -> List[Proof]:
"""List recent proofs"""
params = []
if limit:
params.append(f"limit={limit}")
if offset:
params.append(f"offset={offset}")
query = f"?{'&'.join(params)}" if params else ""
result = await self._zk._get(f"/proofs{query}")
return [Proof.from_dict(p) for p in result.get("proofs", [])]
async def serialize(self, proof: Proof) -> bytes:
"""Serialize a proof to bytes"""
result = await self._zk._post("/proofs/serialize", {"proof_id": proof.id})
return base64.b64decode(result["data"])
async def deserialize(self, data: bytes, system: ProofSystem) -> Proof:
"""Deserialize bytes to a proof"""
result = await self._zk._post("/proofs/deserialize", {
"data": base64.b64encode(data).decode(),
"system": system.value,
})
return Proof.from_dict(result)
class CircuitsClient:
"""Circuits sub-client"""
def __init__(self, zk: SynorZk):
self._zk = zk
async def get_verification_key(
self,
circuit_type: CircuitType,
system: Optional[ProofSystem] = None,
) -> VerificationKey:
"""Get verification key for a circuit"""
sys = system or self._zk.default_proof_system
result = await self._zk._get(f"/circuits/{circuit_type.value}/vk?system={sys.value}")
return VerificationKey.from_dict(result)
async def get_proving_key(
self,
circuit_type: CircuitType,
system: Optional[ProofSystem] = None,
) -> ProvingKey:
"""Get proving key for a circuit"""
sys = system or self._zk.default_proof_system
result = await self._zk._get(f"/circuits/{circuit_type.value}/pk?system={sys.value}")
return ProvingKey.from_dict(result)
async def list(self) -> List[CircuitConfig]:
"""List available circuits"""
result = await self._zk._get("/circuits")
return [CircuitConfig.from_dict(c) for c in result.get("circuits", [])]
async def get_config(self, circuit_type: CircuitType) -> CircuitConfig:
"""Get circuit configuration"""
result = await self._zk._get(f"/circuits/{circuit_type.value}/config")
return CircuitConfig.from_dict(result)
async def compile(self, config: CircuitConfig) -> str:
"""Compile a custom circuit, returns circuit ID"""
result = await self._zk._post("/circuits/compile", {
"type": config.type.value,
"max_batch_size": config.max_batch_size,
"tree_depth": config.tree_depth,
"verify_signatures": config.verify_signatures,
"custom_constraints": config.custom_constraints,
})
return result["circuit_id"]
class RollupClient:
"""Rollup sub-client"""
def __init__(self, zk: SynorZk):
self._zk = zk
async def get_stats(self) -> RollupStats:
"""Get rollup statistics"""
result = await self._zk._get("/rollup/stats")
return RollupStats.from_dict(result)
async def get_current_batch(self) -> Batch:
"""Get current batch"""
result = await self._zk._get("/rollup/batch/current")
return Batch.from_dict(result)
async def get_batch(self, batch_number: int) -> Batch:
"""Get batch by number"""
result = await self._zk._get(f"/rollup/batch/{batch_number}")
return Batch.from_dict(result)
async def submit_transfer(self, transfer: Transfer) -> str:
"""Submit a transfer, returns transaction ID"""
result = await self._zk._post("/rollup/transfer", transfer.to_dict())
return result["tx_id"]
async def submit_deposit(self, deposit: Deposit) -> str:
"""Submit a deposit, returns transaction ID"""
result = await self._zk._post("/rollup/deposit", deposit.to_dict())
return result["tx_id"]
async def submit_withdrawal(self, withdrawal: Withdrawal) -> str:
"""Submit a withdrawal, returns transaction ID"""
result = await self._zk._post("/rollup/withdraw", withdrawal.to_dict())
return result["tx_id"]
async def finalize_batch(self) -> Batch:
"""Finalize current batch (generates proof and submits to L1)"""
result = await self._zk._post("/rollup/batch/finalize", {})
return Batch.from_dict(result)
async def get_pending_transactions(self) -> List[Transfer]:
"""Get pending transactions"""
result = await self._zk._get("/rollup/pending")
return [Transfer.from_dict(t) for t in result.get("transactions", [])]
class StateClient:
"""State sub-client"""
def __init__(self, zk: SynorZk):
self._zk = zk
async def get_root(self) -> str:
"""Get current state root"""
result = await self._zk._get("/state/root")
return result["root"]
async def get_account(self, address: str) -> AccountState:
"""Get account state"""
result = await self._zk._get(f"/state/account/{address}")
return AccountState.from_dict(result)
async def get_merkle_proof(self, address: str) -> MerkleProof:
"""Get merkle proof for account inclusion"""
result = await self._zk._get(f"/state/proof/{address}")
return MerkleProof.from_dict(result)
async def verify_merkle_proof(self, proof: MerkleProof) -> bool:
"""Verify merkle proof"""
result = await self._zk._post("/state/proof/verify", proof.to_dict())
return result["valid"]
async def get_state_at_batch(self, batch_number: int) -> Dict[str, Any]:
"""Get state at specific batch"""
return await self._zk._get(f"/state/batch/{batch_number}")
class CeremonyClient:
"""Ceremony sub-client (trusted setup)"""
def __init__(self, zk: SynorZk):
self._zk = zk
async def get_status(
self,
circuit_type: CircuitType,
system: Optional[ProofSystem] = None,
) -> TrustedSetup:
"""Get ceremony status"""
sys = system or self._zk.default_proof_system
result = await self._zk._get(f"/ceremony/{circuit_type.value}?system={sys.value}")
return TrustedSetup.from_dict(result)
async def contribute(
self,
circuit_type: CircuitType,
entropy: bytes,
system: Optional[ProofSystem] = None,
) -> CeremonyContribution:
"""Contribute to ceremony"""
sys = system or self._zk.default_proof_system
result = await self._zk._post("/ceremony/contribute", {
"circuit_type": circuit_type.value,
"entropy": base64.b64encode(entropy).decode(),
"system": sys.value,
})
return CeremonyContribution.from_dict(result)
async def verify_contribution(
self,
circuit_type: CircuitType,
contribution_hash: str,
) -> bool:
"""Verify a contribution"""
result = await self._zk._post("/ceremony/verify", {
"circuit_type": circuit_type.value,
"contribution_hash": contribution_hash,
})
return result["valid"]
async def list_contributions(
self,
circuit_type: CircuitType,
) -> List[CeremonyContribution]:
"""List contributions"""
result = await self._zk._get(f"/ceremony/{circuit_type.value}/contributions")
return [CeremonyContribution.from_dict(c) for c in result.get("contributions", [])]

View file

@ -0,0 +1,464 @@
"""
Synor ZK SDK Types for Python
Zero-Knowledge proof systems for ZK-Rollups and privacy.
"""
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional, List, Dict, Any
class ProofSystem(str, Enum):
"""Proof system backends"""
GROTH16 = "groth16" # Smallest proofs (~192 bytes), fastest verification
PLONK = "plonk" # Universal trusted setup, medium proofs (~512 bytes)
STARK = "stark" # No trusted setup, largest proofs (~50KB)
class CircuitType(str, Enum):
"""Circuit types for different operations"""
TRANSFER = "transfer" # Single transfer between accounts
BATCH = "batch" # Batch of multiple transfers
DEPOSIT = "deposit" # Deposit from L1 to L2
WITHDRAW = "withdraw" # Withdrawal from L2 to L1
class RollupState(str, Enum):
"""Rollup state"""
ACTIVE = "active"
PAUSED = "paused"
FINALIZING = "finalizing"
FINALIZED = "finalized"
class ProofStatus(str, Enum):
"""Proof status"""
GENERATING = "generating"
COMPLETED = "completed"
FAILED = "failed"
VERIFIED = "verified"
@dataclass
class Proof:
"""Zero-knowledge proof"""
id: str
system: ProofSystem
circuit_type: CircuitType
data: str # Base64 encoded
public_inputs: List[str]
size: int
generation_time_ms: int
created_at: int
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "Proof":
return cls(
id=data["id"],
system=ProofSystem(data["system"]),
circuit_type=CircuitType(data["circuit_type"]),
data=data["data"],
public_inputs=data.get("public_inputs", []),
size=data.get("size", 0),
generation_time_ms=data.get("generation_time_ms", 0),
created_at=data.get("created_at", 0),
)
@dataclass
class VerificationKey:
"""Verification key for a circuit"""
circuit_id: str
circuit_type: CircuitType
system: ProofSystem
data: str # Base64 encoded
size: int
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "VerificationKey":
return cls(
circuit_id=data["circuit_id"],
circuit_type=CircuitType(data["circuit_type"]),
system=ProofSystem(data["system"]),
data=data["data"],
size=data.get("size", 0),
)
@dataclass
class ProvingKey:
"""Proving key for generating proofs"""
circuit_id: str
circuit_type: CircuitType
system: ProofSystem
data: str # Base64 encoded
size: int
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "ProvingKey":
return cls(
circuit_id=data["circuit_id"],
circuit_type=CircuitType(data["circuit_type"]),
system=ProofSystem(data["system"]),
data=data["data"],
size=data.get("size", 0),
)
@dataclass
class CircuitConfig:
"""Circuit configuration"""
type: CircuitType
max_batch_size: Optional[int] = None
tree_depth: Optional[int] = None
verify_signatures: Optional[bool] = None
custom_constraints: Optional[Dict[str, Any]] = None
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "CircuitConfig":
return cls(
type=CircuitType(data["type"]),
max_batch_size=data.get("max_batch_size"),
tree_depth=data.get("tree_depth"),
verify_signatures=data.get("verify_signatures"),
custom_constraints=data.get("custom_constraints"),
)
@dataclass
class AccountState:
"""Account state in the rollup"""
address: str
balance: str
nonce: int
pubkey_hash: str
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "AccountState":
return cls(
address=data["address"],
balance=data["balance"],
nonce=data.get("nonce", 0),
pubkey_hash=data.get("pubkey_hash", ""),
)
@dataclass
class Transfer:
"""Transfer operation"""
from_addr: str
to: str
amount: str
fee: str
nonce: int
signature: Optional[str] = None
def to_dict(self) -> Dict[str, Any]:
result = {
"from": self.from_addr,
"to": self.to,
"amount": self.amount,
"fee": self.fee,
"nonce": self.nonce,
}
if self.signature:
result["signature"] = self.signature
return result
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "Transfer":
return cls(
from_addr=data["from"],
to=data["to"],
amount=data["amount"],
fee=data["fee"],
nonce=data.get("nonce", 0),
signature=data.get("signature"),
)
@dataclass
class Deposit:
"""Deposit operation (L1 -> L2)"""
l1_tx_hash: str
recipient: str
amount: str
token: Optional[str] = None
def to_dict(self) -> Dict[str, Any]:
result = {
"l1_tx_hash": self.l1_tx_hash,
"recipient": self.recipient,
"amount": self.amount,
}
if self.token:
result["token"] = self.token
return result
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "Deposit":
return cls(
l1_tx_hash=data["l1_tx_hash"],
recipient=data["recipient"],
amount=data["amount"],
token=data.get("token"),
)
@dataclass
class Withdrawal:
"""Withdrawal operation (L2 -> L1)"""
sender: str
recipient: str
amount: str
token: Optional[str] = None
nonce: int = 0
signature: Optional[str] = None
def to_dict(self) -> Dict[str, Any]:
result = {
"sender": self.sender,
"recipient": self.recipient,
"amount": self.amount,
"nonce": self.nonce,
}
if self.token:
result["token"] = self.token
if self.signature:
result["signature"] = self.signature
return result
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "Withdrawal":
return cls(
sender=data["sender"],
recipient=data["recipient"],
amount=data["amount"],
token=data.get("token"),
nonce=data.get("nonce", 0),
signature=data.get("signature"),
)
@dataclass
class Batch:
"""Rollup batch"""
batch_number: int
prev_state_root: str
new_state_root: str
transfers: List[Transfer]
deposits: List[Deposit]
withdrawals: List[Withdrawal]
proof: Optional[Proof] = None
timestamp: int = 0
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "Batch":
return cls(
batch_number=data["batch_number"],
prev_state_root=data["prev_state_root"],
new_state_root=data["new_state_root"],
transfers=[Transfer.from_dict(t) for t in data.get("transfers", [])],
deposits=[Deposit.from_dict(d) for d in data.get("deposits", [])],
withdrawals=[Withdrawal.from_dict(w) for w in data.get("withdrawals", [])],
proof=Proof.from_dict(data["proof"]) if data.get("proof") else None,
timestamp=data.get("timestamp", 0),
)
@dataclass
class RollupStats:
"""Rollup statistics"""
current_batch: int
total_transactions: int
total_proofs: int
avg_proof_time_ms: int
state_root: str
account_count: int
tvl: str
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "RollupStats":
return cls(
current_batch=data["current_batch"],
total_transactions=data.get("total_transactions", 0),
total_proofs=data.get("total_proofs", 0),
avg_proof_time_ms=data.get("avg_proof_time_ms", 0),
state_root=data["state_root"],
account_count=data.get("account_count", 0),
tvl=data.get("tvl", "0"),
)
@dataclass
class ProofRequest:
"""Proof generation request"""
circuit_type: CircuitType
public_inputs: List[str]
private_inputs: List[str]
system: Optional[ProofSystem] = None
def to_dict(self) -> Dict[str, Any]:
result = {
"circuit_type": self.circuit_type.value,
"public_inputs": self.public_inputs,
"private_inputs": self.private_inputs,
}
if self.system:
result["system"] = self.system.value
return result
@dataclass
class VerificationResult:
"""Proof verification result"""
valid: bool
verification_time_ms: int
error: Optional[str] = None
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "VerificationResult":
return cls(
valid=data["valid"],
verification_time_ms=data.get("verification_time_ms", 0),
error=data.get("error"),
)
@dataclass
class MerkleProof:
"""Merkle proof for state inclusion"""
leaf: str
path: List[str]
indices: List[int]
root: str
def to_dict(self) -> Dict[str, Any]:
return {
"leaf": self.leaf,
"path": self.path,
"indices": self.indices,
"root": self.root,
}
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "MerkleProof":
return cls(
leaf=data["leaf"],
path=data["path"],
indices=data["indices"],
root=data["root"],
)
@dataclass
class CeremonyContribution:
"""Trusted setup ceremony contribution"""
contributor_id: str
hash: str
timestamp: int
verified: bool
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "CeremonyContribution":
return cls(
contributor_id=data["contributor_id"],
hash=data["hash"],
timestamp=data.get("timestamp", 0),
verified=data.get("verified", False),
)
@dataclass
class TrustedSetup:
"""Trusted setup ceremony"""
id: str
circuit_type: CircuitType
system: ProofSystem
contribution_count: int
latest_hash: str
complete: bool
contributions: List[CeremonyContribution]
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> "TrustedSetup":
return cls(
id=data["id"],
circuit_type=CircuitType(data["circuit_type"]),
system=ProofSystem(data["system"]),
contribution_count=data.get("contribution_count", 0),
latest_hash=data.get("latest_hash", ""),
complete=data.get("complete", False),
contributions=[
CeremonyContribution.from_dict(c)
for c in data.get("contributions", [])
],
)
@dataclass
class ZkConfig:
"""ZK SDK configuration"""
api_key: str
endpoint: str = "https://zk.synor.io/v1"
ws_endpoint: str = "wss://zk.synor.io/v1/ws"
timeout: int = 60 # Seconds (ZK proofs take longer)
retries: int = 3
default_proof_system: ProofSystem = ProofSystem.GROTH16
debug: bool = False
class ZkError(Exception):
"""ZK SDK error"""
def __init__(
self,
message: str,
code: Optional[str] = None,
status: Optional[int] = None,
):
super().__init__(message)
self.code = code
self.status = status
# Default configuration
DEFAULT_CONFIG = {
"endpoint": "https://zk.synor.io/v1",
"ws_endpoint": "wss://zk.synor.io/v1/ws",
"timeout": 60,
"retries": 3,
"default_proof_system": ProofSystem.GROTH16,
"debug": False,
}
# Constants
MAX_BATCH_SIZE = 1000
STATE_TREE_DEPTH = 32
PROOF_EXPIRY_BLOCKS = 100
# Proof system characteristics
PROOF_SYSTEM_INFO = {
ProofSystem.GROTH16: {
"name": "Groth16",
"proof_size": 192,
"verification_time_ms": 10,
"trusted_setup": True,
"universal": False,
},
ProofSystem.PLONK: {
"name": "PLONK",
"proof_size": 512,
"verification_time_ms": 15,
"trusted_setup": True,
"universal": True,
},
ProofSystem.STARK: {
"name": "STARK",
"proof_size": 50000,
"verification_time_ms": 30,
"trusted_setup": False,
"universal": True,
},
}

770
sdk/ruby/lib/synor/zk.rb Normal file
View file

@ -0,0 +1,770 @@
# frozen_string_literal: true
require 'net/http'
require 'uri'
require 'json'
require 'base64'
module Synor
# ZK SDK for Ruby
#
# Zero-Knowledge proof systems for ZK-Rollups and privacy.
module Zk
VERSION = '0.1.0'
# Proof system backends
module ProofSystem
GROTH16 = 'groth16' # Smallest proofs (~192 bytes), fastest verification
PLONK = 'plonk' # Universal trusted setup, medium proofs (~512 bytes)
STARK = 'stark' # No trusted setup, largest proofs (~50KB)
end
# Circuit types for different operations
module CircuitType
TRANSFER = 'transfer' # Single transfer between accounts
BATCH = 'batch' # Batch of multiple transfers
DEPOSIT = 'deposit' # Deposit from L1 to L2
WITHDRAW = 'withdraw' # Withdrawal from L2 to L1
end
# Rollup state
module RollupState
ACTIVE = 'active'
PAUSED = 'paused'
FINALIZING = 'finalizing'
FINALIZED = 'finalized'
end
# Proof status
module ProofStatus
GENERATING = 'generating'
COMPLETED = 'completed'
FAILED = 'failed'
VERIFIED = 'verified'
end
# Zero-knowledge proof
class Proof
attr_reader :id, :system, :circuit_type, :data, :public_inputs,
:size, :generation_time_ms, :created_at
def initialize(id:, system:, circuit_type:, data:, public_inputs:,
size:, generation_time_ms:, created_at:)
@id = id
@system = system
@circuit_type = circuit_type
@data = data
@public_inputs = public_inputs
@size = size
@generation_time_ms = generation_time_ms
@created_at = created_at
end
def self.from_json(json)
Proof.new(
id: json['id'],
system: json['system'],
circuit_type: json['circuit_type'],
data: json['data'],
public_inputs: json['public_inputs'] || [],
size: json['size'] || 0,
generation_time_ms: json['generation_time_ms'] || 0,
created_at: json['created_at'] || 0
)
end
def to_json(*_args)
{
'id' => @id,
'system' => @system,
'circuit_type' => @circuit_type,
'data' => @data,
'public_inputs' => @public_inputs,
'size' => @size,
'generation_time_ms' => @generation_time_ms,
'created_at' => @created_at
}
end
end
# Verification key
class VerificationKey
attr_reader :circuit_id, :circuit_type, :system, :data, :size
def initialize(circuit_id:, circuit_type:, system:, data:, size:)
@circuit_id = circuit_id
@circuit_type = circuit_type
@system = system
@data = data
@size = size
end
def self.from_json(json)
VerificationKey.new(
circuit_id: json['circuit_id'],
circuit_type: json['circuit_type'],
system: json['system'],
data: json['data'],
size: json['size'] || 0
)
end
end
# Proving key
class ProvingKey
attr_reader :circuit_id, :circuit_type, :system, :data, :size
def initialize(circuit_id:, circuit_type:, system:, data:, size:)
@circuit_id = circuit_id
@circuit_type = circuit_type
@system = system
@data = data
@size = size
end
def self.from_json(json)
ProvingKey.new(
circuit_id: json['circuit_id'],
circuit_type: json['circuit_type'],
system: json['system'],
data: json['data'],
size: json['size'] || 0
)
end
end
# Circuit configuration
class CircuitConfig
attr_reader :type, :max_batch_size, :tree_depth, :verify_signatures, :custom_constraints
def initialize(type:, max_batch_size: nil, tree_depth: nil,
verify_signatures: nil, custom_constraints: nil)
@type = type
@max_batch_size = max_batch_size
@tree_depth = tree_depth
@verify_signatures = verify_signatures
@custom_constraints = custom_constraints
end
def self.from_json(json)
CircuitConfig.new(
type: json['type'],
max_batch_size: json['max_batch_size'],
tree_depth: json['tree_depth'],
verify_signatures: json['verify_signatures'],
custom_constraints: json['custom_constraints']
)
end
def to_json(*_args)
result = { 'type' => @type }
result['max_batch_size'] = @max_batch_size if @max_batch_size
result['tree_depth'] = @tree_depth if @tree_depth
result['verify_signatures'] = @verify_signatures unless @verify_signatures.nil?
result['custom_constraints'] = @custom_constraints if @custom_constraints
result
end
end
# Account state
class AccountState
attr_reader :address, :balance, :nonce, :pubkey_hash
def initialize(address:, balance:, nonce:, pubkey_hash:)
@address = address
@balance = balance
@nonce = nonce
@pubkey_hash = pubkey_hash
end
def self.from_json(json)
AccountState.new(
address: json['address'],
balance: json['balance'],
nonce: json['nonce'] || 0,
pubkey_hash: json['pubkey_hash'] || ''
)
end
end
# Transfer operation
class Transfer
attr_reader :from, :to, :amount, :fee, :nonce, :signature
def initialize(from:, to:, amount:, fee:, nonce:, signature: nil)
@from = from
@to = to
@amount = amount
@fee = fee
@nonce = nonce
@signature = signature
end
def self.from_json(json)
Transfer.new(
from: json['from'],
to: json['to'],
amount: json['amount'],
fee: json['fee'],
nonce: json['nonce'] || 0,
signature: json['signature']
)
end
def to_json(*_args)
result = { 'from' => @from, 'to' => @to, 'amount' => @amount, 'fee' => @fee, 'nonce' => @nonce }
result['signature'] = @signature if @signature
result
end
end
# Deposit operation
class Deposit
attr_reader :l1_tx_hash, :recipient, :amount, :token
def initialize(l1_tx_hash:, recipient:, amount:, token: nil)
@l1_tx_hash = l1_tx_hash
@recipient = recipient
@amount = amount
@token = token
end
def to_json(*_args)
result = { 'l1_tx_hash' => @l1_tx_hash, 'recipient' => @recipient, 'amount' => @amount }
result['token'] = @token if @token
result
end
end
# Withdrawal operation
class Withdrawal
attr_reader :sender, :recipient, :amount, :token, :nonce, :signature
def initialize(sender:, recipient:, amount:, nonce:, token: nil, signature: nil)
@sender = sender
@recipient = recipient
@amount = amount
@token = token
@nonce = nonce
@signature = signature
end
def to_json(*_args)
result = { 'sender' => @sender, 'recipient' => @recipient, 'amount' => @amount, 'nonce' => @nonce }
result['token'] = @token if @token
result['signature'] = @signature if @signature
result
end
end
# Rollup batch
class Batch
attr_reader :batch_number, :prev_state_root, :new_state_root,
:transfers, :deposits, :withdrawals, :proof, :timestamp
def initialize(batch_number:, prev_state_root:, new_state_root:, transfers:,
deposits:, withdrawals:, proof: nil, timestamp:)
@batch_number = batch_number
@prev_state_root = prev_state_root
@new_state_root = new_state_root
@transfers = transfers
@deposits = deposits
@withdrawals = withdrawals
@proof = proof
@timestamp = timestamp
end
def self.from_json(json)
Batch.new(
batch_number: json['batch_number'],
prev_state_root: json['prev_state_root'],
new_state_root: json['new_state_root'],
transfers: (json['transfers'] || []).map { |t| Transfer.from_json(t) },
deposits: json['deposits'] || [],
withdrawals: json['withdrawals'] || [],
proof: json['proof'] ? Proof.from_json(json['proof']) : nil,
timestamp: json['timestamp'] || 0
)
end
end
# Rollup statistics
class RollupStats
attr_reader :current_batch, :total_transactions, :total_proofs,
:avg_proof_time_ms, :state_root, :account_count, :tvl
def initialize(current_batch:, total_transactions:, total_proofs:,
avg_proof_time_ms:, state_root:, account_count:, tvl:)
@current_batch = current_batch
@total_transactions = total_transactions
@total_proofs = total_proofs
@avg_proof_time_ms = avg_proof_time_ms
@state_root = state_root
@account_count = account_count
@tvl = tvl
end
def self.from_json(json)
RollupStats.new(
current_batch: json['current_batch'],
total_transactions: json['total_transactions'] || 0,
total_proofs: json['total_proofs'] || 0,
avg_proof_time_ms: json['avg_proof_time_ms'] || 0,
state_root: json['state_root'],
account_count: json['account_count'] || 0,
tvl: json['tvl'] || '0'
)
end
end
# Proof request
class ProofRequest
attr_reader :circuit_type, :public_inputs, :private_inputs, :system
def initialize(circuit_type:, public_inputs:, private_inputs:, system: nil)
@circuit_type = circuit_type
@public_inputs = public_inputs
@private_inputs = private_inputs
@system = system
end
def to_json(*_args)
result = {
'circuit_type' => @circuit_type,
'public_inputs' => @public_inputs,
'private_inputs' => @private_inputs
}
result['system'] = @system if @system
result
end
end
# Verification result
class VerificationResult
attr_reader :valid, :verification_time_ms, :error
def initialize(valid:, verification_time_ms:, error: nil)
@valid = valid
@verification_time_ms = verification_time_ms
@error = error
end
def self.from_json(json)
VerificationResult.new(
valid: json['valid'],
verification_time_ms: json['verification_time_ms'] || 0,
error: json['error']
)
end
end
# Merkle proof
class MerkleProof
attr_reader :leaf, :path, :indices, :root
def initialize(leaf:, path:, indices:, root:)
@leaf = leaf
@path = path
@indices = indices
@root = root
end
def self.from_json(json)
MerkleProof.new(
leaf: json['leaf'],
path: json['path'],
indices: json['indices'],
root: json['root']
)
end
def to_json(*_args)
{ 'leaf' => @leaf, 'path' => @path, 'indices' => @indices, 'root' => @root }
end
end
# Ceremony contribution
class CeremonyContribution
attr_reader :contributor_id, :hash, :timestamp, :verified
def initialize(contributor_id:, hash:, timestamp:, verified:)
@contributor_id = contributor_id
@hash = hash
@timestamp = timestamp
@verified = verified
end
def self.from_json(json)
CeremonyContribution.new(
contributor_id: json['contributor_id'],
hash: json['hash'],
timestamp: json['timestamp'] || 0,
verified: json['verified'] || false
)
end
end
# Trusted setup ceremony
class TrustedSetup
attr_reader :id, :circuit_type, :system, :contribution_count,
:latest_hash, :complete, :contributions
def initialize(id:, circuit_type:, system:, contribution_count:,
latest_hash:, complete:, contributions:)
@id = id
@circuit_type = circuit_type
@system = system
@contribution_count = contribution_count
@latest_hash = latest_hash
@complete = complete
@contributions = contributions
end
def self.from_json(json)
TrustedSetup.new(
id: json['id'],
circuit_type: json['circuit_type'],
system: json['system'],
contribution_count: json['contribution_count'] || 0,
latest_hash: json['latest_hash'] || '',
complete: json['complete'] || false,
contributions: (json['contributions'] || []).map { |c| CeremonyContribution.from_json(c) }
)
end
end
# ZK SDK configuration
class Config
attr_accessor :api_key, :endpoint, :ws_endpoint, :timeout, :retries,
:default_proof_system, :debug
def initialize(
api_key:,
endpoint: 'https://zk.synor.io/v1',
ws_endpoint: 'wss://zk.synor.io/v1/ws',
timeout: 60,
retries: 3,
default_proof_system: ProofSystem::GROTH16,
debug: false
)
@api_key = api_key
@endpoint = endpoint
@ws_endpoint = ws_endpoint
@timeout = timeout
@retries = retries
@default_proof_system = default_proof_system
@debug = debug
end
end
# ZK exception
class ZkError < StandardError
attr_reader :code, :status
def initialize(message, code: nil, status: nil)
super(message)
@code = code
@status = status
end
end
# Proof system info
ProofSystemInfo = Struct.new(:name, :proof_size, :verification_time_ms, :trusted_setup, :universal)
PROOF_SYSTEM_INFO = {
ProofSystem::GROTH16 => ProofSystemInfo.new('Groth16', 192, 10, true, false),
ProofSystem::PLONK => ProofSystemInfo.new('PLONK', 512, 15, true, true),
ProofSystem::STARK => ProofSystemInfo.new('STARK', 50_000, 30, false, true)
}.freeze
# Constants
MAX_BATCH_SIZE = 1000
STATE_TREE_DEPTH = 32
PROOF_EXPIRY_BLOCKS = 100
# Main ZK client
class Client
attr_reader :proofs, :circuits, :rollup, :state, :ceremony
def initialize(config)
@config = config
@closed = false
@proofs = ProofsClient.new(self)
@circuits = CircuitsClient.new(self)
@rollup = RollupClient.new(self)
@state = StateClient.new(self)
@ceremony = CeremonyClient.new(self)
end
def default_proof_system
@config.default_proof_system
end
def health_check
result = get('/health')
result['status'] == 'healthy'
rescue StandardError
false
end
def get_info
get('/info')
end
def close
@closed = true
end
def closed?
@closed
end
def get(path)
request(:get, path)
end
def post(path, body)
request(:post, path, body)
end
private
def request(method, path, body = nil)
raise ZkError.new('Client has been closed', code: 'CLIENT_CLOSED') if @closed
uri = URI.parse("#{@config.endpoint}#{path}")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = uri.scheme == 'https'
http.read_timeout = @config.timeout
request = case method
when :get
Net::HTTP::Get.new(uri.request_uri)
when :post
req = Net::HTTP::Post.new(uri.request_uri)
req.body = body.to_json if body
req
end
request['Content-Type'] = 'application/json'
request['Authorization'] = "Bearer #{@config.api_key}"
request['X-SDK-Version'] = 'ruby/0.1.0'
response = http.request(request)
unless response.is_a?(Net::HTTPSuccess)
error = JSON.parse(response.body) rescue {}
raise ZkError.new(
error['message'] || "HTTP #{response.code}",
code: error['code'],
status: response.code.to_i
)
end
JSON.parse(response.body)
end
end
# Proofs sub-client
class ProofsClient
def initialize(zk)
@zk = zk
end
def generate(request)
body = request.to_json
body['system'] ||= @zk.default_proof_system
result = @zk.post('/proofs/generate', body)
Proof.from_json(result)
end
def verify(proof)
result = @zk.post('/proofs/verify', {
'proof_id' => proof.id,
'data' => proof.data,
'public_inputs' => proof.public_inputs,
'system' => proof.system,
'circuit_type' => proof.circuit_type
})
VerificationResult.from_json(result)
end
def get(proof_id)
result = @zk.get("/proofs/#{proof_id}")
Proof.from_json(result)
end
def list(limit: nil, offset: nil)
params = []
params << "limit=#{limit}" if limit
params << "offset=#{offset}" if offset
path = params.empty? ? '/proofs' : "/proofs?#{params.join('&')}"
result = @zk.get(path)
(result['proofs'] || []).map { |p| Proof.from_json(p) }
end
def serialize(proof)
result = @zk.post('/proofs/serialize', { 'proof_id' => proof.id })
Base64.strict_decode64(result['data'])
end
def deserialize(data, system)
result = @zk.post('/proofs/deserialize', {
'data' => Base64.strict_encode64(data),
'system' => system
})
Proof.from_json(result)
end
end
# Circuits sub-client
class CircuitsClient
def initialize(zk)
@zk = zk
end
def get_verification_key(circuit_type, system = nil)
sys = system || @zk.default_proof_system
result = @zk.get("/circuits/#{circuit_type}/vk?system=#{sys}")
VerificationKey.from_json(result)
end
def get_proving_key(circuit_type, system = nil)
sys = system || @zk.default_proof_system
result = @zk.get("/circuits/#{circuit_type}/pk?system=#{sys}")
ProvingKey.from_json(result)
end
def list
result = @zk.get('/circuits')
(result['circuits'] || []).map { |c| CircuitConfig.from_json(c) }
end
def get_config(circuit_type)
result = @zk.get("/circuits/#{circuit_type}/config")
CircuitConfig.from_json(result)
end
def compile(config)
result = @zk.post('/circuits/compile', config.to_json)
result['circuit_id']
end
end
# Rollup sub-client
class RollupClient
def initialize(zk)
@zk = zk
end
def get_stats
result = @zk.get('/rollup/stats')
RollupStats.from_json(result)
end
def get_current_batch
result = @zk.get('/rollup/batch/current')
Batch.from_json(result)
end
def get_batch(batch_number)
result = @zk.get("/rollup/batch/#{batch_number}")
Batch.from_json(result)
end
def submit_transfer(transfer)
result = @zk.post('/rollup/transfer', transfer.to_json)
result['tx_id']
end
def submit_deposit(deposit)
result = @zk.post('/rollup/deposit', deposit.to_json)
result['tx_id']
end
def submit_withdrawal(withdrawal)
result = @zk.post('/rollup/withdraw', withdrawal.to_json)
result['tx_id']
end
def finalize_batch
result = @zk.post('/rollup/batch/finalize', {})
Batch.from_json(result)
end
def get_pending_transactions
result = @zk.get('/rollup/pending')
(result['transactions'] || []).map { |t| Transfer.from_json(t) }
end
end
# State sub-client
class StateClient
def initialize(zk)
@zk = zk
end
def get_root
result = @zk.get('/state/root')
result['root']
end
def get_account(address)
result = @zk.get("/state/account/#{address}")
AccountState.from_json(result)
end
def get_merkle_proof(address)
result = @zk.get("/state/proof/#{address}")
MerkleProof.from_json(result)
end
def verify_merkle_proof(proof)
result = @zk.post('/state/proof/verify', proof.to_json)
result['valid']
end
def get_state_at_batch(batch_number)
@zk.get("/state/batch/#{batch_number}")
end
end
# Ceremony sub-client
class CeremonyClient
def initialize(zk)
@zk = zk
end
def get_status(circuit_type, system = nil)
sys = system || @zk.default_proof_system
result = @zk.get("/ceremony/#{circuit_type}?system=#{sys}")
TrustedSetup.from_json(result)
end
def contribute(circuit_type, entropy, system = nil)
sys = system || @zk.default_proof_system
result = @zk.post('/ceremony/contribute', {
'circuit_type' => circuit_type,
'entropy' => Base64.strict_encode64(entropy.pack('C*')),
'system' => sys
})
CeremonyContribution.from_json(result)
end
def verify_contribution(circuit_type, contribution_hash)
result = @zk.post('/ceremony/verify', {
'circuit_type' => circuit_type,
'contribution_hash' => contribution_hash
})
result['valid']
end
def list_contributions(circuit_type)
result = @zk.get("/ceremony/#{circuit_type}/contributions")
(result['contributions'] || []).map { |c| CeremonyContribution.from_json(c) }
end
end
end
end

376
sdk/rust/src/zk/client.rs Normal file
View file

@ -0,0 +1,376 @@
//! ZK SDK Client
use crate::zk::types::*;
use base64::{Engine as _, engine::general_purpose::STANDARD};
use reqwest::Client;
use serde::{de::DeserializeOwned, Serialize};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
/// Synor ZK SDK Client
pub struct SynorZk {
config: ZkConfig,
client: Client,
closed: Arc<AtomicBool>,
}
impl SynorZk {
/// Create a new ZK SDK client
pub fn new(config: ZkConfig) -> Self {
Self {
config,
client: Client::new(),
closed: Arc::new(AtomicBool::new(false)),
}
}
/// Get the default proof system
pub fn default_proof_system(&self) -> ProofSystem {
self.config.default_proof_system
}
/// Health check
pub async fn health_check(&self) -> bool {
match self.get::<serde_json::Value>("/health").await {
Ok(v) => v.get("status").and_then(|s| s.as_str()) == Some("healthy"),
Err(_) => false,
}
}
/// Get service info
pub async fn get_info(&self) -> ZkResult<serde_json::Value> {
self.get("/info").await
}
/// Close the client
pub fn close(&self) {
self.closed.store(true, Ordering::SeqCst);
}
/// Check if client is closed
pub fn is_closed(&self) -> bool {
self.closed.load(Ordering::SeqCst)
}
// ========================================================================
// Proof Operations
// ========================================================================
/// Generate a zero-knowledge proof
pub async fn generate_proof(&self, request: ProofRequest) -> ZkResult<Proof> {
let system = request.system.unwrap_or(self.default_proof_system());
self.post("/proofs/generate", &serde_json::json!({
"circuit_type": request.circuit_type,
"public_inputs": request.public_inputs,
"private_inputs": request.private_inputs,
"system": system,
})).await
}
/// Verify a proof
pub async fn verify_proof(&self, proof: &Proof) -> ZkResult<VerificationResult> {
self.post("/proofs/verify", &serde_json::json!({
"proof_id": proof.id,
"data": proof.data,
"public_inputs": proof.public_inputs,
"system": proof.system,
"circuit_type": proof.circuit_type,
})).await
}
/// Get a proof by ID
pub async fn get_proof(&self, proof_id: &str) -> ZkResult<Proof> {
self.get(&format!("/proofs/{}", proof_id)).await
}
/// List recent proofs
pub async fn list_proofs(&self, limit: Option<usize>, offset: Option<usize>) -> ZkResult<Vec<Proof>> {
let mut path = "/proofs".to_string();
if limit.is_some() || offset.is_some() {
path = format!("/proofs?limit={}&offset={}", limit.unwrap_or(10), offset.unwrap_or(0));
}
#[derive(Deserialize)]
struct Response { proofs: Vec<Proof> }
let resp: Response = self.get(&path).await?;
Ok(resp.proofs)
}
/// Serialize a proof to bytes
pub async fn serialize_proof(&self, proof: &Proof) -> ZkResult<Vec<u8>> {
#[derive(Deserialize)]
struct Response { data: String }
let resp: Response = self.post("/proofs/serialize", &serde_json::json!({
"proof_id": proof.id,
})).await?;
STANDARD.decode(&resp.data).map_err(|e| ZkError {
message: e.to_string(),
code: None,
status: None,
})
}
/// Deserialize bytes to a proof
pub async fn deserialize_proof(&self, data: &[u8], system: ProofSystem) -> ZkResult<Proof> {
self.post("/proofs/deserialize", &serde_json::json!({
"data": STANDARD.encode(data),
"system": system,
})).await
}
// ========================================================================
// Circuit Operations
// ========================================================================
/// Get verification key for a circuit
pub async fn get_verification_key(&self, circuit_type: CircuitType, system: Option<ProofSystem>) -> ZkResult<VerificationKey> {
let sys = system.unwrap_or(self.default_proof_system());
self.get(&format!("/circuits/{:?}/vk?system={:?}", circuit_type, sys).to_lowercase()).await
}
/// Get proving key for a circuit
pub async fn get_proving_key(&self, circuit_type: CircuitType, system: Option<ProofSystem>) -> ZkResult<ProvingKey> {
let sys = system.unwrap_or(self.default_proof_system());
self.get(&format!("/circuits/{:?}/pk?system={:?}", circuit_type, sys).to_lowercase()).await
}
/// List available circuits
pub async fn list_circuits(&self) -> ZkResult<Vec<CircuitConfig>> {
#[derive(Deserialize)]
struct Response { circuits: Vec<CircuitConfig> }
let resp: Response = self.get("/circuits").await?;
Ok(resp.circuits)
}
/// Get circuit configuration
pub async fn get_circuit_config(&self, circuit_type: CircuitType) -> ZkResult<CircuitConfig> {
self.get(&format!("/circuits/{:?}/config", circuit_type).to_lowercase()).await
}
/// Compile a custom circuit
pub async fn compile_circuit(&self, config: CircuitConfig) -> ZkResult<String> {
#[derive(Deserialize)]
struct Response { circuit_id: String }
let resp: Response = self.post("/circuits/compile", &config).await?;
Ok(resp.circuit_id)
}
// ========================================================================
// Rollup Operations
// ========================================================================
/// Get rollup statistics
pub async fn get_rollup_stats(&self) -> ZkResult<RollupStats> {
self.get("/rollup/stats").await
}
/// Get current batch
pub async fn get_current_batch(&self) -> ZkResult<Batch> {
self.get("/rollup/batch/current").await
}
/// Get batch by number
pub async fn get_batch(&self, batch_number: u64) -> ZkResult<Batch> {
self.get(&format!("/rollup/batch/{}", batch_number)).await
}
/// Submit a transfer
pub async fn submit_transfer(&self, transfer: Transfer) -> ZkResult<String> {
#[derive(Deserialize)]
struct Response { tx_id: String }
let resp: Response = self.post("/rollup/transfer", &transfer).await?;
Ok(resp.tx_id)
}
/// Submit a deposit
pub async fn submit_deposit(&self, deposit: Deposit) -> ZkResult<String> {
#[derive(Deserialize)]
struct Response { tx_id: String }
let resp: Response = self.post("/rollup/deposit", &deposit).await?;
Ok(resp.tx_id)
}
/// Submit a withdrawal
pub async fn submit_withdrawal(&self, withdrawal: Withdrawal) -> ZkResult<String> {
#[derive(Deserialize)]
struct Response { tx_id: String }
let resp: Response = self.post("/rollup/withdraw", &withdrawal).await?;
Ok(resp.tx_id)
}
/// Finalize current batch
pub async fn finalize_batch(&self) -> ZkResult<Batch> {
self.post("/rollup/batch/finalize", &()).await
}
/// Get pending transactions
pub async fn get_pending_transactions(&self) -> ZkResult<Vec<Transfer>> {
#[derive(Deserialize)]
struct Response { transactions: Vec<Transfer> }
let resp: Response = self.get("/rollup/pending").await?;
Ok(resp.transactions)
}
// ========================================================================
// State Operations
// ========================================================================
/// Get current state root
pub async fn get_state_root(&self) -> ZkResult<String> {
#[derive(Deserialize)]
struct Response { root: String }
let resp: Response = self.get("/state/root").await?;
Ok(resp.root)
}
/// Get account state
pub async fn get_account(&self, address: &str) -> ZkResult<AccountState> {
self.get(&format!("/state/account/{}", address)).await
}
/// Get merkle proof for account inclusion
pub async fn get_merkle_proof(&self, address: &str) -> ZkResult<MerkleProof> {
self.get(&format!("/state/proof/{}", address)).await
}
/// Verify merkle proof
pub async fn verify_merkle_proof(&self, proof: &MerkleProof) -> ZkResult<bool> {
#[derive(Deserialize)]
struct Response { valid: bool }
let resp: Response = self.post("/state/proof/verify", proof).await?;
Ok(resp.valid)
}
/// Get state at specific batch
pub async fn get_state_at_batch(&self, batch_number: u64) -> ZkResult<serde_json::Value> {
self.get(&format!("/state/batch/{}", batch_number)).await
}
// ========================================================================
// Ceremony Operations
// ========================================================================
/// Get ceremony status
pub async fn get_ceremony_status(&self, circuit_type: CircuitType, system: Option<ProofSystem>) -> ZkResult<TrustedSetup> {
let sys = system.unwrap_or(self.default_proof_system());
self.get(&format!("/ceremony/{:?}?system={:?}", circuit_type, sys).to_lowercase()).await
}
/// Contribute to ceremony
pub async fn contribute_to_ceremony(
&self,
circuit_type: CircuitType,
entropy: &[u8],
system: Option<ProofSystem>,
) -> ZkResult<CeremonyContribution> {
let sys = system.unwrap_or(self.default_proof_system());
self.post("/ceremony/contribute", &serde_json::json!({
"circuit_type": circuit_type,
"entropy": STANDARD.encode(entropy),
"system": sys,
})).await
}
/// Verify a contribution
pub async fn verify_contribution(
&self,
circuit_type: CircuitType,
contribution_hash: &str,
) -> ZkResult<bool> {
#[derive(Deserialize)]
struct Response { valid: bool }
let resp: Response = self.post("/ceremony/verify", &serde_json::json!({
"circuit_type": circuit_type,
"contribution_hash": contribution_hash,
})).await?;
Ok(resp.valid)
}
/// List contributions
pub async fn list_contributions(&self, circuit_type: CircuitType) -> ZkResult<Vec<CeremonyContribution>> {
#[derive(Deserialize)]
struct Response { contributions: Vec<CeremonyContribution> }
let resp: Response = self.get(&format!("/ceremony/{:?}/contributions", circuit_type).to_lowercase()).await?;
Ok(resp.contributions)
}
// ========================================================================
// HTTP Methods
// ========================================================================
async fn get<T: DeserializeOwned>(&self, path: &str) -> ZkResult<T> {
self.request("GET", path, Option::<&()>::None).await
}
async fn post<T: DeserializeOwned, B: Serialize>(&self, path: &str, body: &B) -> ZkResult<T> {
self.request("POST", path, Some(body)).await
}
async fn request<T: DeserializeOwned, B: Serialize>(
&self,
method: &str,
path: &str,
body: Option<&B>,
) -> ZkResult<T> {
if self.is_closed() {
return Err(ZkError {
message: "Client has been closed".to_string(),
code: Some("CLIENT_CLOSED".to_string()),
status: None,
});
}
let url = format!("{}{}", self.config.endpoint, path);
let mut last_error = None;
for attempt in 0..=self.config.retries {
let mut req = match method {
"GET" => self.client.get(&url),
"POST" => self.client.post(&url),
"DELETE" => self.client.delete(&url),
_ => unreachable!(),
};
req = req
.header("Content-Type", "application/json")
.header("Authorization", format!("Bearer {}", self.config.api_key))
.header("X-SDK-Version", "rust/0.1.0")
.timeout(self.config.timeout);
if let Some(b) = body {
req = req.json(b);
}
match req.send().await {
Ok(resp) => {
let status = resp.status();
if status.is_success() {
return resp.json().await.map_err(|e| ZkError {
message: e.to_string(),
code: None,
status: None,
});
} else {
let error: serde_json::Value = resp.json().await.unwrap_or_default();
return Err(ZkError {
message: error["message"].as_str().unwrap_or(&format!("HTTP {}", status)).to_string(),
code: error["code"].as_str().map(String::from),
status: Some(status.as_u16()),
});
}
}
Err(e) => {
last_error = Some(e.to_string());
if attempt < self.config.retries {
tokio::time::sleep(std::time::Duration::from_millis(100 * 2u64.pow(attempt))).await;
}
}
}
}
Err(ZkError {
message: last_error.unwrap_or_else(|| "Request failed".to_string()),
code: Some("NETWORK_ERROR".to_string()),
status: None,
})
}
}

35
sdk/rust/src/zk/mod.rs Normal file
View file

@ -0,0 +1,35 @@
//! Synor ZK SDK for Rust
//!
//! Zero-Knowledge proof systems for ZK-Rollups and privacy.
//!
//! # Example
//!
//! ```rust,no_run
//! use synor_sdk::zk::{SynorZk, ZkConfig, ProofRequest, CircuitType, ProofSystem};
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let config = ZkConfig::new("your-api-key");
//! let zk = SynorZk::new(config);
//!
//! // Generate a proof
//! let proof = zk.generate_proof(ProofRequest {
//! circuit_type: CircuitType::Transfer,
//! public_inputs: vec![],
//! private_inputs: vec![],
//! system: Some(ProofSystem::Groth16),
//! }).await?;
//!
//! // Verify the proof
//! let result = zk.verify_proof(&proof).await?;
//! println!("Valid: {}", result.valid);
//!
//! Ok(())
//! }
//! ```
mod types;
mod client;
pub use types::*;
pub use client::*;

312
sdk/rust/src/zk/types.rs Normal file
View file

@ -0,0 +1,312 @@
//! ZK SDK Types
use serde::{Deserialize, Serialize};
use std::fmt;
/// Proof system backends
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ProofSystem {
/// Groth16 - smallest proofs (~192 bytes), fastest verification
Groth16,
/// PLONK - universal trusted setup, medium proofs (~512 bytes)
Plonk,
/// STARK - no trusted setup, largest proofs (~50KB)
Stark,
}
impl Default for ProofSystem {
fn default() -> Self {
Self::Groth16
}
}
/// Circuit types for different operations
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum CircuitType {
/// Single transfer between accounts
Transfer,
/// Batch of multiple transfers
Batch,
/// Deposit from L1 to L2
Deposit,
/// Withdrawal from L2 to L1
Withdraw,
}
/// Rollup state
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum RollupState {
Active,
Paused,
Finalizing,
Finalized,
}
/// Proof status
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ProofStatus {
Generating,
Completed,
Failed,
Verified,
}
/// Zero-knowledge proof
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Proof {
pub id: String,
pub system: ProofSystem,
pub circuit_type: CircuitType,
/// Base64 encoded proof data
pub data: String,
pub public_inputs: Vec<String>,
pub size: usize,
pub generation_time_ms: u64,
pub created_at: u64,
}
/// Verification key for a circuit
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VerificationKey {
pub circuit_id: String,
pub circuit_type: CircuitType,
pub system: ProofSystem,
/// Base64 encoded verification key
pub data: String,
pub size: usize,
}
/// Proving key for generating proofs
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProvingKey {
pub circuit_id: String,
pub circuit_type: CircuitType,
pub system: ProofSystem,
/// Base64 encoded proving key
pub data: String,
pub size: usize,
}
/// Circuit configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CircuitConfig {
#[serde(rename = "type")]
pub circuit_type: CircuitType,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_batch_size: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tree_depth: Option<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub verify_signatures: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub custom_constraints: Option<serde_json::Value>,
}
/// Account state in the rollup
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccountState {
pub address: String,
pub balance: String,
pub nonce: u64,
pub pubkey_hash: String,
}
/// Transfer operation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Transfer {
pub from: String,
pub to: String,
pub amount: String,
pub fee: String,
pub nonce: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
}
/// Deposit operation (L1 -> L2)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Deposit {
pub l1_tx_hash: String,
pub recipient: String,
pub amount: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub token: Option<String>,
}
/// Withdrawal operation (L2 -> L1)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Withdrawal {
pub sender: String,
pub recipient: String,
pub amount: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub token: Option<String>,
pub nonce: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
}
/// Rollup batch
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Batch {
pub batch_number: u64,
pub prev_state_root: String,
pub new_state_root: String,
pub transfers: Vec<Transfer>,
pub deposits: Vec<Deposit>,
pub withdrawals: Vec<Withdrawal>,
#[serde(skip_serializing_if = "Option::is_none")]
pub proof: Option<Proof>,
pub timestamp: u64,
}
/// Rollup statistics
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RollupStats {
pub current_batch: u64,
pub total_transactions: u64,
pub total_proofs: u64,
pub avg_proof_time_ms: u64,
pub state_root: String,
pub account_count: u64,
pub tvl: String,
}
/// Proof generation request
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProofRequest {
pub circuit_type: CircuitType,
pub public_inputs: Vec<String>,
pub private_inputs: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub system: Option<ProofSystem>,
}
/// Proof verification result
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VerificationResult {
pub valid: bool,
pub verification_time_ms: u64,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
/// Merkle proof for state inclusion
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MerkleProof {
pub leaf: String,
pub path: Vec<String>,
pub indices: Vec<u8>,
pub root: String,
}
/// Trusted setup ceremony contribution
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CeremonyContribution {
pub contributor_id: String,
pub hash: String,
pub timestamp: u64,
pub verified: bool,
}
/// Trusted setup ceremony
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TrustedSetup {
pub id: String,
pub circuit_type: CircuitType,
pub system: ProofSystem,
pub contribution_count: usize,
pub latest_hash: String,
pub complete: bool,
pub contributions: Vec<CeremonyContribution>,
}
/// ZK SDK configuration
#[derive(Debug, Clone)]
pub struct ZkConfig {
pub api_key: String,
pub endpoint: String,
pub ws_endpoint: String,
pub timeout: std::time::Duration,
pub retries: u32,
pub default_proof_system: ProofSystem,
pub debug: bool,
}
impl ZkConfig {
pub fn new(api_key: impl Into<String>) -> Self {
Self {
api_key: api_key.into(),
endpoint: "https://zk.synor.io/v1".to_string(),
ws_endpoint: "wss://zk.synor.io/v1/ws".to_string(),
timeout: std::time::Duration::from_secs(60),
retries: 3,
default_proof_system: ProofSystem::Groth16,
debug: false,
}
}
}
/// ZK SDK error
#[derive(Debug)]
pub struct ZkError {
pub message: String,
pub code: Option<String>,
pub status: Option<u16>,
}
impl fmt::Display for ZkError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.message)
}
}
impl std::error::Error for ZkError {}
pub type ZkResult<T> = Result<T, ZkError>;
/// Proof system characteristics
pub struct ProofSystemInfo {
pub name: &'static str,
pub proof_size: usize,
pub verification_time_ms: u64,
pub trusted_setup: bool,
pub universal: bool,
}
impl ProofSystem {
pub fn info(&self) -> ProofSystemInfo {
match self {
ProofSystem::Groth16 => ProofSystemInfo {
name: "Groth16",
proof_size: 192,
verification_time_ms: 10,
trusted_setup: true,
universal: false,
},
ProofSystem::Plonk => ProofSystemInfo {
name: "PLONK",
proof_size: 512,
verification_time_ms: 15,
trusted_setup: true,
universal: true,
},
ProofSystem::Stark => ProofSystemInfo {
name: "STARK",
proof_size: 50000,
verification_time_ms: 30,
trusted_setup: false,
universal: true,
},
}
}
}
/// Constants
pub const MAX_BATCH_SIZE: usize = 1000;
pub const STATE_TREE_DEPTH: usize = 32;
pub const PROOF_EXPIRY_BLOCKS: u64 = 100;

View file

@ -0,0 +1,337 @@
import Foundation
/// Synor ZK SDK for Swift
///
/// Zero-Knowledge proof systems for ZK-Rollups and privacy.
public class SynorZk {
private let config: ZkConfig
private let session: URLSession
private var _closed = false
public lazy var proofs = ProofsClient(zk: self)
public lazy var circuits = CircuitsClient(zk: self)
public lazy var rollup = RollupClient(zk: self)
public lazy var state = StateClient(zk: self)
public lazy var ceremony = CeremonyClient(zk: self)
public init(config: ZkConfig) {
self.config = config
let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = TimeInterval(config.timeout)
self.session = URLSession(configuration: sessionConfig)
}
public var defaultProofSystem: ProofSystem { config.defaultProofSystem }
public func healthCheck() async -> Bool {
do {
let result = try await get("/health")
return result["status"] as? String == "healthy"
} catch {
return false
}
}
public func getInfo() async throws -> [String: Any] {
try await get("/info")
}
public func close() {
_closed = true
session.invalidateAndCancel()
}
public var isClosed: Bool { _closed }
// Internal HTTP methods
func get(_ path: String) async throws -> [String: Any] {
try checkClosed()
var request = URLRequest(url: URL(string: "\(config.endpoint)\(path)")!)
request.httpMethod = "GET"
addHeaders(&request)
return try await performRequest(request)
}
func post(_ path: String, body: [String: Any]) async throws -> [String: Any] {
try checkClosed()
var request = URLRequest(url: URL(string: "\(config.endpoint)\(path)")!)
request.httpMethod = "POST"
request.httpBody = try JSONSerialization.data(withJSONObject: body)
addHeaders(&request)
return try await performRequest(request)
}
private func addHeaders(_ request: inout URLRequest) {
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(config.apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("swift/0.1.0", forHTTPHeaderField: "X-SDK-Version")
}
private func performRequest(_ request: URLRequest) async throws -> [String: Any] {
let (data, response) = try await session.data(for: request)
guard let httpResponse = response as? HTTPURLResponse else {
throw ZkError("Invalid response")
}
if httpResponse.statusCode >= 400 {
let error = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
throw ZkError(
error?["message"] as? String ?? "HTTP \(httpResponse.statusCode)",
code: error?["code"] as? String,
status: httpResponse.statusCode
)
}
guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] else {
throw ZkError("Invalid JSON response")
}
return json
}
private func checkClosed() throws {
if _closed {
throw ZkError("Client has been closed", code: "CLIENT_CLOSED")
}
}
/// Proofs sub-client
public class ProofsClient {
private let zk: SynorZk
init(zk: SynorZk) {
self.zk = zk
}
public func generate(_ request: ProofRequest) async throws -> Proof {
var body: [String: Any] = [
"circuit_type": request.circuitType.rawValue,
"public_inputs": request.publicInputs,
"private_inputs": request.privateInputs,
"system": (request.system ?? zk.defaultProofSystem).rawValue
]
let result = try await zk.post("/proofs/generate", body: body)
return try Proof.fromJson(result)
}
public func verify(_ proof: Proof) async throws -> VerificationResult {
let body: [String: Any] = [
"proof_id": proof.id,
"data": proof.data,
"public_inputs": proof.publicInputs,
"system": proof.system.rawValue,
"circuit_type": proof.circuitType.rawValue
]
let result = try await zk.post("/proofs/verify", body: body)
return VerificationResult.fromJson(result)
}
public func get(proofId: String) async throws -> Proof {
let result = try await zk.get("/proofs/\(proofId)")
return try Proof.fromJson(result)
}
public func list(limit: Int? = nil, offset: Int? = nil) async throws -> [Proof] {
var path = "/proofs"
var params: [String] = []
if let limit = limit { params.append("limit=\(limit)") }
if let offset = offset { params.append("offset=\(offset)") }
if !params.isEmpty { path += "?\(params.joined(separator: "&"))" }
let result = try await zk.get(path)
guard let proofs = result["proofs"] as? [[String: Any]] else { return [] }
return try proofs.map { try Proof.fromJson($0) }
}
public func serialize(_ proof: Proof) async throws -> Data {
let result = try await zk.post("/proofs/serialize", body: ["proof_id": proof.id])
guard let dataStr = result["data"] as? String,
let data = Data(base64Encoded: dataStr) else {
throw ZkError("Invalid response")
}
return data
}
public func deserialize(_ data: Data, system: ProofSystem) async throws -> Proof {
let result = try await zk.post("/proofs/deserialize", body: [
"data": data.base64EncodedString(),
"system": system.rawValue
])
return try Proof.fromJson(result)
}
}
/// Circuits sub-client
public class CircuitsClient {
private let zk: SynorZk
init(zk: SynorZk) {
self.zk = zk
}
public func getVerificationKey(circuitType: CircuitType, system: ProofSystem? = nil) async throws -> VerificationKey {
let sys = system ?? zk.defaultProofSystem
let result = try await zk.get("/circuits/\(circuitType.rawValue)/vk?system=\(sys.rawValue)")
return try VerificationKey.fromJson(result)
}
public func getProvingKey(circuitType: CircuitType, system: ProofSystem? = nil) async throws -> ProvingKey {
let sys = system ?? zk.defaultProofSystem
let result = try await zk.get("/circuits/\(circuitType.rawValue)/pk?system=\(sys.rawValue)")
return try ProvingKey.fromJson(result)
}
public func list() async throws -> [CircuitConfig] {
let result = try await zk.get("/circuits")
guard let circuits = result["circuits"] as? [[String: Any]] else { return [] }
return circuits.compactMap { CircuitConfig.fromJson($0) }
}
public func getConfig(circuitType: CircuitType) async throws -> CircuitConfig {
let result = try await zk.get("/circuits/\(circuitType.rawValue)/config")
guard let config = CircuitConfig.fromJson(result) else {
throw ZkError("Invalid response")
}
return config
}
public func compile(_ config: CircuitConfig) async throws -> String {
let result = try await zk.post("/circuits/compile", body: config.toJson())
guard let circuitId = result["circuit_id"] as? String else {
throw ZkError("Invalid response")
}
return circuitId
}
}
/// Rollup sub-client
public class RollupClient {
private let zk: SynorZk
init(zk: SynorZk) {
self.zk = zk
}
public func getStats() async throws -> RollupStats {
let result = try await zk.get("/rollup/stats")
return RollupStats.fromJson(result)
}
public func getCurrentBatch() async throws -> Batch {
let result = try await zk.get("/rollup/batch/current")
return try Batch.fromJson(result)
}
public func getBatch(_ batchNumber: Int) async throws -> Batch {
let result = try await zk.get("/rollup/batch/\(batchNumber)")
return try Batch.fromJson(result)
}
public func submitTransfer(_ transfer: Transfer) async throws -> String {
let result = try await zk.post("/rollup/transfer", body: transfer.toJson())
guard let txId = result["tx_id"] as? String else {
throw ZkError("Invalid response")
}
return txId
}
public func submitDeposit(_ deposit: Deposit) async throws -> String {
let result = try await zk.post("/rollup/deposit", body: deposit.toJson())
guard let txId = result["tx_id"] as? String else {
throw ZkError("Invalid response")
}
return txId
}
public func submitWithdrawal(_ withdrawal: Withdrawal) async throws -> String {
let result = try await zk.post("/rollup/withdraw", body: withdrawal.toJson())
guard let txId = result["tx_id"] as? String else {
throw ZkError("Invalid response")
}
return txId
}
public func finalizeBatch() async throws -> Batch {
let result = try await zk.post("/rollup/batch/finalize", body: [:])
return try Batch.fromJson(result)
}
public func getPendingTransactions() async throws -> [Transfer] {
let result = try await zk.get("/rollup/pending")
guard let transactions = result["transactions"] as? [[String: Any]] else { return [] }
return transactions.compactMap { Transfer.fromJson($0) }
}
}
/// State sub-client
public class StateClient {
private let zk: SynorZk
init(zk: SynorZk) {
self.zk = zk
}
public func getRoot() async throws -> String {
let result = try await zk.get("/state/root")
guard let root = result["root"] as? String else {
throw ZkError("Invalid response")
}
return root
}
public func getAccount(address: String) async throws -> AccountState {
let result = try await zk.get("/state/account/\(address)")
return AccountState.fromJson(result)
}
public func getMerkleProof(address: String) async throws -> MerkleProof {
let result = try await zk.get("/state/proof/\(address)")
return MerkleProof.fromJson(result)
}
public func verifyMerkleProof(_ proof: MerkleProof) async throws -> Bool {
let result = try await zk.post("/state/proof/verify", body: proof.toJson())
return result["valid"] as? Bool ?? false
}
public func getStateAtBatch(_ batchNumber: Int) async throws -> [String: Any] {
try await zk.get("/state/batch/\(batchNumber)")
}
}
/// Ceremony sub-client
public class CeremonyClient {
private let zk: SynorZk
init(zk: SynorZk) {
self.zk = zk
}
public func getStatus(circuitType: CircuitType, system: ProofSystem? = nil) async throws -> TrustedSetup {
let sys = system ?? zk.defaultProofSystem
let result = try await zk.get("/ceremony/\(circuitType.rawValue)?system=\(sys.rawValue)")
return TrustedSetup.fromJson(result)
}
public func contribute(circuitType: CircuitType, entropy: Data, system: ProofSystem? = nil) async throws -> CeremonyContribution {
let sys = system ?? zk.defaultProofSystem
let result = try await zk.post("/ceremony/contribute", body: [
"circuit_type": circuitType.rawValue,
"entropy": entropy.base64EncodedString(),
"system": sys.rawValue
])
return CeremonyContribution.fromJson(result)
}
public func verifyContribution(circuitType: CircuitType, contributionHash: String) async throws -> Bool {
let result = try await zk.post("/ceremony/verify", body: [
"circuit_type": circuitType.rawValue,
"contribution_hash": contributionHash
])
return result["valid"] as? Bool ?? false
}
public func listContributions(circuitType: CircuitType) async throws -> [CeremonyContribution] {
let result = try await zk.get("/ceremony/\(circuitType.rawValue)/contributions")
guard let contributions = result["contributions"] as? [[String: Any]] else { return [] }
return contributions.map { CeremonyContribution.fromJson($0) }
}
}
}

View file

@ -0,0 +1,496 @@
import Foundation
/// Synor ZK SDK Types for Swift
///
/// Zero-Knowledge proof systems for ZK-Rollups and privacy.
/// Proof system backends
public enum ProofSystem: String, Codable {
case groth16
case plonk
case stark
}
/// Circuit types for different operations
public enum CircuitType: String, Codable {
case transfer
case batch
case deposit
case withdraw
}
/// Rollup state
public enum RollupState: String, Codable {
case active
case paused
case finalizing
case finalized
}
/// Proof status
public enum ProofStatus: String, Codable {
case generating
case completed
case failed
case verified
}
/// Zero-knowledge proof
public struct Proof {
public let id: String
public let system: ProofSystem
public let circuitType: CircuitType
public let data: String
public let publicInputs: [String]
public let size: Int
public let generationTimeMs: Int
public let createdAt: Int
public init(id: String, system: ProofSystem, circuitType: CircuitType, data: String,
publicInputs: [String], size: Int, generationTimeMs: Int, createdAt: Int) {
self.id = id
self.system = system
self.circuitType = circuitType
self.data = data
self.publicInputs = publicInputs
self.size = size
self.generationTimeMs = generationTimeMs
self.createdAt = createdAt
}
public static func fromJson(_ json: [String: Any]) throws -> Proof {
guard let id = json["id"] as? String,
let systemStr = json["system"] as? String,
let system = ProofSystem(rawValue: systemStr),
let circuitTypeStr = json["circuit_type"] as? String,
let circuitType = CircuitType(rawValue: circuitTypeStr),
let data = json["data"] as? String else {
throw ZkError("Invalid proof JSON")
}
return Proof(
id: id,
system: system,
circuitType: circuitType,
data: data,
publicInputs: json["public_inputs"] as? [String] ?? [],
size: json["size"] as? Int ?? 0,
generationTimeMs: json["generation_time_ms"] as? Int ?? 0,
createdAt: json["created_at"] as? Int ?? 0
)
}
}
/// Verification key for a circuit
public struct VerificationKey {
public let circuitId: String
public let circuitType: CircuitType
public let system: ProofSystem
public let data: String
public let size: Int
public static func fromJson(_ json: [String: Any]) throws -> VerificationKey {
guard let circuitId = json["circuit_id"] as? String,
let circuitTypeStr = json["circuit_type"] as? String,
let circuitType = CircuitType(rawValue: circuitTypeStr),
let systemStr = json["system"] as? String,
let system = ProofSystem(rawValue: systemStr),
let data = json["data"] as? String else {
throw ZkError("Invalid verification key JSON")
}
return VerificationKey(
circuitId: circuitId,
circuitType: circuitType,
system: system,
data: data,
size: json["size"] as? Int ?? 0
)
}
}
/// Proving key for generating proofs
public struct ProvingKey {
public let circuitId: String
public let circuitType: CircuitType
public let system: ProofSystem
public let data: String
public let size: Int
public static func fromJson(_ json: [String: Any]) throws -> ProvingKey {
guard let circuitId = json["circuit_id"] as? String,
let circuitTypeStr = json["circuit_type"] as? String,
let circuitType = CircuitType(rawValue: circuitTypeStr),
let systemStr = json["system"] as? String,
let system = ProofSystem(rawValue: systemStr),
let data = json["data"] as? String else {
throw ZkError("Invalid proving key JSON")
}
return ProvingKey(
circuitId: circuitId,
circuitType: circuitType,
system: system,
data: data,
size: json["size"] as? Int ?? 0
)
}
}
/// Circuit configuration
public struct CircuitConfig {
public let type: CircuitType
public let maxBatchSize: Int?
public let treeDepth: Int?
public let verifySignatures: Bool?
public let customConstraints: [String: Any]?
public static func fromJson(_ json: [String: Any]) -> CircuitConfig? {
guard let typeStr = json["type"] as? String,
let type = CircuitType(rawValue: typeStr) else { return nil }
return CircuitConfig(
type: type,
maxBatchSize: json["max_batch_size"] as? Int,
treeDepth: json["tree_depth"] as? Int,
verifySignatures: json["verify_signatures"] as? Bool,
customConstraints: json["custom_constraints"] as? [String: Any]
)
}
public func toJson() -> [String: Any] {
var result: [String: Any] = ["type": type.rawValue]
if let v = maxBatchSize { result["max_batch_size"] = v }
if let v = treeDepth { result["tree_depth"] = v }
if let v = verifySignatures { result["verify_signatures"] = v }
if let v = customConstraints { result["custom_constraints"] = v }
return result
}
}
/// Account state in the rollup
public struct AccountState {
public let address: String
public let balance: String
public let nonce: Int
public let pubkeyHash: String
public static func fromJson(_ json: [String: Any]) -> AccountState {
AccountState(
address: json["address"] as? String ?? "",
balance: json["balance"] as? String ?? "0",
nonce: json["nonce"] as? Int ?? 0,
pubkeyHash: json["pubkey_hash"] as? String ?? ""
)
}
}
/// Transfer operation
public struct Transfer {
public let from: String
public let to: String
public let amount: String
public let fee: String
public let nonce: Int
public let signature: String?
public init(from: String, to: String, amount: String, fee: String, nonce: Int, signature: String? = nil) {
self.from = from
self.to = to
self.amount = amount
self.fee = fee
self.nonce = nonce
self.signature = signature
}
public static func fromJson(_ json: [String: Any]) -> Transfer? {
guard let from = json["from"] as? String,
let to = json["to"] as? String,
let amount = json["amount"] as? String,
let fee = json["fee"] as? String else { return nil }
return Transfer(
from: from,
to: to,
amount: amount,
fee: fee,
nonce: json["nonce"] as? Int ?? 0,
signature: json["signature"] as? String
)
}
public func toJson() -> [String: Any] {
var result: [String: Any] = [
"from": from,
"to": to,
"amount": amount,
"fee": fee,
"nonce": nonce
]
if let sig = signature { result["signature"] = sig }
return result
}
}
/// Deposit operation (L1 -> L2)
public struct Deposit {
public let l1TxHash: String
public let recipient: String
public let amount: String
public let token: String?
public init(l1TxHash: String, recipient: String, amount: String, token: String? = nil) {
self.l1TxHash = l1TxHash
self.recipient = recipient
self.amount = amount
self.token = token
}
public func toJson() -> [String: Any] {
var result: [String: Any] = [
"l1_tx_hash": l1TxHash,
"recipient": recipient,
"amount": amount
]
if let t = token { result["token"] = t }
return result
}
}
/// Withdrawal operation (L2 -> L1)
public struct Withdrawal {
public let sender: String
public let recipient: String
public let amount: String
public let token: String?
public let nonce: Int
public let signature: String?
public init(sender: String, recipient: String, amount: String, token: String? = nil, nonce: Int, signature: String? = nil) {
self.sender = sender
self.recipient = recipient
self.amount = amount
self.token = token
self.nonce = nonce
self.signature = signature
}
public func toJson() -> [String: Any] {
var result: [String: Any] = [
"sender": sender,
"recipient": recipient,
"amount": amount,
"nonce": nonce
]
if let t = token { result["token"] = t }
if let sig = signature { result["signature"] = sig }
return result
}
}
/// Rollup batch
public struct Batch {
public let batchNumber: Int
public let prevStateRoot: String
public let newStateRoot: String
public let transfers: [Transfer]
public let deposits: [Deposit]
public let withdrawals: [Withdrawal]
public let proof: Proof?
public let timestamp: Int
public static func fromJson(_ json: [String: Any]) throws -> Batch {
let transfers = (json["transfers"] as? [[String: Any]] ?? []).compactMap { Transfer.fromJson($0) }
return Batch(
batchNumber: json["batch_number"] as? Int ?? 0,
prevStateRoot: json["prev_state_root"] as? String ?? "",
newStateRoot: json["new_state_root"] as? String ?? "",
transfers: transfers,
deposits: [],
withdrawals: [],
proof: (json["proof"] as? [String: Any]).flatMap { try? Proof.fromJson($0) },
timestamp: json["timestamp"] as? Int ?? 0
)
}
}
/// Rollup statistics
public struct RollupStats {
public let currentBatch: Int
public let totalTransactions: Int
public let totalProofs: Int
public let avgProofTimeMs: Int
public let stateRoot: String
public let accountCount: Int
public let tvl: String
public static func fromJson(_ json: [String: Any]) -> RollupStats {
RollupStats(
currentBatch: json["current_batch"] as? Int ?? 0,
totalTransactions: json["total_transactions"] as? Int ?? 0,
totalProofs: json["total_proofs"] as? Int ?? 0,
avgProofTimeMs: json["avg_proof_time_ms"] as? Int ?? 0,
stateRoot: json["state_root"] as? String ?? "",
accountCount: json["account_count"] as? Int ?? 0,
tvl: json["tvl"] as? String ?? "0"
)
}
}
/// Proof generation request
public struct ProofRequest {
public let circuitType: CircuitType
public let publicInputs: [String]
public let privateInputs: [String]
public let system: ProofSystem?
public init(circuitType: CircuitType, publicInputs: [String], privateInputs: [String], system: ProofSystem? = nil) {
self.circuitType = circuitType
self.publicInputs = publicInputs
self.privateInputs = privateInputs
self.system = system
}
}
/// Proof verification result
public struct VerificationResult {
public let valid: Bool
public let verificationTimeMs: Int
public let error: String?
public static func fromJson(_ json: [String: Any]) -> VerificationResult {
VerificationResult(
valid: json["valid"] as? Bool ?? false,
verificationTimeMs: json["verification_time_ms"] as? Int ?? 0,
error: json["error"] as? String
)
}
}
/// Merkle proof for state inclusion
public struct MerkleProof {
public let leaf: String
public let path: [String]
public let indices: [Int]
public let root: String
public static func fromJson(_ json: [String: Any]) -> MerkleProof {
MerkleProof(
leaf: json["leaf"] as? String ?? "",
path: json["path"] as? [String] ?? [],
indices: json["indices"] as? [Int] ?? [],
root: json["root"] as? String ?? ""
)
}
public func toJson() -> [String: Any] {
["leaf": leaf, "path": path, "indices": indices, "root": root]
}
}
/// Trusted setup ceremony contribution
public struct CeremonyContribution {
public let contributorId: String
public let hash: String
public let timestamp: Int
public let verified: Bool
public static func fromJson(_ json: [String: Any]) -> CeremonyContribution {
CeremonyContribution(
contributorId: json["contributor_id"] as? String ?? "",
hash: json["hash"] as? String ?? "",
timestamp: json["timestamp"] as? Int ?? 0,
verified: json["verified"] as? Bool ?? false
)
}
}
/// Trusted setup ceremony
public struct TrustedSetup {
public let id: String
public let circuitType: CircuitType
public let system: ProofSystem
public let contributionCount: Int
public let latestHash: String
public let complete: Bool
public let contributions: [CeremonyContribution]
public static func fromJson(_ json: [String: Any]) -> TrustedSetup {
let contributions = (json["contributions"] as? [[String: Any]] ?? []).map { CeremonyContribution.fromJson($0) }
return TrustedSetup(
id: json["id"] as? String ?? "",
circuitType: CircuitType(rawValue: json["circuit_type"] as? String ?? "transfer") ?? .transfer,
system: ProofSystem(rawValue: json["system"] as? String ?? "groth16") ?? .groth16,
contributionCount: json["contribution_count"] as? Int ?? 0,
latestHash: json["latest_hash"] as? String ?? "",
complete: json["complete"] as? Bool ?? false,
contributions: contributions
)
}
}
/// ZK SDK configuration
public struct ZkConfig {
public let apiKey: String
public let endpoint: String
public let wsEndpoint: String
public let timeout: Int
public let retries: Int
public let defaultProofSystem: ProofSystem
public let debug: Bool
public init(
apiKey: String,
endpoint: String = "https://zk.synor.io/v1",
wsEndpoint: String = "wss://zk.synor.io/v1/ws",
timeout: Int = 60,
retries: Int = 3,
defaultProofSystem: ProofSystem = .groth16,
debug: Bool = false
) {
self.apiKey = apiKey
self.endpoint = endpoint
self.wsEndpoint = wsEndpoint
self.timeout = timeout
self.retries = retries
self.defaultProofSystem = defaultProofSystem
self.debug = debug
}
}
/// ZK SDK error
public struct ZkError: Error, CustomStringConvertible {
public let message: String
public let code: String?
public let status: Int?
public init(_ message: String, code: String? = nil, status: Int? = nil) {
self.message = message
self.code = code
self.status = status
}
public var description: String {
"ZkError: \(message)\(code.map { " (\($0))" } ?? "")"
}
}
/// Proof system characteristics
public struct ProofSystemInfo {
public let name: String
public let proofSize: Int
public let verificationTimeMs: Int
public let trustedSetup: Bool
public let universal: Bool
}
public func getProofSystemInfo(_ system: ProofSystem) -> ProofSystemInfo {
switch system {
case .groth16:
return ProofSystemInfo(name: "Groth16", proofSize: 192, verificationTimeMs: 10, trustedSetup: true, universal: false)
case .plonk:
return ProofSystemInfo(name: "PLONK", proofSize: 512, verificationTimeMs: 15, trustedSetup: true, universal: true)
case .stark:
return ProofSystemInfo(name: "STARK", proofSize: 50000, verificationTimeMs: 30, trustedSetup: false, universal: true)
}
}
// Constants
public let MAX_BATCH_SIZE = 1000
public let STATE_TREE_DEPTH = 32
public let PROOF_EXPIRY_BLOCKS = 100