A gRPC service acting as a "cryptographic adapter" providing proofs that data (a blob) exists on Celestia that are efficiently verifiable on EVM networks. A Namespace Merkle Tree (NMT) proof is transformed via a Zero Knowledge Proof (ZKP) into a keccak hash check.
A few key features:
- On each request, a status is returned. Internally the service will dive each request to success or failure.
- If a retryable failure is encountered, a subsequent request will attempt the job again.
- It is normal and safe behavior to regularly repeat the same request for status updates and retries.
- The service eagerly caches work as it's completed, returning those results rather than redoing work.
Jump to a section:
- Send requests this service: Interact
- Spin up an instance of the service: Operate
- Build & troubleshoot: Develop
flowchart TB
user@{ shape: circle, label: "End User" } ==>|POST Request Eq. Proof| jobs
zkep@{ shape: doc, label: "zkVM Equivalence Program" } --> zkc
subgraph eq ["`**Equivalence Service**`"]
nmtp@{ shape: lean-r, label: "NMT Proofs" }
zkp@{ shape: lean-r, label: "ZK Proofs" }
lc[Celestia Light Client] --> nmtp --> jobs
nmtp --> zkc
zkc[ZK Proof Generation Client] --> zkp --> jobs
jobs[Jobs Que & Results Cache] <--> sled
sled[(Sled DB)]
end
lc --->|GET NMT Inclusion| cel{Celestia}
zkc --->|POST Proof Generation| pn{ZK Prover Network}
style zkep fill:#66f
style jobs fill:#888
The service requires a connection to:
- Celestia Data Availability (DA) Node to:
- Fetch blob data.
- Get headers.
- Retrieve Merkle tree proofs for blobs.
- Succinct's prover network as a provider to generate Zero-Knowledge Proofs (ZKPs) of data existing on Celestia. See the ZKP program for details on what is proven.
Any gRPC client will do, integrating via the eqservice.proto
interface
The endpoint reports back a status, error, or success of a Job
linked to identical request fields.
Repeated requests will yield status updates and eventually a finalized proof or error status.
Here are examples using the grpcurl
CLI tool:
# Acquire the proto
curl https://raw.githubusercontent.com/celestiaorg/eq-service/refs/heads/main/common/proto/eqservice.proto --output eqservice.proto
# Local or remote instance of the eq-service
export EQ_SOCKET="127.0.0.1:50051"
# Where to find the proto file
export EQ_PROTO_DIR="."
# Example
# Fetching the Keccak inclusion proof for a specific Celestia commitment, namespace, and height
grpcurl -import-path $EQ_PROTO_DIR -proto eqservice.proto \
-d '{height": <block height (integer)>", "namespace": "<your_namespace_hex>", commitment": "<your_commitment_hex>"}'
-plaintext $EQ_SOCKET eqs.Inclusion.GetKeccakInclusion
# Working examples using Celestia's mocha network
# https://mocha.celenium.io/tx/e064ae79e06150ae75b37d3604c015d5698e173c52d0c2e3bf3203fe708e7513?tab=messages
grpcurl -import-path $EQ_PROTO_DIR -proto eqservice.proto \
-d '{"height": 4214864, "namespace": "3q2+796tvu8=", "commitment":"YcARQRj9KE/7sSXd4090FAONKkPz9ajYKIZq8liv3A0="}' \
-plaintext $EQ_SOCKET eqs.Inclusion.GetKeccakInclusion
# https://mocha.celenium.io/tx/c3c301fe579feb908fe02e2e8549c38f23707d30a3d4aa73e26402d854ff9104
grpcurl -import-path $EQ_PROTO_DIR -proto eqservice.proto \
-d '{"height": 4409088, "namespace": "XSUTEfJbE6VJ4A==", "commitment":"DYoAZpU7FrviV7Ui/AjQv0BpxCwexPWaOW/hQVpEl/s="}' \
-plaintext $EQ_SOCKET eqs.Inclusion.GetKeccakInclusion
# https://mocha.celenium.io/tx/6ead3f794b384a9f41f58e62be4d58822626add607eefcb7ab9f0dd6b70a6abe
grpcurl -import-path $EQ_PROTO_DIR -proto eqservice.proto \
-d '{"height": 4499000, "namespace": "EV1P7ciRW7PodQ==", "commitment":"mV9udfLnkNqmG/3khk2/gH0wLPx/6RinVDCTV77X3Xw="}' \
-plaintext $EQ_SOCKET eqs.Inclusion.GetKeccakInclusion
# https://mocha.celenium.io/tx/30a274a332e812df43cef70f395c413df191857ed581b68c44f05a3c5c322312
grpcurl -import-path $EQ_PROTO_DIR -proto eqservice.proto \
-d '{"height": 4499999, "namespace": "Ucwac9Zflfa95g==", "commitment":"S2iIifIPdAjQ33KPeyfAga26FSF3IL11WsCGtJKSOTA="}' \
-plaintext $EQ_SOCKET eqs.Inclusion.GetKeccakInclusion
Most users will want to pull and run this service via the container registry
-
A machine to run with a minimum of:
- 2 threads
- 2GB RAM
- Ports accessible (by default):
- service listening at
50051
- Light client (local or remote) over
26658
- Succinct prover network over
443
- service listening at
- NOTE: These requirements may be significantly more to respond under heavy load, please report if you have issues!
-
A whitelisted key in your
env
for use with the Succinct prover network Key - requested here. -
A Celestia Light Node installed & running accessible on
localhost
, or elsewhere. Alternatively, use an RPC provider you trust.
Required and optional settings are best configured via a .env
file. See example.env
for configurable items.
cp example.env .env
# edit .env
Docker and Podman is configured in Dockerfile to build an image with that includes a few caching layers to minimize development time & final image size -> publish where possible. To build and run in a container:
# Using just
just docker-build
just docker-run
# Manually
## Build
[docker|podman] build -t eq_service .
## Setup
source .env
mkdir -p $EQ_DB_PATH
## Run (example)
[docker|podman] run --rm -it -v $EQ_DB_PATH:$EQ_DB_PATH --env-file .env --env RUST_LOG=eq_service=debug --network=host -p $EQ_PORT:$EQ_PORT eq_service
Importantly, the DB should persist, and the container must have access to connect to the DA light client (likely port 26658) and Succinct network ports (HTTPS over 443).
The images are built and published for releases and available to pull from here: TODO
First, some tooling is required:
- Rust & Cargo - install instructions
- Succinct's SP1 zkVM Toolchain - install instructions
- Protocol Buffers (Protobuf) compiler - official examples contain install instructions
- (Optional) Just - a modern alternative to
make
installed
Then:
-
Clone the repo
git clone https://github.com/your-repo-name/eq-service.git cd eq-service
-
Choose a Celestia Node
- See the How-to-guides on nodes to run one yourself, or choose a provider & set in
env
. - NOTE: You must have the node synced back to the oldest possible height you may encounter in calling this service for it to fulfill that request.
- See the How-to-guides on nodes to run one yourself, or choose a provider & set in
-
Build and run the service
# NOT optimized, default includes debug logs printed just run-debug # Optimized build, to test realistic performance w/ INFO logs just run-release
There are many other helper scripts exposed in the justfile, get a list with:
# Print just recipes
just
TODO