This is a security fix release that includes some additional features and improvements, in particular for miner users.
This releases reduces the end of support height to approximately Nov 2nd, 2026, in preparation for NU7 (tentatively scheduled for Nov 5th, 2026). We acknowledge that reducing the end of support height is not ideal and can cause the risks of some nodes not being upgraded on time, but we believe this risk can be minimized with partner outreach. We do not want this to become a common procedure in the future.
Please ensure you upgrade to 6.4.0 before Nov 2nd to ensure you do not accidentally miss the upgrade window; the next release of Zebra should support NU7.
Added
- Add metrics
zcash.pool.value.zatoshis(labeled by pool name) andzcash.pool.notes.created(labeled by pool name) reporting value pool balances in zatoshis and note commitment counts at the non-finalized chain tip (#11391) - Zebra can now serve Zcash light clients directly: a new experimental gRPC server implements the lightwalletd
CompactTxStreamerinterface, enabled by settingrpc.lightwalletd_listen_addrin the config (#10953).
Changed
rpc.max_response_body_sizeis now limited to 4,294,967,295 bytes. Configurations with larger values must reduce the limit; they are rejected during configuration loading instead of causing an RPC server startup panic (#11259).- Updated the
nixdependency to 0.31 (#11267). - Block template construction now caps the ZIP-317 fee weight ratio at 10 instead of 4, widening the priority lane for transactions that pay more than their conventional fee (#11290).
- Zebra no longer includes the unmaintained
ordered-mapcrate or its legacyquickcheck0.9 andrand0.7 dependency subtree (#10516). - Peer connection limiting is now applied per IPv6
/64subnet instead of per individual IPv6 address, so one machine can no longer bypassnetwork.max_connections_per_ipby connecting from many addresses in the same/64allocation. IPv4 connections are unchanged, and are still limited per address (#11255). - The
getblocktemplateRPC uses a precomputed block template for the current chain tip when one is available, rather than assembling one while the miner waits. Zebra precomputes templates when a miner address is configured and either the RPC server or the internal miner is enabled, refreshing them on chain tip changes and every few seconds, so a template can be a few seconds behind the mempool, but each template is checked against the committed tip. Cached work is also refreshed when Testnet difficulty becomes easier. Tip changes do not accumulate unfinished coinbase proofs (#11370). - Peer bans now expire after 24 hours instead of lasting until Zebra restarts, so a peer banned by mistake — or one sharing an IPv6
/64with a misbehaving peer — is not shut out permanently (#11255). - When two competing chains have equal cumulative work, Zebra now prefers the chain whose tip block it received first, as specified by the Zcash protocol, instead of the chain with the greater tip block hash (#11341).
- The mempool now accepts transactions that pay at least 1000 zatoshis per ZIP-317 logical action instead of 5000 (2000 instead of 10000 for a minimal transaction), block template weights follow the new conventional fee, and
getstandardfeereports 1000, per zcash/zips#1352 (#11290). - The end-of-support halt time is now 12 weeks instead of 15 weeks, moving this release's halt to early November 2026 (#11491).
- Zebra caches Orchard, Ironwood, and Sapling bundle verification results, so a proof or signature verified when its transaction entered the mempool is not verified again when the block that mines it arrives. The cache is reported by the new
zebra.consensus.cache.*metrics (#11380).
Fixed
- Zebra no longer runs a shielded coinbase proof for each outstanding
getblocktemplatelong poll when the configured miner address has a shielded component (#10747). - The syncer no longer restarts when a block's transparent input lookup times out near the tip, or when the short post-checkpoint verify timeout fires. Both are transient UTXO races, and restarting cancelled the in-flight parent commit, causing a sync restart loop (#11168, #11132).
- The
zcashd_source = "embedded"sidecar is now pinned tozebra-compat-v1.2.0, which raises the zcashd reorg limit from 99 to 1000 blocks to match Zebra'sMAX_BLOCK_REORG_HEIGHT. The previouszebra-compat-v1.1.0sidecar shut itself down on any reorg deeper than 99 blocks while Zebra kept following the chain. Wallets holding shielded notes should expect the witness cache andwallet.datto grow roughly 10x, reached gradually over about 900 blocks (#11403). - The
docker-split-containersmode ofscripts/install-zebra.shnow prints a zcashd container command that can run. It defaulted to a zcashd Docker image that was never published; it now runs the hash-pinned sidecarzcashdfrom the Zebra image, downloading and verifying the binary on the host and bind-mounting it in. Pass--zcashd-docker-image IMAGEto use your own image instead (#11413). - Build
librocksdb-syswith bindgen'sruntimefeature, so libclang loads correctly when more than one bindgen version is resolved (#11444). z_gettreestateno longer returns null commitments for a block it found when a concurrent reorg moves that block onto a side chain (#10820).- The mempool now frees a peer's download slot when a transaction from that peer times out during verification. Before, each timeout permanently used up one of the peer's slots, until the mempool rejected every further transaction from that peer as a full queue (#11229).
Security
-
Score misbehavior for peers that advertise a block containing duplicate transactions, matching the treatment of the other definitive block-validity violations (#11157).
-
Penalize coinbase scriptSig rewrite in inbound path (GHSA-4f6v-mj46-gxg3). Thanks to @craftsoldier for reporting the issue.
-
Misbehaving peers can no longer avoid being banned by reconnecting from a different address in the same IPv6
/64allocation: bans now apply to the whole peer group (#11255). -
The syncer no longer restarts its sync round when a peer serves a block body whose authorizing data does not match the header commitment. The failure was an ordinary
Invalidverification error, so it cancelled the round and idled the syncer forSYNC_RESTART_DELAY, and the block hash was dropped instead of being re-requested. The hash is canonical and only the served body was forged, so the syncer now continues the round and re-requests the body from another peer, bounded byMAX_BLOCK_REOBTAIN_RETRIES. Blocks the state rejects because they were queued behind a forged body are re-requested the same way, without scoring the peers that served them (GHSA-3c94-hf7p-g5mf). Thanks to @ouicate for reporting the issue.
Contributors
Thank you to everyone who contributed to this release:
@Bortlesboat, @CodeMongerrr, @LarryRuane, @alchemydc, @andres-pcg, @aphelionz, @arya2, @conradoplg, @craftsoldier, @evan-forbes, @gustavovalverde, @jiehuo100net, @john-lawniczak, @mpguerra, @natalieesk, @oxarbitrage, @questfever, @robustfengbin, @str4d, @syszery and @upbqdn