# Current ways to connect to gRPC in the Zcash stack (LWD, Zaino, Zebrad, Zakura, ztreamer)

**URL:** <https://forum.zcashcommunity.com/t/current-ways-to-connect-to-grpc-in-the-zcash-stack-lwd-zaino-zebrad-zakura-ztreamer/57539>\
**Category:** General\
**Created:** [September 10, 2026, 2:46pm UTC](https://forum.zcashcommunity.com/t/current-ways-to-connect-to-grpc-in-the-zcash-stack-lwd-zaino-zebrad-zakura-ztreamer/57539 "2026-09-10T14:46:06Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![dismad](https://sea2.discourse-cdn.com/zcash/user_avatar/forum.zcashcommunity.com/dismad/32/18432_2.png) [@dismad](https://forum.zcashcommunity.com/u/dismad)\
**Post date:** [September 10, 2026, 2:46pm UTC](https://forum.zcashcommunity.com/t/current-ways-to-connect-to-grpc-in-the-zcash-stack-lwd-zaino-zebrad-zakura-ztreamer/57539/1 "2026-09-10T14:46:06Z")

</div>

![headed](https://global.discourse-cdn.com/zcash/original/3X/e/1/e1559c42d9cae155fb802bd4cf2209c85165cd58.jpeg)

This is a snapshot as of September 2026 of how clients actually talk gRPC in the Zcash ecosystem: what implements `CompactTxStreamer`, what is a different gRPC surface, how you transport it, and the tradeoffs.

Corrections welcome if I have a port, completeness claim, or status wrong.

This is sourced from grok.

* * *

## The wallet contract

Almost every light wallet still speaks one service:

`cash.z.wallet.sdk.rpc.CompactTxStreamer`

Canonical protos: [zcash/lightwallet-protocol](https://github.com/zcash/lightwallet-protocol) (ZIP-307). Current methods include compact blocks / nullifiers, tx fetch + submit, transparent address queries, mempool streams, tree/subtree state, UTXOs, `GetLightdInfo`. Ironwood (NU6.3) fields are in the current proto.

If you are wiring a wallet SDK, this is the API. Everything below is “who serves it” and “how the bytes get there.”

JSON-RPC on zebrad/zakura `:8232`, Zaino `:8237`, or hosted “Zcash RPC” gateways (Tatum, QuickNode, etc.) is a **different** protocol. Do not point `CompactTxStreamerClient` at those.

Zebrad also has a **second** gRPC service, `zebra.indexer.rpc.Indexer` (`rpc.indexer_listen_addr`). That is for indexers and trusted sync, not for Zashi/Ywallet. Do not confuse it with CompactTxStreamer.

## CompactTxStreamer servers

| | lightwalletd | Zaino (zainod) | zebrad native LWD | ztreamer | lightwalletd-rs | Zinder compat |
| --- | --- | --- | --- | --- | --- | --- |
| **What** | Original Go compact-block server | Rust indexer replacing LWD + a zcashd JSON-RPC subset | Zebra serving CompactTxStreamer in-process ([#10953](https://github.com/ZcashFoundation/zebra/pull/10953)) | CompactTxStreamer + P2Pv2 on embedded Zakura | Rust LWD rewrite | Compat plane in front of Zinder `WalletQuery` |
| **Repo** | `zcash/lightwalletd` | `zingolabs/zaino` | `ZcashFoundation/zebra` (`zebra_rpc::lightwalletd`) | `distractedm1nd/ztreamer` | `jpgonzalezra/lightwalletd-rs` | `gustavovalverde/zinder` |
| **Age** | ~2019–2020; latest **v0.5.4** (Aug 2026) | Grant work 2024; LWD-compat pre-release Nov 2024; **0.2.0** ~Sep 2025; **0.8.0** Aug 2026 | **Merged 18 Aug 2026.** Not the 2024 Zebra 1.6 scanner/indexer gRPC | **v0.0.1** announced 2 Sep 2026 | Forum announce Jul 2026, beta | 2026, early |
| **Process** | Separate Go daemon | Separate Rust daemon | Same process as zebrad | Same process as embedded Zakura | Separate Rust daemon | Separate reader |
| **Default gRPC** | `127.0.0.1:9067` | `127.0.0.1:8137` | `[rpc] lightwalletd_listen_addr` (often `:9067`) | configurable; docs use `:9067` | TLS on by default | compat ~`:19067` |
| **Backend** | JSON-RPC → zcashd / **zebrad** / **zakura** (0.5.1+) | `rpc` = JSON-RPC to node (default, remote-ok); `direct` = Zebra state DB (same host) | In-process read-state + mempool; wallet-shaped RPCs reused from JSON-RPC `RpcImpl` | In-process Zakura | zebrad JSON-RPC or co-located state | Own RocksDB projections |
| **Protocol coverage** | Full + Ironwood in 0.5.0 | Full list in `docs/rpc_api.md` | **18 methods.** `Ping` disabled to match production LWD. Ironwood in-tree. See wire-compat notes below | All methods **except `GetMempoolTx`**. `GetBlock` omits transparent data; `GetBlockRange` rejects transparent filters | Claims full CompactTxStreamer + darkside | Compat shim; certify per wallet |
| **Other APIs** | optional HTTP debug | JSON-RPC explorer/wallet subset (`:8237`) | zebrad JSON-RPC `:8232` + separate indexer gRPC | 24/27 of Zaino-direct JSON-RPCs | Prometheus, reflection | Native `zinder.v1.wallet.WalletQuery` |
| **TLS** | Production certs expected; `--no-tls-very-insecure` is local-only | Public bind **requires** TLS unless `no_tls_use_unencrypted_traffic` | **None.** Plaintext HTTP/2, no cookie auth | Plaintext default; PEM cert/key flags | TLS on by default | Bind loopback; TLS on your proxy |
| **Wallet compat** | What Zashi/ZODL, Ywallet, Zingo, Ledger utils assume | Drop-in for LWD clients; Z3 indexer profile | Same proto with documented LWD wire quirks; **do not** put public wallets on it yet | Same proto with the deviations above | Same proto, unaudited | Only after end-to-end cert |
| **Public hosts** | `zec.rocks:443`, Cake, 0xRPC, … | `zaino.unsafe.zec.rocks:443` (+ testnet twin) | none intended | none known | none known | none known |
| **Pros** | Longest production history; every shipping light wallet already speaks it; Zakura recognized as backend | Unified LWD + JSON-RPC; Rust; Z3/Zallet path; TLS enforcement; remote `rpc` backend | Fewest moving parts; no second daemon; no compact-cache rebuild; DoS hardening in-tree | Fastest advertised historical index (author: 92s genesis→serve, ~16 GiB index); first P2P CompactTxStreamer | Rust, TLS defaults, metrics | Epoch-pinned reads; scale read plane separately |
| **Cons** | Extra daemon + compact cache; another failure domain | Still 0.x; `direct` is same-machine only; public hosts marked unsafe | Experimental; no TLS/auth; almost no production exposure; ZF: not for services you run for others | Brand new; proto deviations break t-addr/mempool clients; single-maintainer | Beta, not audited | Early; CompactTxStreamer is a translation layer |
| **Use when** | You want existing wallets to just work | Post-zcashd indexer / explorer RPC / Z3 | Dev/regtest or loopback behind your own TLS proxy | You’re on Zakura and care about index speed or P2P light clients | Rust LWD and you accept beta | Building on WalletQuery, need LWD during migration |

Zakura itself is **not** a CompactTxStreamer server. It is the full node (Zebra fork). LWD and ztreamer consume it. Zakura 1.3+/1.4+ specifically sped up the JSON-RPC that LWD polls (`getblockchaininfo`, historic tree frontiers for pruned / P2Pv2 nodes).

Shielded Labs **Zero** vendors zebra + zaino + zallet + lightwalletd. Same protocols, packaged for operators. No new gRPC API.

## Zebrad native CompactTxStreamer in detail

Source: [ZcashFoundation/zebra#10953](https://github.com/ZcashFoundation/zebra/pull/10953) — `feat(rpc)!: add lightwalletd-compatible gRPC server implementing CompactTxStreamer`, merged **18 Aug 2026**.

This is **not** the Zebra 1.6 (Feb 2024) shielded-scanning gRPC, and it is **not** `rpc.indexer_listen_addr`. Those are a different service (`zebra.indexer.rpc.Indexer`).

Enable:

```toml
[rpc]
lightwalletd_listen_addr = '127.0.0.1:9067'

```

Disabled by default. Implementation: `zebra_rpc::lightwalletd`, tonic, protos vendored from LWD into `zebra-rpc/proto/`. Compact blocks and mempool streams come from Zebra read-state / mempool in-process. Wallet-shaped calls (`GetTreeState`, `GetTaddressBalance`, `SendTransaction`, …) reuse existing JSON-RPC `RpcImpl`.

**Wire-compat, verified against Go LWD** (including two places LWD contradicts its own proto comments):

- `GetMempoolTx` exclude entries are **little-endian txid suffixes**.
- `GetMempoolStream` sends **height 0** for mempool txs.
- `GetTreeState` prefers hash over height and uses internal little-endian hash order. That diverges from LWD because of [zcash/lightwalletd#512](https://github.com/zcash/lightwalletd/issues/512); Zebra treats the LWD behavior as the bug.
- `Ping` is **disabled** , matching production LWD instances.
- Missing Sapling/Orchard tree → `ABORTED`, not size 0 (size 0 would corrupt client note positions across a reorg). Missing Ironwood tree **pre-activation** is treated as zero.
- Ironwood fields taken from `zcash/lightwallet-protocol`; Ironwood tree reads gated on activation.

**Hardening in the PR**

- Streamed t-addrs validated as they arrive (no unbounded buffer on `GetTaddressBalanceStream`).
- Raw tx larger than `MAX_BLOCK_BYTES` rejected before hex-encode.
- `MAX_EXCLUDE_ENTRIES` raised to 20,000 with suffix-length bucketing.
- Request tracing Tower layer aligned with JSON-RPC / Jaeger.

**Still experimental.** Plaintext HTTP/2, no TLS, no cookie auth. ZF book: do not run this on end-user machines; do not offer it as a public service without a TLS-terminating proxy and a loopback/private bind. The supported production path remains a separate `lightwalletd` in front of zebrad JSON-RPC. See [Zebra book: lightwalletd](https://zebra.zfnd.org/user/lightwalletd.html).

## Other gRPC surfaces (not the wallet proto)

| | Zebra / Zakura indexer gRPC | Zinder WalletQuery | gRPC-web gateway | P2Pv2 CompactTxStreamer |
| --- | --- | --- | --- | --- |
| **Service** | `zebra.indexer.rpc.Indexer` | `zinder.v1.wallet.WalletQuery` | CompactTxStreamer, different transport | CompactTxStreamer over Zakura P2Pv2 |
| **Age** | ~Zebra 1.6 (Feb 2024) scanning gRPC → current indexer API | 2026 | Constraint is old; packaged Envoy stack is 2026 grant work | ztreamer 0.0.1 (Sep 2026) |
| **Who connects** | Indexers, TrustedChainSync, historical backfill — **not** Zashi | New wallet integrations | Browser wallets (WebZjs) | Future P2P light wallets |
| **Listen** | `[rpc] indexer_listen_addr` e.g. `:8230`, feature `indexer` | native query port (Zinder docs ~`:19106`) | Envoy → upstream LWD or Zaino | Advertised as a P2P service |
| **Methods** | `ChainTipChange`, `NonFinalizedStateChange`, `MempoolChange`, `GetBlock`; Zakura adds streaming `GetBlockRange` | Native query API | Proxied CompactTxStreamer | Whatever ztreamer implements |
| **Pros** | Streaming tip/mempool; no compact-block transform | Designed query semantics | Only way browsers can talk to LWD/Zaino | No trusted LWD operator |
| **Cons** | Private / unauthenticated; not ZIP-307 | Existing SDKs don’t speak it | Extra hop; CORS / rate-limit / TLS | Experimental P2P; no shipping mobile wallet |
| **Use when** | Building an indexer against zebrad/zakura | Greenfield wallet API | Browser / extension | Research / Tachyon-shaped clients |

Zaino’s `validator_grpc_listen_address` in some configs is this **node** hop (Zaino → validator), not the wallet-facing `:8137`.

## Transports

Same CompactTxStreamer, different pipe.

| Transport | Pros | Cons |
| --- | --- | --- |
| Native gRPC/HTTP2 + TLS (`host:443`) | What every current mobile/desktop light wallet uses | Not browsers |
| Native gRPC plaintext (`:9067` / `:8137`) | Fine on loopback / private net | Address queries visible; anyone who can reach the port can submit txs |
| Reverse proxy (`nginx grpc_pass`, Envoy, haproxy) | TLS, rate limits, hide plaintext backend | Need large HTTP/2 frames + long stream timeouts |
| gRPC-web (Envoy) | Browsers work | Don’t give WebZjs an unproxied LWD URL |
| Tor (Arti in `zcash_client_backend`) | Hides client IP from the indexer | Does not hide _what_ you query; extra latency |
| P2Pv2 service discovery | No central LWD | New; unused by shipping wallets |

Quick checks:

```bash
# local LWD
grpcurl -plaintext localhost:9067 cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo

# local Zaino
grpcurl -plaintext localhost:8137 list
grpcurl -plaintext -d '{}' localhost:8137 cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock

# zebrad native CompactTxStreamer (if enabled)
grpcurl -plaintext localhost:9067 cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo

# public TLS
grpcurl zec.rocks:443 cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo

```

Client libraries that already speak this: `zcash_client_backend` `CompactTxStreamerClient` (tonic, `lightwalletd-tonic`), zingolib, Zashi/ZODL SDKs, Ywallet, `@ledgerhq/zcash-utils`. zecd defaults to zebrad JSON-RPC and can take a lightwalletd gRPC URL since 0.6.0.

## Topologies

Production-shaped:

```auto
wallet --TLS gRPC--> lightwalletd:9067 --JSON-RPC--> zebrad|zakura :8232
wallet --TLS gRPC--> zainod:8137 --JSON-RPC--> zebrad|zakura :8232
wallet --TLS gRPC--> zainod:8137 --direct----> zebra state dir (same host)

```

Experimental one-process:

```auto
wallet --gRPC--> zebrad :9067 # rpc.lightwalletd_listen_addr, plaintext, #10953
wallet --gRPC--> ztreamerd # embedded Zakura

```

Z3 Compose: Zebra + optional Zaino (`indexer` profile, mainnet gRPC `8137`) + Zallet. Zallet embeds Zaino libraries and talks Zebra JSON-RPC; **external** light wallets still hit standalone Zaino gRPC.

Do not expose zebrad `lightwalletd_listen_addr` or indexer `:8230` to the internet.

## Public CompactTxStreamer endpoints

Check [hosh.zec.rocks](https://hosh.zec.rocks) / [status.zec.rocks](https://status.zec.rocks) rather than a static list. At last write-up:

- `zec.rocks:443` (+ `na/eu/ap/sa.zec.rocks`)
- `zec-node.cakewallet.com:443`
- `zec.0xrpc.io:443`
- `zaino.unsafe.zec.rocks:443` (experimental — the hostname is the warning)
- `testnet.zec.rocks:443`, `zaino.testnet.unsafe.zec.rocks`

Tor hides your IP from these operators. It does not hide the addresses you query. Running your own server is the other trust model.

## Practical pick

- Existing wallet, public or self-hosted server: lightwalletd `:9067` or Zaino `:8137`, TLS off-box.
- New self-host after zcashd EOL: Zebra or Zakura + **Zaino** (Z3 `indexer` profile) or LWD. Both work; Zaino is the funded replacement path.
- One-box Zebra experiment: `rpc.lightwalletd_listen_addr` from [#10953](https://github.com/ZcashFoundation/zebra/pull/10953). Loopback + your own TLS proxy, or don’t.
- One-box Zakura experiment: ztreamer. Don’t point Zashi at it until mempool + transparent behavior match the proto.
- Browser: Envoy gRPC-web in front of LWD or Zaino.
- Building an indexer, not a wallet: Zebra/Zakura indexer gRPC, not CompactTxStreamer.

## References

- Protocol: [GitHub - zcash/lightwallet-protocol: The canonical source of truth for the Zcash light wallet GRPC interface and associated protobuf definitions. · GitHub](https://github.com/zcash/lightwallet-protocol)
- LWD: [GitHub - zcash/lightwalletd: Lightwalletd is a backend service that provides a bandwidth-efficient interface to the Zcash blockchain · GitHub](https://github.com/zcash/lightwalletd)
- LWD `GetTreeState` hash-order bug: [`GetLatestBlock` hash response has been broken for 2.5 years without anyone noticing · Issue #512 · zcash/lightwalletd · GitHub](https://github.com/zcash/lightwalletd/issues/512)
- Zaino RPC list: [zaino/docs/rpc\_api.md at dev · zingolabs/zaino · GitHub](https://github.com/zingolabs/zaino/blob/dev/docs/rpc_api.md)
- Zebrad native CompactTxStreamer: [feat(rpc)!: add lightwalletd-compatible gRPC server implementing CompactTxStreamer by arya2 · Pull Request #10953 · ZcashFoundation/zebra · GitHub](https://github.com/ZcashFoundation/zebra/pull/10953)
- Zebra book (LWD + experimental native server): [Lightwalletd - The Zebra Book](https://zebra.zfnd.org/user/lightwalletd.html)
- Z3: [GitHub - ZcashFoundation/z3: Repository to iterate on the grand unification of Zebra, Zaino and Zallet · GitHub](https://github.com/ZcashFoundation/z3)
- Zakura (node, not LWD): [Introducing Zakura — Zakura](https://zakura.com/announcements/introducing-zakura/)
- ztreamer: [GitHub - distractedm1nd/ztreamer: heavily optimized zcash indexer · GitHub](https://github.com/distractedm1nd/ztreamer)
- ZecHub lightwallet nodes / public servers: [zechub/site/Zcash\_Tech/Lightwallet\_Nodes.md at main · ZecHub/zechub · GitHub](https://github.com/ZecHub/zechub/blob/main/site/Zcash_Tech/Lightwallet_Nodes.md)
- Shielded Labs Zero: [GitHub - ShieldedLabs/zero: Enterprise Zcash · GitHub](https://github.com/ShieldedLabs/zero)

If maintainers want this living somewhere durable (ZecHub page, zebra book appendix), happy to turn it into that next.

---

<div class="post-metadata">

**Author:** ![distractedm1nd](https://sea2.discourse-cdn.com/zcash/user_avatar/forum.zcashcommunity.com/distractedm1nd/32/48255_2.png) [@distractedm1nd](https://forum.zcashcommunity.com/u/distractedm1nd)\
**Post date:** [September 18, 2026, 6:08pm UTC](https://forum.zcashcommunity.com/t/current-ways-to-connect-to-grpc-in-the-zcash-stack-lwd-zaino-zebrad-zakura-ztreamer/57539/2 "2026-09-18T18:08:53Z")

</div>

This is sick, thank you for this!

ztreamer had [another release](https://x.com/distractedm1nd/status/2098657255008706913), but I am still holding out on the next zakura release so I can get rid of my fork.

Do you have any opinions on what a PIR-aware, tachyon ready lightwallet-protocol might need? I have a lot of ideas here I will post about soon. This is what I will want to trojan horse with ztreamer
