Release: Zakura 1.8.0

Zakura 1.8.0 release art on dotted paper: the pink zakura flower logo beside 1.8.0 in large ink numerals. Along the bottom, two outlined blocks wait at a gate, a rejected block tumbles away below it, and an admitted pink block trailing speed lines races toward a dashed open slot at the head of a chain of ink blocks receding into a pale pink disc.Zakura 1.8.0 release art on dotted night ink: the pink zakura flower logo beside 1.8.0 in large cream numerals. Along the bottom, two outlined blocks wait at a gate, a rejected block tumbles away below it, and an admitted pink block trailing speed lines races toward a dashed open slot at the head of a chain of cream blocks receding into a plum disc.

We have released Zakura 1.8.0, a security and stability release. It removes unnecessary dependencies, reducing supply chain risk and making our release downloads smaller. This builds on the reductions we already shipped in 1.7.0. We also made significant performance improvements to block announcement and validation.

NU7 activates on Mainnet in about three days, but there is no rush to update to 1.8.0 if you are already running 1.7.0. Updating early is fine too, and gets these improvements onto the network sooner.

Fewer Dependencies

Zakura's dependency lock file lists 341 packages, down from 350 in 1.7.0.

  • The Prometheus metrics endpoint is now in-tree, replacing metrics-exporter-prometheus. Metric names and the output format are unchanged. Histogram quantiles also become more accurate: they now reflect every sample from the last minute, where the previous exporter lost samples recorded before a histogram's first scrape.
  • Building Zakura no longer requires libclang. The RocksDB bindings are no longer generated at build time, removing a system prerequisite we introduced in 1.1.1.
  • The bundled RocksDB is compiled without features Zakura never uses, such as SST file ingestion and remote compaction. This leaves out more than 500 KB of code and shortens clean builds; RocksDB's behavior and the on-disk database format are unchanged.
  • The indexer gRPC server is now a build-time choice. Default and release builds still include it, and a build without the new indexer-rpc feature drops the gRPC dependency tree entirely.

Faster Block Announcements

New blocks are announced to peers up to about 110× faster. In a two-node benchmark measuring the time from a block mined on one node to the other node building a block template on it, the median fell from 833 ms to 7.5 ms, statistically indistinguishable from Zebra 7.0.0 on the same setup.

The old median was a worst case for a quiet node: an announcement could sit behind an unanswered block-discovery request until that request's six-second timeout, and most samples did. Announcements now go out on their own queue, adopting the announcement design Zebra uses.

The effect is already visible on Mainnet. After a mining pool upgraded its sending node to Zakura 1.8.0-rc.1, the median time from the pool submitting a block to our nodes accepting it fell by about half, and the slowest deliveries by about three quarters (16 blocks before, 13 after, across three receivers):

Before upgradeAfter upgrade
Median delivery delay, across three receivers1.15 to 1.56 s0.63 to 0.69 s
Slowest observed delivery7.44 to 7.55 s1.35 to 1.91 s

With NU7 tripling the block rate, these delays would have occurred three times as often. The related changes:

  • Blocks no longer queue behind earlier announcements. Newly mined or received blocks previously waited for an earlier block's announcements to finish; each block's announcements now start immediately.
  • Quiet connections answer immediately. When its mempool is empty, the node now replies to inventory requests with an empty list instead of letting them time out. This removes block relay delays of up to six seconds for sparsely connected nodes.
  • Announced blocks download at once. Blocks announced while the node waits on a discovery reply from the same connection download immediately instead of after the full discovery round. Gossiped blocks that arrive before their parent request the missing parent right away, after a proof-of-work check, instead of waiting for the next sync round.
  • Announcement peers stay current. The peers selected for legacy block announcements are refreshed while the node is idle, and announcements retry against fresh peers when a selected connection becomes unusable.
  • Local transactions reach block templates sooner. sendrawtransaction and other local submissions no longer wait an extra 50 ms per transaction before the verified transaction enters the mempool and block templates.

Faster Block Validation

