Public Bindings API

This header file defines the core public API for Colibri's stateless Ethereum proof generation and verification system. It serves as the primary interface for language bindings (TypeScript, Python, Kotlin, Swift, etc.) and native C applications.

Overview

Colibri implements a stateless light client for Ethereum that can generate and verify cryptographic proofs for JSON-RPC method calls without maintaining blockchain state. The API provides:

  • Proof Generation: Create cryptographic proofs for Ethereum RPC calls

  • Proof Verification: Verify proofs and extract verified results

  • Asynchronous Execution: Non-blocking request handling with external data fetching

  • Multi-Chain Support: Works with Ethereum mainnet, testnets, and L2s

  • Language Bindings: Clean C API designed for easy FFI integration

Architecture

Stateless Design

Unlike traditional Ethereum nodes that maintain the full blockchain state, Colibri operates statelessly by:

  1. Requesting only necessary data from external sources (RPC nodes, beacon chain APIs)

  2. Building cryptographic proofs from Merkle proofs and beacon chain sync committee signatures

  3. Verifying against trusted checkpoints without storing any state

This design allows Colibri to run efficiently in constrained environments (browsers, mobile devices, IoT) while providing the same security guarantees as a full node.

Asynchronous Execution Model

The API implements an asynchronous state machine where the C library cannot perform network I/O directly. Instead, the host system (JavaScript runtime, Python process, JVM, etc.) is responsible for executing HTTP requests.

Execution Flow

This design allows the host system to use native async technologies (Promises in JavaScript, async/await in Python, coroutines in Kotlin) while keeping the C core synchronous and portable.

Host System Responsibilities

The host system (language binding or application using this API) has several critical responsibilities:

1. Configuration and Node Management

The host system must maintain lists of data source endpoints for each chain:

  • Ethereum RPC nodes (type: "eth_rpc"): For execution layer data

  • Beacon API nodes (type: "beacon_api"): For consensus layer data

  • Checkpointz servers (type: "checkpointz"): For trusted sync committee checkpoints

  • Prover servers (type: "prover"): Optional centralized proof generation

Example Configuration:

2. Request Execution with Retry Logic

When c4_prover_execute_json_status() or c4_verify_execute_json_status() returns "status": "pending", the host system must execute all pending requests. For each request in the "requests" array:

Step 1: Select Node

Choose a node from the appropriate list based on request.type:

  • "eth_rpc" → use Ethereum RPC nodes

  • "beacon_api" → use Beacon API nodes

  • "checkpointz" → use Checkpointz servers

Step 2: Apply Filters

  • Skip excluded nodes: If (request.exclude_mask & (1 << node_index)) != 0, skip this node

  • Prefer client types: If request.preferred_client_type != 0, prefer matching beacon clients

Step 3: Build HTTP Request

  • Method: Use request.method (usually "GET" or "POST")

  • URL: Construct as server_base_url + "/" + request.url

  • Headers:

    • Content-Type: "application/json" if request.payload is present

    • Accept: "application/octet-stream" if request.encoding == "ssz", else "application/json"

  • Body: Use request.payload as JSON for POST requests

Step 4: Retry Logic

If a request fails:

  1. Try the next node in the list (respecting exclude_mask)

  2. If all nodes fail, call c4_req_set_error(request.req_ptr, error_message, 0)

If a request succeeds:

  1. Call c4_req_set_response(request.req_ptr, response_data, node_index)

Step 5: Parallel Execution

For optimal performance, execute all pending requests in parallel using the host language's async capabilities (Promise.all, asyncio.gather, etc.).

3. Memory Management

  • Allocated strings: All strings returned from C functions (JSON status strings) must be freed by the host

  • Context cleanup: Always call c4_free_prover_ctx() or c4_verify_free_ctx() when done

  • Request data: Data passed to c4_req_set_response() is copied by the C library

  • Error strings: Error strings passed to c4_req_set_error() are copied by the C library

4. Error Handling

The host system should handle:

  • Network errors: Retry with different nodes

  • HTTP errors: Check status codes, parse JSON-RPC error responses

  • Timeouts: Implement reasonable timeouts (30s recommended)

  • Invalid responses: Validate response format before calling c4_req_set_response()

Data Request Structure

When the status is "pending", the "requests" array contains objects with:

Field
Type
Description

req_ptr

number

Opaque pointer to pass to c4_req_set_response() or c4_req_set_error()

chain_id

number

Chain ID for this request

type

string

Request type: "eth_rpc", "beacon_api", "checkpointz", "rest_api"

encoding

string

Response encoding: "json" or "ssz"

method

string

HTTP method: "get", "post", "put", "delete"

url

string

URL path to append to server base URL

payload

object?

Optional JSON payload for POST/PUT requests

exclude_mask

number

Bitmask of nodes to exclude (bit N = exclude node N)

preferred_client_type

number

Preferred beacon client type (0 = any)

Method Support

Not all Ethereum RPC methods can be proven. Use c4_get_method_support() to check:

