Enabling
Zcash is opt-in. Thezcash feature exists on parser_app, parser_http_server and parser_cli, but it is not in any of their default feature sets, and the parser_app and parser_http_server images do not list it in CHAIN_FEATURES. Build with --features zcash, or pass --build-arg CHAIN_FEATURES="... zcash" to an image build. The visualsign-zcash library crate is a workspace member and is built and tested in CI regardless.
Input
- Encoding: PCZT bytes as hex (optional
0x) or base64. Both the v1 and v2 PCZT encodings are accepted. - Resource limits: up to 4 MiB of PCZT bytes and 64 total Sapling outputs plus Orchard and Ironwood actions. Zero-value padding counts toward the same shared limit. The parser checks the count immediately after deserialization, before canonical re-encoding, sighashes, commitment checks, note recovery, or rendering. Note checks and recovery require cryptographic work per output; the separate count budget keeps that work bounded while allowing batch payments with dozens of recipients. These are parser resource policies, independent of Zcash consensus limits; they do not guarantee a fixed execution time. Transparent bundles are bounded separately: at most 600 inputs (per-input ZIP-244 sighashes re-hash every input, so cost grows quadratically) and 2,900 outputs, about zcashd’s 100,000-byte standard transaction size. Repeated previous outputs are refused, each input shows its outpoint, and any sum above 21,000,000 ZEC is refused.
- Canonical bytes only: re-encoding the parsed PCZT under its own version must reproduce the input exactly, so trailing data and non-canonical encodings are refused.
- Declared network (unsigned): taken from the PCZT’s coin type (133 mainnet, 1 testnet). Neither the coin type nor the network-specific address prefixes are authenticated by a sighash. Confirm the network independently; there is no caller network pin. There are no Zcash-specific CLI flags.
What is checked without a key
- Outputs: each shielded output’s recipient, value and
rseedmust reproduce its note commitment, which the ZIP-244 sighash commits to. Redacted outputs and nonzero outputs whose ciphertext cannot be recovered from their note fields are refused. This prevents displaying an undetectable note as a payment. - Memos: recovered from each output’s own note fields. The sender-side ephemeral secret derives from
rseed, so no viewing key is needed. Non-ASCII text memos are shown as their UTF-8 bytes in hex. - Value balance: per pool, the value spent is the committed value balance plus the outputs. Spend values stated in the PCZT must add up to the same total.
- User addresses: a
user_addresson an output must decode for the PCZT’s network and contain the output’s receiver. The address shown for the output is always the receiver actually paid, encoded from the output itself; theuser_addressis shown separately as an unsigned hint. A Unified Address expiry height must be at least the transaction expiry height, and an address with a height limit requires a nonzero transaction expiry. Address expiry times are displayed as Unix seconds and are not checked because the parser has no clock. TEX recipients are refused when any shielded pool spends a nonzero amount. - Fee: transparent in minus transparent out plus the shielded value balances, compared with the ZIP-317 conventional fee. The ZIP-244 sighashes commit to transparent input amounts. Transparent signers must use their per-input digest.
- Sighashes: the ZIP-244 shielded digest and one digest per transparent input are returned. The transparent digests use the signer’s
ALL_ONLYpolicy:NONE,SINGLE, andANYONECANPAYare refused. A signing wallet must use the digest for the input it signs.
What needs a key, and is marked
Without a viewing key the parser cannot tell which spends belong to the signer or which outputs are change. Spends are shown as per-pool totals with “spend ownership unverified (parser has no viewing key)”. Every output is listed, including change, and aChange field says change is unverified. A BIP 32 derivation on a transparent output is unsigned, so it earns no change badge.
Zero-value outputs whose memo is empty or does not decrypt are padding (ZIP 326 same-address outputs carry random ciphertexts) and are counted in Padding outputs.
Pools
Using parser_cli
Dependencies
The crate pins the librustzcash pre-release line (pczt =0.10.0-pre.2, zcash_primitives =0.31.0-pre.2, zcash_keys =0.17.0-pre.2, orchard =0.16.0, sapling-crypto =0.9.0). This is the line with v6 transactions, the Ironwood pool and the v2 PCZT encoding. No circuit or prover features are enabled.
Hash validation
The test suite pins 10 upstream ZIP-244 v5 known-answer vectors and 18 independent candidate v6/Ironwood vectors from zcash-test-vectors PR #130 at commit5eb4b7eba44485b18bfffd6bf6928343b485540f. The v6 vectors are from an open, unmerged proposal. They check raw-transaction txid, auth digest, and shielded sighash; they do not independently validate PCZT extraction or rendered field mapping. The PCZT-to-field comparison is an integration mapping test using the same signer implementation.