NozyWallet Development Roadmap

Hello everyone

sharing a roadblock hit and how, I address it. With how NozyWallet was built, shielded sends were not reliable when the wallet depended only on Zebrad’s JSON-RPC for everything the prover needs (e.g. witness / Merkle-path style data). That stalled proving and was worrying until we mapped it to a concrete fix. We’re aligning the send path with the usual Zcash light-client stack: Zebrad + lightwalletd (gRPC compact blocks) + the wallet’s local Orchard witness / anchor checks against the node (as documented in our tree). I’ll post updates as the code lands.

What’s Done: No reliance on Zebrad position/authpath RPCs for proving; spends use local incremental witnesses + treestate check + local prove; lightwalletd + Zeaking already back compact sync and related tooling.

April was good the goal moving head start improving zeaking witness catch-up from the same compact bytes Zeaking already persists, so shielded send matches a compact-first story end-to-end: lightwalletd as the primary chain-data pipe into SQLite, Zebrad for treestate checks, broadcast, and other RPC that compact does not replace.

Sequencing: We’ve started Zeaking-focused work so the compact layer is dependable at scale; Phase 1 of the roadmap below is done in-tree. Next is Phase 2 (ergonomics across surfaces), then performance/tests/DX as listed. Wiring Nozy’s OrchardWitnessProvider to use LwdCompactStore for witness advancement (instead of or as a fallback to getblock JSON) is explicit planned core work once we’re happy with the compact sync UX and semantics surfaced through Zeaking.

Phase 1 — Reliability & clarity (shipped)

Phase 1 focused on reliable compact sync and clearer errors at the boundaries (Rust crate → HTTP companion → desktop → FFI → extension).

zeaking (crate)

  • connect_lightwalletd: fixed a move-after-use bug by cloning the URI for the error path (lwd/client.rs).

  • Streaming (GetBlockRange): stream errors now go through map_grpc_status so callers get structured gRPC Status (code / message) instead of treating them like generic transport failures (lwd/sync.rs).

  • Public API: SyncCompactOptions, SyncCompactStats, sync_compact_range_with_options, and compact_sync_progress_height are re-exported from lwd/mod.rs.

Companion HTTP (api-server)

  • POST /api/lwd/sync/compact: optional JSON body field resume (same semantics as SyncCompactOptions.resume_from_store).

  • Response: range_start_requested, range_start_effective, range_end, blocks_written (replacing the old single range_start field).

  • HTTP status mapping (via zeaking_status): Grpc → 502, Storage → 500, InvalidOperation → 400.

Desktop (Tauri)

  • lwd_sync_compact: optional resume on the request struct.

  • Response: range_start_requested / range_start_effective / range_end (replacing range_start).

  • zeaking_err: distinct codes LWD_GRPC, LWD_STORAGE, LWD_INVALID where applicable.

UniFFI (zeaking-ffi) — breaking for generated bindings

  • lwd_sync_compact: new argument resume: Option<bool> (last parameter).

  • LwdSyncResultFfi: range_start replaced by range_start_requested and range_start_effective. Regenerate Kotlin / Swift after upgrading the dylib.

Browser extension

  • Companion sync can pass resume: true from companion-api.js; extensionApi.ts typings updated.

  • Defaults stay safe: resume is off unless explicitly set; sync_compact_range unchanged for callers that do not opt in.

How we validated

  • cargo build --workspace

  • cargo build in desktop-client/src-tauri

  • cargo test

  • cargo test -p zeaking --features lightwalletd

  • cargo fmt --all -- --check

ZecHub have an hackathon coming up Nozywallet will be a submission. Great time to show the community Nozy before submission in a retroactive grant, I still more work to do.

1 Like