Return Value
Enum
Meaning

1

PROOFABLE

Method can be proven (use proof flow)

2

UNPROOFABLE

Method exists but cannot be proven (call RPC directly)

3

NOT_SUPPORTED

Method not supported by Colibri

4

LOCAL

Method can be computed locally (no network needed)

Proofable methods include:

  • eth_getBalance, eth_getCode, eth_getStorageAt

  • eth_getTransactionByHash, eth_getTransactionReceipt

  • eth_getBlockByHash, eth_getBlockByNumber

  • eth_getLogs, eth_call, eth_getProof

Local methods include:

  • eth_chainId, net_version

Complete Usage Examples

These examples show how to call the C functions directly from different host languages. This is useful for developers creating new language bindings or integrating Colibri into existing applications.

Note: These examples are simplified for clarity. In production code, you should:

  • Use proper JSON parsing libraries (not string matching)

  • Implement robust error handling and retry logic

  • Handle memory management carefully (especially in C/manual memory languages)

  • Execute pending requests in parallel for optimal performance

  • Implement proper node selection and exclusion mask handling

Best Practices

Performance Optimization

  1. Parallel Request Execution: Always execute pending requests in parallel

  2. Connection Pooling: Reuse HTTP connections across requests

  3. Response Caching: Cache responses based on request URL and payload (respect TTL)

  4. Node Selection: Track node reliability and prefer faster/more reliable nodes

Error Handling

  1. Retry with Backoff: Implement exponential backoff for transient errors

  2. Fallback Nodes: Always configure multiple nodes per data source type

  3. Timeout Handling: Use reasonable timeouts (30s recommended)

  4. Graceful Degradation: Fall back to direct RPC for UNPROOFABLE methods

Security Considerations

  1. Trusted Checkpoint: Always configure a trusted checkpoint for initial sync

  2. Node Diversity: Use nodes from different operators to prevent eclipse attacks

  3. Response Validation: Validate response formats before passing to C library

  4. Memory Safety: Always free returned strings and contexts

c4_create_prover_ctx

bindings/colibri.h

Creates a new prover context for generating a proof.

This function initializes the proof generation process for a specific Ethereum RPC method. The returned context must be used with c4_prover_execute_json_status() to drive the asynchronous proof generation process.

Memory Management: The caller is responsible for freeing the returned context using c4_free_prover_ctx() when done.

Example:

Parameters

  • method : The Ethereum RPC method to prove (e.g., "eth_getBalance", "eth_getBlockByHash")

  • params : The method parameters as a JSON array string (e.g., '["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "latest"]')

  • chain_id : The blockchain chain ID (1 = Ethereum Mainnet, 11155111 = Sepolia, etc.)

  • flags : Flags to customize proof generation:

Returns

A new prover context pointer, or NULL if creation failed

c4_prover_execute_json_status

bindings/colibri.h

Executes one step of the proof generation state machine.

This function drives the asynchronous proof generation process. Call it repeatedly in a loop until it returns a status of "success" or "error". When it returns "pending", the host system must handle the pending data requests before calling this function again.

Memory Management: The returned JSON string must be freed by the caller using free().

Return Value Format:

The function returns a JSON string with one of three possible statuses:

Success (proof generation complete):

  • result: Hexadecimal string pointer to proof data (use with c4_prover_get_proof())

  • result_len: Length of the proof in bytes

Error (proof generation failed):

  • error: Human-readable error message

Pending (waiting for external data):

  • requests: Array of data requests that must be fulfilled (see "Data Request Structure" in API docs)

Example Usage:

Parameters

  • ctx : The prover context created by c4_create_prover_ctx()

Returns

A JSON string describing the current status (see format below)

c4_prover_get_proof

bindings/colibri.h

Retrieves the generated proof from a completed prover context.

This function should only be called after c4_prover_execute_json_status() returns a status of "success". The proof data is owned by the context and remains valid until c4_free_prover_ctx() is called.

Memory Management: The returned bytes_t.data pointer is owned by the context. Do NOT call free() on it. Copy the data if you need to retain it after freeing the context.

Example:

Parameters

  • ctx : The prover context (must be in "success" state)

Returns

A bytes_t structure containing the proof data

c4_free_prover_ctx

bindings/colibri.h

Frees all resources associated with a prover context.

This function must be called to clean up a prover context created by c4_create_prover_ctx(). After calling this function, the context pointer is invalid and must not be used.

Memory Management: This frees the context and all associated internal memory, including the proof data. If you need the proof data after freeing the context, copy it first using c4_prover_get_proof().

Example:

Parameters

  • ctx : The prover context to free (may be NULL, in which case this is a no-op)

c4_req_set_response

bindings/colibri.h

Sets the successful response data for a pending data request.

When c4_prover_execute_json_status() or c4_verify_execute_json_status() returns "status": "pending", the host system must fetch the data for each request and call this function to provide the response. After all pending requests are fulfilled, call the execute function again to continue processing.

Memory Management: The data is copied by this function. The caller retains ownership of the input data and is responsible for freeing it if needed.