Verifying new blocks and accepting mined ones is faster across every block type we benchmark; the comparison section below puts the numbers next to Zebra's. The changes:

  • Accepting a block built from the node's own template takes about half as long. In our benchmarks, a 1.9 MB block drops from 375 ms to under 200 ms. The node no longer logs every transaction during the commit, reads output addresses straight from their scripts, skips the Merkle check for a template it already validated, and reuses the template's transactions instead of parsing them again. Miners start building on their own blocks sooner.
  • Verifying a block the node has never seen takes up to 34% less time. In our benchmarks, a 1.9 MB transparent block drops from 2.14 to 1.41 seconds, and a mixed block from 882 to 742 ms. Transaction results are collected without being throttled by the async runtime, and Orchard proof batches are prepared on blocking threads instead of the workers that admit transactions, which makes Orchard blocks verify in about 11% less time.
  • The Common libraries are updated to 5.0.0, with faster Groth16 proof and RedDSA signature batch verification and faster parsing of Sapling proofs.
  • Per-block overhead falls 3 to 5% on every block. Verification no longer recomputes each transaction's ID for its signature hashes, network upgrade lookups no longer rebuild their tables, parent-input checks overlap their reads, and block commits no longer open a tracing span per transaction. getblocktemplate also uses about 10% less CPU.
  • Transactions use less memory. Sprout, Sapling, and Orchard bundles move out of every transaction's inline representation.

Comparing With Zebra Ándale

The Zcash Foundation recently released Zebra Ándale, a performance build for miners and mining pools, with benchmarks comparing it to Zakura 1.7.0. Congratulations to the Zebra team on the release.

On everyday Mainnet blocks, the two nodes are close. The Foundation's live dashboard feeds every new Mainnet block to each node and times its acceptance. Over the 24 hours to November 2 (1,154 blocks), Zakura 1.7.0 accepted a block in a median of 6.7 ms against Ándale's 5.9 ms, a difference of under a millisecond, while Zebra 7.0.0 took 119 ms.

The Zebra team's benchmarks also exercise more demanding cases, such as large synthetic blocks sent to nodes with no peers and empty mempools, where every proof is checked inside the block rather than earlier in the mempool. Those cases were a useful stress test for us, and they pointed to several improvements in this release.

The biggest one was in block announcements. The announcement of a new block could wait behind a busy connection, which slowed how quickly a peer learned about a block and built new work on it. That is fixed in 1.8.0. On the Zebra team's tip-to-template benchmark, run on our hardware, the median fell from 833 ms to 7.5 ms. Thanks to the Zebra team for publishing their benchmark harness, which made this easy to find and confirm.

Before the announcement fix833 msZakura 1.8.07.5 ms0300600900 ms
Median time from a mined block to a connected peer building new work, measured on the same two-node benchmark. Lower is better.

Running the same harness against Ándale, block propagation is now measured in milliseconds on both nodes, and Zakura is the more predictable of the two. When a peer learns of a new block over a fresh connection, Zakura 1.8.0 builds new work on it in a median of 61 ms, and never took longer than 106 ms across 18 runs; Ándale's median was 71 ms, with its slowest run at 2 seconds. Empty solved blocks reach a peer in 14 to 103 ms on Zakura and 21 to 92 ms on Ándale. On a quiet, settled connection and on a node's own block, both nodes build new work within about 12 ms.

The propagation results below are medians of repeated runs, with the fastest and slowest run in parentheses. Both nodes were measured on the same machine in the same session for each row, and where a table marks both nodes, the difference between them was smaller than the run-to-run spread.

Zakura 1.8.0Zebra Ándale
New work after a peer's block, fresh connection61 ms (12–106)71 ms (13–1,998)
Same, settled connection12 ms (10–15)5.5 ms (4–16)
New work after the node's own block4.2 ms (3–8)1.6 ms (1–2)
Relaying an empty solved block to a peer62 ms (14–103)46 ms (21–92)

Additionally, we replayed 32,860 consecutive Mainnet blocks, about four weeks of chain, into Zakura 1.8.0 and Zebra Ándale on the same 8-vCPU cloud server, with both nodes fully verifying and committing every block. Zakura was 2.5× faster, 461 seconds against 1,141, using under a quarter of the CPU time:

Zakura 1.8.0Zebra Ándale
Average time per block14.0 ms34.7 ms
Median time per block12.7 ms26.2 ms
99th percentile time per block81 ms367 ms
Slowest block396 ms1,106 ms
Blocks verified faster32,368 (98.5%)492 (1.5%)
CPU time for all blocks1,382 s5,632 s

Shielded blocks verified 2.6× faster, and Ándale's slowest 1% of blocks 5.3× faster. Each node replayed the blocks three times with no peers and empty mempools, so every proof was checked inside its block.

