Lightwalletd-rs: a Rust implementation of lightwalletd for light wallets

Hi Zcashers :waving_hand:

For the last few months I’ve been building lightwalletd-rs, a Rust implementation of lightwalletd, and I’d love to share it with the community and hear what you think.

Repo: GitHub - jpgonzalezra/lightwalletd-rs: A Rust lightwalletd for Zcash: a caching proxy that serves compact blockchain data to shielded light wallets over gRPC. · GitHub (MIT)

⚠️ Beta, not security-audited. Under active development. Expect breaking changes and run it at your own risk.

Why I built it

I come from the Ethereum world, and I’ve recently started going deep on Zcash. Its privacy model and the cryptography behind it are what pulled me in, and I’ve always found the best way to learn an ecosystem is to build something real in it, so I picked a piece of its infrastructure I wanted to understand and reimplemented it.

I wanted to see what a lightwalletd would look like written in Rust: a single memory-safe binary, fast to sync, easy to run, and built directly on the librustzcash crates the rest of the ecosystem already uses. It started as a way to understand the light-client protocol end to end, and grew into something I think others might find useful to run.

What it is

Light wallets don’t download the whole chain; they rely on a server that hands them a slimmed-down view of it. lightwalletd is that server. lightwalletd-rs is a caching proxy between a Zcash full node (zebrad) and light wallets: it pulls blocks from the node, strips the zk proofs (a ~2 MB block becomes a few KB), caches them on disk, and streams them to wallets over the standard light-client gRPC. Everything else (send tx, tree state, mempool, transparent balances) is proxied to the node.

Because it speaks the standard protocol, existing Zcash light wallets connect to it unchanged.

What works today

  • All 20 CompactTxStreamer methods (blocks, transactions, tree state, subtrees, nullifiers, transparent balances/txids, mempool).
  • On-disk compact-block cache with reorg rollback and automatic recovery from gaps/corruption.
  • TLS on by default, Prometheus metrics + gRPC reflection, and hardened defaults (input validation, per-connection limits, graceful shutdown).
  • A “darkside” test mode: a controllable mock chain for deterministic wallet tests.
  • Two backends: the default one talks to any reachable zebrad over JSON-RPC; an optional one reads a co-located node’s state in-process for lower read latency.

There’s a reproducible benchmark harness in the repo too. Early numbers are encouraging (a full genesis→tip sync in ~1h 22m on my test host) but they’re relative to one machine. The README has the full methodology and disclaimer so you can reproduce them yourself.

Looking ahead

I’d love feedback from wallet developers, node operators, and anyone running Zcash infrastructure, especially on protocol edge cases and deployment ergonomics. Issues and PRs are very welcome, and I’m happy to help anyone who wants to spin one up.

Thanks

lightwalletd-rs is inspired by and indebted to the original Go lightwalletd. Its protocol, behavior, and years of design decisions were the reference I followed. Thanks to the whole Zcash community that built and maintains it. :folded_hands:

2 Likes

What’s the difference with zaino?

Zaino is a general-purpose indexer: it serves full-node wallets and block
explorers as well as the light-client gRPC, backed by its own index database.
lightwalletd-rs is scoped to the light-client gRPC alone, filling the same role
as lightwalletd but reimplemented on the ecosystem’s Rust stack (librustzcash
for parsing, optionally Zebra’s ReadStateService for reads), with measured gains
in throughput and tail latency under concurrency.

2 Likes

Small update: there are public endpoints now, if anyone wants to try this without
running a node.

mainnet.lightwalletd-rs-beta.zecdev.org:443
testnet.lightwalletd-rs-beta.zecdev.org:443

Both are lightwalletd-rs 0.1.1 in front of Zebra 6.3.0, TLS on 443, so you can point
a wallet at them like any other server.

It really is beta. I’ll be restarting them as I push changes and I’m not promising
uptime yet, so don’t put anything you care about behind them.

They also share a machine with the two zebrad nodes, on a modest CPU and bandwidth
budget. Fine for using a wallet or poking at the gRPC API, but if you benchmark them
you’ll be measuring my hosting, not the code. There are proper numbers in
contrib/bench/results/ from a controlled setup.

If something breaks or looks off, open an issue. That’s mostly why they’re up.

3 Likes