Example:

Parameters

  • req_ptr : Opaque request pointer from the "req_ptr" field in the JSON status

  • data : The response data as bytes_t (will be copied)

  • node_index : Index of the node that provided this response (0-15, used for exclude_mask)

c4_req_set_error

bindings/colibri.h

Sets an error for a pending data request.

When a data request cannot be fulfilled (network error, all nodes failed, invalid response), call this function to report the error. The proof generation/verification will typically fail with this error message, or may retry with different parameters.

Memory Management: The error string is copied by this function. The caller retains ownership and is responsible for freeing it if needed.

Example:

Parameters

  • req_ptr : Opaque request pointer from the "req_ptr" field in the JSON status

  • error : Error message string (will be copied)

  • node_index : Index of the node that failed (0-15), or 0 if all nodes failed

c4_verify_create_ctx

bindings/colibri.h

Creates a verification context for verifying a proof.

This function initializes the proof verification process. The returned context must be used with c4_verify_execute_json_status() to drive the asynchronous verification process.

Verification may require additional data from external sources (e.g., beacon chain finality updates, sync committee data), so it follows the same asynchronous execution model as proof generation.

Memory Management: The caller is responsible for freeing the returned context using c4_verify_free_ctx() when done.

Trusted Checkpoints:

A trusted checkpoint is a 32-byte hash of a beacon chain block root that is assumed to be correct. Colibri uses this checkpoint as the starting point for verification, avoiding the need to sync from genesis.

  • Format: "0x" + 64 hex characters (66 characters total)

  • Recommended: Use a recent finalized beacon block root from a trusted source

  • If NULL: Uses the built-in checkpoint for the chain (may be outdated)

Example:

Parameters

  • proof : The proof data to verify

  • method : The Ethereum RPC method that was proven (e.g., "eth_getBalance")

  • args : The method arguments as JSON array string (must match proof)

  • chain_id : The blockchain chain ID (must match proof)

  • trusted_checkpoint : Optional trusted checkpoint as hex string (0x-prefixed, 66 chars),

Returns

A new verification context pointer, or NULL if creation failed

c4_verify_execute_json_status

bindings/colibri.h

Executes one step of the proof verification state machine.

This function drives the asynchronous proof verification process. Call it repeatedly in a loop until it returns a status of "success" or "error". When it returns "pending", the host system must handle the pending data requests before calling this function again.

The execution flow is identical to c4_prover_execute_json_status(), but returns the verified result instead of a proof.

Memory Management: The returned JSON string must be freed by the caller using free().

Return Value Format:

Success (verification complete):

Error (verification failed):

Pending (waiting for external data):

Example Usage:

Parameters

  • ctx : The verification context created by c4_verify_create_ctx()

Returns

A JSON string describing the current status (see format below)

c4_verify_free_ctx

bindings/colibri.h

Frees all resources associated with a verification context.

This function must be called to clean up a verification context created by c4_verify_create_ctx(). After calling this function, the context pointer is invalid and must not be used.

Example:

Parameters

  • ctx : The verification context to free (may be NULL, in which case this is a no-op)

c4_get_method_support

bindings/colibri.h

Queries whether a specific RPC method is supported and how it should be handled.

Not all Ethereum RPC methods can be cryptographically proven. This function returns information about method support, allowing the host system to decide how to handle each RPC call.

Return Values:

Value
Name
Meaning
How to Handle

1

PROOFABLE

Method can be cryptographically proven

Use proof generation and verification flow

2

UNPROOFABLE

Method exists but cannot be proven

Call RPC node directly without proof

3

NOT_SUPPORTED

Method is not supported by Colibri

Return error to caller

4

LOCAL

Method can be computed locally

Use verification with empty proof

0

UNKNOWN

Unknown method or error

Treat as NOT_SUPPORTED

Proofable Methods (return 1):

  • State queries: eth_getBalance, eth_getCode, eth_getStorageAt, eth_getProof

  • Transaction queries: eth_getTransactionByHash, eth_getTransactionReceipt, eth_getTransactionByBlockHashAndIndex, eth_getTransactionByBlockNumberAndIndex

  • Block queries: eth_getBlockByHash, eth_getBlockByNumber, eth_getBlockTransactionCountByHash, eth_getBlockTransactionCountByNumber

  • Log queries: eth_getLogs

  • Call simulation: eth_call, eth_estimateGas

Unproofable Methods (return 2):

  • Mempool: eth_sendTransaction, eth_sendRawTransaction, eth_getTransactionCount (pending)

  • Mining: eth_mining, eth_hashrate, eth_getWork, eth_submitWork

  • Network: net_listening, net_peerCount

Local Methods (return 4):

  • eth_chainId: Returns the configured chain ID

  • net_version: Returns the network version (same as chain ID)

Example:

Parameters

  • chain_id : The blockchain chain ID to check

  • method : The Ethereum RPC method name (e.g., "eth_getBalance")

Returns

Method support type (see table below)

Last updated