the wallet. derives orchard spending keys and transparent keys from an ssh
ed25519 seed via BLAKE2b-512("ZcliWalletSeed" || ed25519_seed).
trial-decrypts compact blocks locally — the server never learns which
addresses belong to you. builds and proves orchard transactions with halo2
locally.
the backend. indexes the zcash chain into
nomt and generates
ligerito proofs over the header
chain (gigaproof + tip proof). serves compact blocks and proofs over
gRPC-web. default endpoint: zcash.rotko.net.
shared verification library. ligerito proof verification, nomt merkle proof verification, actions commitment chain, trial decryption. used by both zcli and zafu.
zcli verifies chain data before trusting it. nothing from the server is
accepted without cryptographic proof. run zcli verify to see
the full chain:
$ zcli verify
zcli verify - trustless verification chain
network: mainnet
endpoint: https://zcash.rotko.net
tip: 3266078 (000000000075b2db)
1. trust anchor
hardcoded orchard activation hash at height 1687104
server returned: 0000000000d72315
expected: 0000000000d72315
PASS
2. cross-verification (1 independent node)
https://zec.rocks - tip matches
consensus: 1/1 agree (threshold: >2/3)
PASS
3. header chain proof (ligerito)
gigaproof: 1687104 -> 3265535 (1578432 headers, 452 KB)
gigaproof anchored to activation hash: PASS
gigaproof cryptographic verification: PASS
tip proof: 3265536 -> 3266078 (543 headers)
tip proof cryptographic verification: PASS
chain continuity (tip chains to giga): PASS
total blocks proven: 1578974
4. cryptographically proven state roots
(extracted from ligerito polynomial trace sentinel row)
tree_root: b375422028a896ed...
nullifier_root: 512ab0f1f95c751e...
actions_commitment: 18001392bc7a253b...
proof freshness: 0 blocks behind tip
all checks passed
the orchard activation block hash (height 1,687,104) is hardcoded in the
binary. every proof chain must start from this immutable anchor. the
gigaproof's start_hash is checked against it.
tip block hash is compared against independent lightwalletd nodes
(default: zec.rocks, configurable via --verify-endpoints).
requires BFT majority (>2/3 agreement). hard-fails on mismatch or
when no nodes respond.
the gigaproof (~300KB) covers the header chain from NU5 activation to the latest epoch boundary. the tip proof (~150KB) covers from there to the current tip, regenerated every block. both are verified cryptographically and must chain continuously.
the ligerito proof commits to a polynomial trace containing a sentinel row with three state roots. these are cryptographically bound to the proven header chain — the server cannot forge them.
the sentinel row in the ligerito trace contains:
tree_root orchard commitment tree root (nomt) nullifier_root nullifier set root (nomt) actions_commitment running chain of per-block action merkle trees
during zcli sync, each received note gets a nomt merkle proof
verified against the proven tree_root. each unspent nullifier
gets a nomt proof against the proven nullifier_root. the
client recomputes per-block action merkle trees and chains them — the
result must match the proven actions_commitment. after trial
decryption, cmx is recomputed from the decrypted note and compared to the
server-provided value. notes are only stored after all proofs pass.
all verification hard-fails. no soft-fails, no warnings-instead-of-errors.
at least one of your cross-verification endpoints must be honest about the chain tip. if all endpoints collude and serve a forked chain, no light client can detect this. this is fundamental to all light clients.
zcli -i ~/.ssh/id_ed25519 address # show addresses zcli sync # scan chain zcli balance # check funds zcli send 0.01 u1... # send shielded zcli shield # t-addr → shielded zcli receive # QR code zcli notes --json # list received notes zcli export # export viewing key zcli board --port 3333 # sync loop + JSON API
all commands accept --json for machine-readable output.
set ZCLI_IDENTITY, ZCLI_ENDPOINT as env vars for headless operation.
zcli import-fvk --cam # scan FVK QR from zigner zcli sync --wallet zigner # sync watch-only wallet zcli balance --wallet zigner # check balance zcli send 1.0 u1... --wallet zigner --cam # build unsigned tx, scan signed QR
see zigner.rotko.net for the hardware signer.
ZCLI_IDENTITY path to ed25519 ssh key (default: ~/.ssh/id_ed25519) ZCLI_ENDPOINT gRPC-web endpoint (default: zcash.rotko.net) SSH_PASSPHRASE key passphrase for non-interactive use