A trustless Mina light node — it joins the p2p network and verifies the chain from its recursive SNARK proof. Unlike a typical light client (an RPC consumer), this is a real light node: it participates in the network.
Mina p2p network ──▶ mina-relay ──(candidate tip)──▶ mina-verify ──▶ verified tip
(untrusted) (this repo) (separate repo) + Merkle-proof reads
- Safety ("never accept a false state") comes from
mina-verify— one recursive proof validates the whole chain (stronger than Bitcoin SPV: no header download). - Liveness / censorship-resistance ("you see the real, current chain") comes
from
mina-relay— decentralized p2p access across many peers, not a trusted RPC.
| Crate | What |
|---|---|
mina-relay |
The p2p network layer: connect to gossip, receive blocks, tap the mempool, broadcast txs, track peers. Proof-systems-agnostic (libp2p + message types only; no verification). Reusable on its own. |
mina-light-node |
The product binary: wires mina-relay + mina-verify into one runnable trustless light node. |
The verifier lives in its own repo, MinaProtocol/mina-verify,
because it's consumed independently (MCP server via wasm, mobile app, the trustless
indexer's trust gate). This repo composes it; it does not own it.
Scaffold. mina-relay carries the working gossip/RPC/broadcast primitives (moved
from mina-verify-capture). The mina-light-node binary currently follows the
gossip network and surfaces candidate tips; the verifier trust-gate, account reads,
mempool tap, broadcast API, and liveness cross-check are TODOs (see src/main.rs).
| Binary | What |
|---|---|
mina-light-node |
Headless node: verify-before-ingest, surfaces the verified tip on stdout / LIGHT_NODE_TIP_FILE. |
mina-light-node-server |
The node + a trustless HTTP API (reads / submit / mempool) — what a Rosetta adapter or a client-side integrity monitor consumes. |
cargo build
# headless node
MINA_NETWORK=devnet cargo run -p mina-light-node
# node + trustless HTTP API on :8645
MINA_NETWORK=devnet cargo run -p mina-light-node --bin mina-light-node-servercurl :8645/health # {status, network, uptime_secs, verified, rejected, seconds_since_last_verified}
curl :8645/tip # {height, state_hash, staking_epoch_ledger_hash}
curl ':8645/account?index=0' # trustless balance/nonce by leaf index (instant)
curl ':8645/account?pubkey=B62…' # by public key (resolved from the swept index map)
curl :8645/mempool # best-effort pending tx ids
curl -XPOST :8645/submit -d '{"tx_hex":"…"}' # broadcast a signed user commandEvery /account answer is Merkle-proved against the verified tip's staking-epoch-ledger
root (what peers serve over sync-ledger), so a lying peer is rejected.
By-public-key needs a pubkey → leaf-index map (the sync-ledger RPC indexes by leaf, not
key). It's an untrusted hint — every read still re-proves Merkle inclusion — so it ships
in the image. Generate it with mapgen and point the server at it via LIGHT_NODE_INDEX_MAP:
MINA_NETWORK=devnet cargo run -p mina-light-node --bin mina-light-node-mapgen devnet.bin
LIGHT_NODE_INDEX_MAP=devnet.bin MINA_NETWORK=devnet cargo run -p mina-light-node --bin mina-light-node-serverThe release pipeline runs mapgen per network, bakes the map into the image and attaches
it to the GitHub Release. Without a baked map the server falls back to sweeping the epoch
ledger at cold start (minutes on a large ledger). The map is generated by an RPC sweep, not
the S3 RocksDB tarball — see docs/ (the tarball stores the leaf index in Mina's
internal RocksDB Location encoding, which the sweep sidesteps).
- Wire the trust gate: verify each gossiped block's proof before ingest
(
verify_tip+ChainMonitor); validated on live devnet. - Account reads:
GET /account?pubkey=&index=Merkle-proves balance/nonce against the verified staking-epoch-ledger root; validated on devnet (account 0 + by-pubkey). - Mempool tap: tx-pool gossip → bounded, TTL'd view (
mempool::MempoolView), keyed by the canonical Mina tx hash;GET /mempool. - Broadcast:
POST /submitpublishes a signed tx to the tx-pool gossip topic. - Liveness cross-check (expose side):
GET /tipis the proof-verified tip a consumer compares against a less-trusted source to flag divergence. - HTTP/RPC surface + deploy glue (
mina-light-node-server, seedeploy/). - Baked
pubkey→indexmap built bymapgenat release time, baked into the image + attached to the release (removes the cold-start sweep); envLIGHT_NODE_INDEX_MAP. - Generate the map from the S3 RocksDB epoch-ledger tarball (vs the current RPC sweep).
- Optional GraphQL facade for existing Mina clients.