The Problem: Light wallet sync and recovery is slow and doesn’t handle interruptions well. Users on unstable connections often have to restart downloads, and there’s no cryptographic verification that downloaded data is correct.
The Solution: Bao (built on BLAKE3) enables streaming verification - every chunk of data can be verified against a known hash, downloads can resume from any point, and chunks can even arrive out of order. This is perfect for wallet recovery.
What I’m Building:
Snapshot generator: Export tree states/compact blocks as Bao-encoded files
Verification library: Browser-compatible streaming verifier with resume support
Community snapshots: Hosted verified snapshots for immediate use
Why Me: I’m the author of blake3-bao, a pure JavaScript BLAKE3 + Bao implementation with WASM SIMD acceleration achieving ~1500 MB/s hashing and ~185 MB/s Bao encoding. It includes full Iroh-compatible chunk groups, resumable downloads via PartialBao, and 1,158 passing tests.
I’d love feedback from wallet developers on what data formats would be most useful to support. Looking forward to your thoughts!
Thanks hanh - appreciate the expertise from a wallet developer.
You’re right about lightwalletd’s GetBlockRange API. I should clarify what this tool actually does differently:
Tree state snapshots, not compact blocks - For initial wallet sync, you need the commitment tree frontier. This tool Bao-encodes tree states so wallets can get a verified starting point without downloading all historical compact blocks.
Resumable HTTP downloads - gRPC streams restart from zero if connection drops. Bao encoding enables chunk-level resume via HTTP range requests.
Browser compatibility - Harder to use gRPC in browsers. This serves over plain HTTP with CORS.
On trust: you’re absolutely right that verifying against a hash shifts trust to the hash publisher. The model is multiple community servers publishing snapshots - users can cross-verify. Not trustless, but trust-distributed.
Question for you: For the tree state frontier specifically (Sapling/Orchard commitment trees), is there an existing lightwalletd API that provides this? Or do wallets currently rebuild it from compact blocks?
GetTreeState RPC - Good to know, I wasn’t aware lightwalletd exposed this. My tool fetches from zcashd directly via z_gettreestate.
Resume from checkpoint - Makes sense for wallet DBs. The difference is Bao enables resume from any HTTP server without trusting it. Failed chunk? Fetch from a different mirror, verification still works.
Snapshot contents - Currently just the tree state (height, hash, Sapling/Orchard frontiers) serialized to JSON, then Bao-encoded. The value isn’t the data - it’s the delivery mechanism: static HTTP files that can be cached on CDNs, served from untrusted mirrors, verified chunk-by-chunk, resumed from any byte offset.
Honest question: Is there a use case for distributing tree states outside the lightwalletd trust model? For example, multiple community mirrors where users verify rather than trust?
If it’s just for the tree state, I’d retrieve it from lwd (or use a hardcoded checkpoint hash and compute from there). The wallet only needs when the account is created.
Fair point - if tree states are small and one-time, the resume/multi-mirror benefit is minimal there.
Where do you see the actual download bottleneck in wallet sync? Is it compact blocks? If so, would Bao-verified compact block distribution be more valuable?
Trying to find where cryptographic verification of untrusted CDN/mirror delivery would actually help the ecosystem.
Demo: Bao Resumable Downloads from Untrusted Sources
Built a demo showing what current lightwalletd can’t do: resumable, verified downloads across multiple untrusted servers with malicious server detection.
Run it yourself:
git clone https://github.com/lamb356/zcash-bao-snapshots.git
cd zcash-bao-snapshots
npm install
npx tsx examples/resume-demo.ts
Output:
╔══════════════════════════════════════════════════════════╗
║ Bao Resumable Download Demo ║
║ Demonstrating verified downloads from untrusted sources ║
╚══════════════════════════════════════════════════════════╝
PHASE 1: Download from Server A (until 50%)
[██████████░░░░░░░░░░] 50% - Group 2/4
⚠️ Connection failed at 50%
Saving verifier state...
PHASE 2: Resume from Server B
[███████████████░░░░░] 75% - Group 3/4
✅ Downloaded group 3 from Server B
PHASE 2.5: Test Malicious Server C
⚠️ Server C sent corrupted data - verification failed!
Fetching from backup...
[████████████████████] 100% - Group 4/4 (from Server B)
✅ Verification complete! Data integrity confirmed.
🔒 SECURITY DEMONSTRATION:
- Server A could have been compromised after Phase 1
- Server C actively attempted to inject corrupted data
- Yet the final data is cryptographically verified
- Only the root hash (32 bytes) needs to be trusted
COMPARISON: Traditional gRPC vs Bao HTTP
Traditional lightwalletd:
❌ Connection drop → restart from 0%
❌ Must reconnect to SAME server
❌ Malicious server → corrupted data accepted
Bao Verified Streaming:
✅ Connection drop → resume from 50%
✅ Can switch to ANY server
✅ Malicious server → corruption detected and rejected
You’re right, tree states are small. The demo shows the mechanism, but the real value is for larger data.
Would Bao-verified streaming make sense for compact blocks (~5GB)? That’s where resumability and CDN distribution would actually help.
Community reminder, this is an early stage grant application. Please don’t run or provide keys to unverified code. Stay safe . Thank you .
Ephemeral Docker container
docker run --rm -it node:20-alpine /bin/sh
# Install git (Alpine container doesn't have it by default)
apk add git
# Clone and run entirely inside the sandbox
git clone https://github.com/lamb356/zcash-bao-snapshots.git
cd zcash-bao-snapshots
npm install
npx tsx examples/resume-demo.ts
Hey hanh — thanks again for the concrete feedback. You were right: if the snapshot is only the tree state frontier, it’s too small for resumability/mirror-failover to matter, and fetching it from GetTreeState is the obvious path.
I’d like to pivot the proposal to something that does fit Bao’s strengths: CDN-hosted, Bao-verified archives of historical compact blocks by height range (still in-order; no “out-of-order blocks” pitch). The goal wouldn’t be to replace lightwalletd, but to offload bulk historical downloads to static mirrors while wallets still use lightwalletd for tip + normal RPC flow.
Two quick questions to sanity-check usefulness:
Would YWallet (or wallets in general) benefit from retrieving large historical compact block ranges over plain HTTPS (range requests) with resume + mirror failover, instead of gRPC streaming?
If yes, what interface would be least disruptive: (a) a standalone “block-archive URL + root hash” config, or (b) a lightwalletd extension that can advertise archives for older ranges?
If you think this is still not solving a real problem, what large artifact in the sync/recovery path is the best candidate for “static verified distribution”?
Thank you for submitting your proposal. Following a thorough review by the ZCG and a period for community feedback on the forum, the committee has decided not to move forward with this proposal.
We sincerely appreciate the time and effort you invested in your application and encourage you to stay involved and continue contributing to the Zcash community.
Thanks for the response. I’d appreciate more specific feedback on why this was declined — the generic response doesn’t give me much to work with for future submissions.
A few questions:
Was this a prioritization decision (not important enough right now) or were there technical/scope concerns with the proposal itself?
What would have made this stronger? Wallet developer commitment upfront? Different scope?
The timing is a bit confusing — hanh posted technical integration questions about the PoC just before this rejection. Is there misalignment between committee priorities and what wallet devs actually want?
I built a working proof-of-concept, wrote comprehensive documentation, and proposed a modest budget with clear milestones. If that’s not enough, I’d genuinely like to understand what the bar is.
Happy to take this feedback into any future proposals.