Skip to content

Latest commit

 

History

History
98 lines (77 loc) · 5.21 KB

File metadata and controls

98 lines (77 loc) · 5.21 KB

mina-light-node

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.

Crates

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.

Status

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).

Binaries

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.

Build / run

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-server

HTTP API (mina-light-node-server, env LIGHT_NODE_HTTP_ADDR, default 127.0.0.1:8645)

curl :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 command

Every /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.

Baked pubkey → index map

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-server

The 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).

Roadmap (see the trustless-light-stack arch doc)

  • 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 /submit publishes a signed tx to the tx-pool gossip topic.
  • Liveness cross-check (expose side): GET /tip is the proof-verified tip a consumer compares against a less-trusted source to flag divergence.
  • HTTP/RPC surface + deploy glue (mina-light-node-server, see deploy/).
  • Baked pubkey→index map built by mapgen at release time, baked into the image + attached to the release (removes the cold-start sweep); env LIGHT_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.