Zakura also leads where pools feel load most: turning a burst of incoming transactions into a block template. With 1.9 MB of transparent transactions arriving at once, Zakura 1.8.0 had them in a template in 19.0 seconds, 38% less time than Ándale's 30.9, and its slowest run beat Ándale's fastest.

Zakura 1.8.0Zebra Ándale
Transaction burst to block template, transparent19.0 s (18.3–19.2)30.9 s (29.9–31.1)

We are glad to be improving Zcash alongside the Zebra team.

Coming Next

  • Accepting a block built from the node's own template catches up with Ándale. The node also reuses the template's spend checks, value-pool change, and body hash: a mixed block takes 75 ms against Ándale's 76 ms, and an Orchard block 41 against 46 ms.
  • Transparent signature checks take about 29% less time on transparent blocks. They stop computing data they never use, such as the v5-only digests and the transaction-wide hash for transactions with no shielded components. New transparent blocks verify in 822 ms, down from 988 ms in 1.8.0.
  • Shielded blocks verify in 6 to 32% less time. Shielded transactions are dispatched to verification first, a partially filled proof batch flushes after five idle milliseconds, and Orchard batches grow to 128 actions. New 250 kB mixed blocks verify in 63 ms, down from 93 ms in 1.8.0.

With that work, relaying a mixed block takes 1,026 ms, down from 1,203 ms in 1.8.0, and a new mixed block verifies in 497 ms, down from 537 ms.

Faster Field Arithmetic on x86-64

Published x86-64 binaries previously used portable Pasta field arithmetic so they could run on any x86-64 CPU. Default and release builds now enable the faster BMI2 and ADX assembly, with no per-operation runtime detection.

zakurad checks the CPU once at startup and exits with an error naming the missing extensions, instead of crashing with an illegal instruction. Intel CPUs since 2014 and AMD CPUs since 2017 have both; older CPUs can still build with --features portable.

Security

  • Decoded blocks can no longer pile up in memory. In our experimental P2Pv2 stack, a slow verifier could leave hundreds of decoded block bodies queued between download and submission. Queued bodies now count against the same 512 MiB decoded-block budget we shipped in 1.7.0; past it, blocks wait as raw bytes and are decoded when submitted. A block at the chain tip is still decoded only once.
  • Recent block downloads must claim real work. As defense in depth, Mainnet block sync now refuses to download a recent block whose header claims less than a minimum proof-of-work difficulty, so floods of low-difficulty announcements cannot occupy download capacity. Historical sync is exempt only below height 3,535,411, and only while the node's committed tip is also below it: full verification from genesis still works, and old height claims cannot bypass the floor.
  • The native protocol rejects more malformed traffic. Stream preludes whose frame cap cannot carry a payload are refused, a frame that does not fit its stream no longer closes the whole connection, and a handshake acknowledgment cannot accept a capability the dialer never offered.

Other Changes

  • zcashd compatibility mode pins zcashd v1.3.1, fixing sidecar sync stalls after out-of-order block announcements.
  • z_gettreestate answers below the prune height. Pruned nodes now return the note commitment tree state for heights whose bodies pruning has dropped.
  • getblocktemplate judges sync by the clock. It reports "not synced" only when the chain tip's block time is more than six hours old. The threshold was a block count, which would have shrunk when NU7 shortens block spacing.
  • getpeerinfo reports startingheight, the best chain height each peer advertised when it connected, as zcashd does.
  • Metrics are more accurate. Histogram quantiles no longer lose samples recorded across a window boundary, the metrics endpoint's /health response is OK again, and five new gauges report block-sync memory use by stage.
  • tracing.filter applies only level and target directives. Span and field directives are now ignored with a warning instead of being applied, and rustls log records no longer appear in zakurad logs.
  • Our experimental P2Pv2 stack's block sync recovers from more failure modes. Stalls after resets, reorgs, and peers without latency measurements are fixed, memory accounting survives resets, and checkpoint sync recovers retained commitment-tree data at a blocked commit boundary instead of waiting for more headers. Discovery also no longer times out connections whose peers already answered.
  • Custom testnets accept compatible peers using the active network upgrade's protocol version.

End of Support

Mainnet zakurad nodes running 1.8.0 support Mainnet through height 3,643,309 and halt above it (estimated 2026-12-05); upgrade warnings begin three days earlier.

Updating

You can update using our signed release binaries or by upgrading the zakura crate to 1.8.0 via Cargo. See the download page for installation and verification instructions.