Skip to content

Commit 912e6d2

Browse files
authored
Feat/add backend (#5)
* feat: add zcash client * feat: update bridge node to support zcash * feat: bring back spv mmr * chore: prob not needed now, but bringing back to be sure * chore: deactivate subchain work check * chore: fmt * chore: rm mmr and wasm crate * chore: rm accumulator crate * chore: cleanup store * chore: rm old crates * chore: add comment * fix: height at init error * feat: add tx merkle logic * feat: add tx merkle proof generation logic * feat: connect get tx proof endpoint * chore: minor cleanup * chore: fmt + clippy * fix: test * chore: impl change requests * chore: fmt + clippy
1 parent f32340f commit 912e6d2

22 files changed

Lines changed: 2576 additions & 1 deletion

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ __pycache__
3333
.utxo_data/
3434
.utreexo_data
3535
.mmr_data/
36+
.data/
3637
.timestamps_data/
3738
.arguments*.json
3839
.proofs*

Cargo.toml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
[workspace]
2+
resolver = "2"
3+
members = [
4+
"crates/zoro-spv-verify",
5+
"crates/zoro-bridge-node",
6+
"crates/zoro-zcash-client",
7+
]
8+
9+
[patch."https://github.com/m-kus/cairo-vm"]
10+
cairo-vm = { git = "https://github.com/maciejka/cairo-vm", rev = "19d8a07ce9799a8af9db6f8a14a8accaad900214" }
11+
12+
[workspace.dependencies]
13+
# Async runtime
14+
tokio = { version = "1.36", features = ["full"] }
15+
reqwest = { version = "0.12", features = ["json", "gzip", "brotli", "zstd"] }
16+
async-trait = "0.1"
17+
18+
# zcash
19+
zebra-chain = {version = "3.1.0"}
20+
21+
# RPC
22+
jsonrpsee = { version = "0.25.1", features = ["http-client", "async-client"] }
23+
base64 = "0.21"
24+
25+
# Storage
26+
sqlx = { version = "0.8", features = ["runtime-tokio", "sqlite"] }
27+
28+
# CLI
29+
clap = { version = "4.5", features = ["derive", "env"] }
30+
dotenv = "0.15"
31+
32+
# Hashing
33+
blake2 = "0.10"
34+
35+
# Serialization
36+
serde = { version = "1.0", features = ["derive"] }
37+
serde_json = { version = "1.0", features = ["arbitrary_precision"] }
38+
hex = "0.4"
39+
bincode = "1.3"
40+
41+
# BigInt
42+
num-bigint = { version = "0.4", features = ["serde"] }
43+
num-traits = "0.2"
44+
45+
# Error handling
46+
thiserror = "1.0"
47+
anyhow = "1.0"
48+
49+
# Logging
50+
tracing = "0.1"
51+
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
52+
53+
# Testing
54+
mockall = "0.12"
55+
wiremock = "0.5"
56+
tempfile = "3.10"

crates/zoro-bridge-node/Cargo.toml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
[package]
2+
name = "zoro-bridge-node"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
zoro-zcash-client = { path = "../zoro-zcash-client" }
8+
zoro-spv-verify = { path = "../zoro-spv-verify" }
9+
10+
# Zcash types
11+
zebra-chain.workspace = true
12+
13+
# Async runtime
14+
tokio.workspace = true
15+
async-trait.workspace = true
16+
# Web framework
17+
axum = "0.7"
18+
tower-http = { version = "0.5", features = ["trace", "cors", "compression-gzip"] }
19+
20+
# Storage
21+
sqlx.workspace = true
22+
bincode.workspace = true
23+
# CLI
24+
clap.workspace = true
25+
dotenv.workspace = true
26+
# Hashing
27+
blake2.workspace = true
28+
# Serialization
29+
serde.workspace = true
30+
serde_json.workspace = true
31+
hex.workspace = true
32+
# BigInt
33+
num-bigint.workspace = true
34+
num-traits.workspace = true
35+
# Error handling
36+
thiserror.workspace = true
37+
anyhow.workspace = true
38+
# Retry logic
39+
backoff = { version = "0.4", features = ["futures", "tokio"] }
40+
# Logging
41+
tracing.workspace = true
42+
tracing-subscriber.workspace = true
43+
44+
[dev-dependencies]
45+
# Testing
46+
mockall.workspace = true
47+
wiremock.workspace = true
48+
tempfile.workspace = true

crates/zoro-bridge-node/README.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# Zoro Bridge Node
2+
3+
A Zcash block indexer that accumulates the Zcash blocks, and generates data required for running the [`assumevalid`](../../packages/assumevalid/) program.
4+
5+
## Overview
6+
7+
The Zoro Bridge Node serves as a data preprocessing layer for the Zcash ZK client, and as an API providing compressed SPV proofs. A compressed SPV proof is a self-sufficient transaction inclusion proof that does not require clients to store the Zcash headers locally nor keep connection to a Zcash RPC node.
8+
9+
## What it does
10+
11+
1. **Connects to Zcash Core** via RPC to fetch block headers
12+
2. **Accumulates block headers** using Cairo-compatible Blake2 hashing
13+
4. **Organizes output** into sharded JSON files for efficient access by the proving pipeline
14+
15+
Zoro bridge node does not handle reorgs, instead it operates with a configurable lag (by default — 1 block).
16+
17+
## Usage
18+
19+
### Command Line
20+
21+
```bash
22+
# Basic usage with remote RPC node
23+
cargo run --bin zoro-bridge-node -- --zcash-rpc-url https://zcash-mainnet.public.blastapi.io
24+
25+
# With authentication
26+
cargo run --bin zoro-bridge-node -- --zcash-rpc-url http://localhost:8332 --zcash-rpc-userpwd user:password
27+
28+
# Custom data directory and shard size
29+
cargo run --bin zoro-bridge-node -- \
30+
--zcash-rpc-url http://localhost:8332 \
31+
--db-path ./custom/app.db \
32+
--roots-dir ./custom/roots \
33+
--shard-size 5000
34+
35+
# Production setup with remote node and custom RPC server host
36+
cargo run --bin zoro-bridge-node -- \
37+
--zcash-rpc-url https://zcash-node.example.com:8332 \
38+
--zcash-rpc-userpwd myuser:mypassword \
39+
--rpc-host 0.0.0.0:8080 \
40+
--shard-size 50000 \
41+
--log-level warn
42+
```
43+
44+
### Environment Variables
45+
46+
You can use environment variables instead of command line arguments:
47+
48+
```bash
49+
# Set environment variables
50+
export ZCASH_RPC="http://localhost:8332"
51+
export USERPWD="user:password"
52+
53+
# Run with defaults (no arguments needed)
54+
cargo run --bin zoro-bridge-node
55+
```
56+
57+
### Using .env File
58+
59+
Create a `.env` file in the project directory:
60+
61+
```env
62+
ZCASH_RPC=http://localhost:8332
63+
USERPWD=user:password
64+
```
65+
66+
Then simply run:
67+
68+
```bash
69+
cargo run --bin zoro-bridge-node
70+
```
71+
72+
## Configuration
73+
74+
| Option | Default | Environment Variable | Description |
75+
|--------|---------|---------------------|-------------|
76+
| `--zcash-rpc-url` | - | `ZCASH_RPC` | Zcash Core RPC URL (required) |
77+
| `--zcash-rpc-userpwd` | - | `USERPWD` | RPC credentials in `user:password` format |
78+
| `--rpc-host` | `127.0.0.1:5000` | - | Host and port for the bridge node's RPC server |
79+
| `--db-path` | `./.data/app.db` | - | SQLite database path for app storage |
80+
| `--shard-size` | `10000` | - | Number of blocks per shard directory |
81+
| `--log-level` | `info` | - | Logging verbosity |
82+
83+
> **Note**: When environment variables are set (either directly or via `.env` file), you can run the bridge node without any command line arguments. This is especially convenient for deployment and development setups.
84+
85+
## RPC Server and API Endpoints
86+
87+
The Zoro Bridge Node runs an HTTP RPC server that provides REST endpoints for querying block data and generating proofs. By default, the server binds to `127.0.0.1:5000`, but this can be configured using the `--rpc-host` option.
88+
89+
### Available Endpoints
90+
91+
#### GET /block-inclusion-proof/:height (needs update)
92+
93+
Generate an inclusion proof for a block at the specified height.
94+
95+
**Parameters:**
96+
- `height` (path parameter): The block height to generate a proof for (0-indexed)
97+
- `block_count` (query, optional): If provided, generate the proof against the header state at this total number of blocks
98+
99+
**Response:**
100+
```json
101+
{
102+
"peaks_hashes": [
103+
"0x5fd720d341e64d17d3b8624b17979b0d0dad4fc17d891796a3a51a99d3f41599",
104+
"0x693aa1ab81c6362fe339fc4c7f6d8ddb1e515701e58c5bb2fb54a193c8287fdc"
105+
],
106+
"siblings_hashes": [
107+
"0xc713e33d89122b85e2f646cc518c2e6ef88b06d3b016104faa95f84f878dab66"
108+
],
109+
"leaf_count": 832500
110+
}
111+
```
112+
113+
**Response Fields:**
114+
- `peaks_hashes`: Array of MMR peak hashes at the time of proof generation (hex-encoded strings)
115+
- `siblings_hashes`: Array of sibling hashes needed to reconstruct the path to the root (hex-encoded strings)
116+
- `leaf_count`: Total number of leaves (blocks) in the MMR the proof was generated against
117+
118+
**Status Codes:**
119+
- `200 OK`: Proof generated successfully
120+
- `500 Internal Server Error`: Failed to generate proof (e.g., invalid height)
121+
122+
#### GET /head
123+
124+
Get the current head (latest processed block height) from the MMR.
125+
126+
Note: The service operates with a lag of at least 1 block; `/head` returns the latest processed height (0-indexed), which is typically `block_count - 1`.
127+
128+
**Response:**
129+
```json
130+
832500
131+
```
132+
133+
**Response:** The current head height as a JSON number (0-indexed)
134+
135+
**Status Codes:**
136+
- `200 OK`: Block count retrieved successfully
137+
- `500 Internal Server Error`: Failed to retrieve block count
138+
139+
### Usage Examples
140+
141+
```bash
142+
# Get the current head (latest processed block height)
143+
curl http://localhost:5000/head
144+
145+
# Generate a proof for block at height 100 (latest state)
146+
curl "http://localhost:5000/block-inclusion-proof/100"
147+
148+
# Generate a proof for block at height 100 for an earlier state (block_count=90)
149+
curl "http://localhost:5000/block-inclusion-proof/100?block_count=90"
150+
151+
# Get sparse roots for the latest state
152+
curl "http://localhost:5000/roots"
153+
154+
155+
# Using a custom RPC host
156+
cargo run --bin zoro-bridge-node -- \
157+
--zcash-rpc-url http://localhost:8332 \
158+
--rpc-host 0.0.0.0:8080
159+
160+
# Then query the custom endpoint
161+
curl http://localhost:8080/head
162+
```
163+
164+
### Integration
165+
166+
The RPC server is designed to be used by:
167+
1. **ZK Clients**: To obtain inclusion proofs for Zcash blocks
168+
2. **Monitoring Tools**: To track synchronization progress via the `/head` endpoint
169+
170+
## Requirements
171+
172+
- Access to a Zcash RPC node
173+
- Sufficient disk space (numbers are for the first 900K blocks)
174+
* 300MB for the accumulator state DB
175+
* 3.6GB for the sparse roots files

0 commit comments

Comments
 (0)