github zakura-core/zakura v1.8.8

pre-release37 minutes ago

Bounded peer replies, steadier connections, and faster mempool cleanup. We recommend upgrading.

Supported on Mainnet until block 3,643,309, around December 3, 2026. Upgrade warnings start about three days earlier.

Before you upgrade

  • network.unconditional_peers now dials peers. Listed single addresses are now dialed and reconnected automatically, with extra connection slots reserved for them. Review existing entries, since previously passive entries now cause outbound connection attempts (#2389).
  • Monitoring labels and refresh intervals. zakura.net.in.errors's error and mempool.failed.verify.tasks.total's reason now use error kinds; update matching alerts. zakura.state.rocksdb.* gauges and size_on_disk now refresh every 5 minutes, not every 30 seconds (#2439, #2475).
  • Custom-network consensus and mempool policy. Custom NU7 chains using the previous payout rule need coordinated deployment and a reset or explicit migration. Sprout JoinSplits are now rejected by mempool policy even on custom pre-NU7 networks (#1591, #2471).
  • Peer service flags in getnetworkinfo. Experimental: pruned nodes advertise NODE_PRUNED. NODE_NETWORK advertising is restored, and getnetworkinfo reports actual localservices; update consumers that assume fixed service flags (#2382).

Highlights

  • Security: a peer's getblocks reply now keeps at most 500 block hashes, preventing one peer from making the syncer process up to 50,000 hashes per response (#2437).
  • Startup makes up to 50 peer connection attempts at once, uses cached peers when all seed DNS lookups fail, and prioritizes peers that responded in the last 3 hours (#2396, #2399, #2404).
  • Lower CPU use at the chain tip and while serving blocks comes from cheaper peer-address metrics, less copying of shielded bundles, and reuse of large-block checksums (#2409, #2421, #2424).
  • With faster legacy checksum hashing on a Mainnet node without SHA instructions, serving old blocks uses 32% less CPU per MB, and one connection delivers blocks about 50% faster (#2450).
  • Mempool cleanup avoids full-pool scans for conflicts and expiry, batches removals, and reduces ordering work; pending transaction gossip cleanup removes changed IDs directly (#2467, #2468, #2469, #2470, #2473).
  • Set network.zakura.trace_dir to record legacy block announcements, requests, and sends in legacy_gossip.jsonl, without peer addresses; ZAKURA_TRACE_PEER_NAMES labels selected peers (#2446).

Library users

Source builds verifying pre-NU7 blocks above the last checkpoint need --features sprout, including Testnet sync from genesis with current checkpoints. The consensus crate restores its Halo2 error type and conversion for stable compatibility (#2413, #2466).

Full changelog

Added

  • With network.zakura.trace_dir set, legacy peer connections write
    legacy_gossip.jsonl: each block announcement sent to a peer, the peer's
    request for that block, and the block being sent to it or found missing.
    They also write the announcements each peer sends, up to 16 a minute for
    each connection. Requests for blocks this node did not announce to that
    peer are not written, so what a peer sends cannot make the file grow
    without bound. Rows never hold a peer's address. The ZAKURA_TRACE_PEER_NAMES
    environment variable (name=ip pairs separated by commas) names the peers an
    operator wants to tell apart
    (#2446).

Changed

  • network.unconditional_peers now also keeps its peers connected. Zakura
    dials every entry that names one address, and dials it again whenever no
    connection to that peer is open in either direction. An entry can give the
    port to dial, such as "192.0.2.1:8233". An entry without a port is dialed
    on the network's default port, and a CIDR range is only dialed when it covers
    a single address. Each dialed address adds one outbound and one inbound
    connection slot on top of the connection limits. The inbound slots are a pool
    that only listed peers can use, so a node whose other inbound slots are full
    still accepts a listed peer that dials it. One IP holds at most
    max_connections_per_ip of these slots. Zakura's other outbound dials leave
    a listed address's IP the room the listed peer needs. Zakura also
    lets these peers reconnect inbound without its usual wait between connections
    from one IP. IP addresses that an existing config
    already lists start being dialed after the upgrade, and a listed peer that
    accepts no connections costs one failed dial every ten minutes once its delay
    has grown
    (#2389).
  • Start up to 50 legacy startup peer connection attempts at once, and start the
    next one as soon as an attempt completes, instead of spacing attempts 100 ms
    apart. The total startup peer target and per-IP limits still apply
    (#2396).
  • Reduced the CPU a node spends keeping its peer address metrics up to date,
    which was the largest single CPU cost of an idle node at the chain tip
    (#2409).
  • Reduced CPU use when encoding blocks and transactions with Orchard, Ironwood
    or Sapling bundles, and when serving blocks to peers, by no longer copying
    each bundle before writing it
    (#2421).
  • Legacy connections now reuse recently calculated large-block checksums,
    reducing repeated hashing when several peers request the same block.
    Concurrent sends can still each calculate a checksum before it is remembered
    (#2424).
  • The error label of zakura.net.in.errors and the reason label of
    mempool.failed.verify.tasks.total now name the error kind, such as io,
    parse, invalid or download_failed, instead of the full error message.
    Peers could otherwise create an unbounded number of metric series. Update
    dashboards and alerts that match full error messages on these labels
    (#2439).
  • The start time in a trace row's process_trace_id is now the moment the
    row's ts counts from, so adding the two gives the row's wall-clock time.
    Before, the two were read at different moments and could be seconds apart
    (#2446).
  • With [network.zakura] trace_dir set, zakurad now moves to the file at a
    trace table's path within about a second when its own file was renamed,
    deleted or replaced, so trace files can be rotated by renaming them without
    losing rows
    (#2449).
  • The continuous profiler finishes reading a renamed trace table across bounded
    reads before switching files, truncating it, or rotating again, preserving rows
    in large backlogs even while the node is delayed before opening a replacement.
  • Legacy P2P message checksums are calculated with ring's SHA-256, which
    uses the vector instructions of CPUs that lack SHA instructions. On such a
    mainnet node, serving old blocks to syncing peers used 32% less CPU per MB
    and one connection delivered blocks about 50% faster. Checksum values are
    unchanged
    (#2450).
  • Calculate block-header hashes, transaction Merkle-tree hashes, and transaction
    IDs for versions one through four with ring, preserving the existing hash
    values (#2457).
  • Made Sprout JoinSplit proof and signature verification opt-in with the sprout
    Cargo feature. Builds using post-NU7 snapshots do not need it; verifying
    pre-NU7 blocks above the last checkpoint, including Testnet sync from genesis
    with the current checkpoints, requires --features sprout
    (#2466).
  • Sped up mempool cleanup after new blocks by finding conflicting transactions
    through spend-owner indexes instead of scanning the entire pool
    (#2467).
  • Sped up mempool expiry cleanup after new blocks by indexing expiry heights
    instead of scanning transactions that are not due to expire
    (#2468).
  • Reduced mempool cleanup work after new blocks by batching transaction removals,
    dependency-order updates and metric reports while retaining unmined children
    of confirmed transactions
    (#2469).
  • Sped up pending transaction gossip cleanup after mining or invalidation by
    removing changed IDs directly instead of scanning the advertisement backlog
    (#2470).
  • Removed the retired Sprout nullifier index from mempool storage. Sprout
    JoinSplits are now rejected by mempool policy even on custom pre-NU7 networks;
    historical block verification remains available with the sprout feature
    (#2471).
  • Reduced mempool ordering maintenance during admission and block cleanup by
    caching ordering scores and refreshing only surviving transactions whose
    priorities change
    (#2473).
  • Reduced how often the state service exports RocksDB metrics from every 30
    seconds to every 5 minutes. The zakura.state.rocksdb.* gauges and the
    size_on_disk RPC estimate now refresh at that interval
    (#2475).
  • Retained the approved v1.8.8 node patch version for the pending operational,
    performance, tracing, and build changes. Builds that verify pre-NU7 blocks
    above the last checkpoint still require the documented sprout feature
    (#2466,
    #2479).

Fixed

  • Scale NU7 reissuance to custom halving intervals so compatible Zebra and Zakura nodes
    calculate the same subsidy. Existing custom NU7 chains need coordinated deployment
    and a reset or explicit migration if they used the previous payout rule
    (#1591).
  • Restored NODE_NETWORK advertising for pruned nodes so peers can discover,
    reconnect to, and download recent blocks from them. Pruned nodes additionally
    advertise an experimental NODE_PRUNED flag. While an updated node is still
    syncing, it downloads blocks from peers without the flag and waits for one of
    them when they are all busy. It asks a pruned peer only when it is connected
    to no such peer, or when those peers leave block requests unanswered. It
    sends getblocks to peers without the flag too, because pruned peers leave
    a getblocks for deleted blocks unanswered. Near
    the network tip it treats pruned peers like any other peer. getnetworkinfo
    now reports the node's actual
    localservices, including these flags
    (#2382).
  • Cancel spawned legacy handshakes when their caller is dropped, so a connection
    timeout releases the stream and connection reservation immediately
    (#2396).
  • A restarted node now dials the peers in its legacy peer cache when every seed
    DNS lookup fails, instead of retrying DNS forever without connecting
    (#2399).
  • The legacy peer cache now keeps only peers that responded to this node in
    the last 3 hours, not addresses learned from gossip, so a restart spends its
    first connection attempts on peers that recently accepted a connection
    (#2404).
  • Restored the published consensus crate's Halo2 error type and conversion,
    preserving compatibility with its current stable release
    (#2413).
  • Read gossip trace peer names from network.zakura.trace_peer_names instead
    of an environment variable that could prevent the node from starting. The
    fleet installer writes the mapping and removes the obsolete environment
    override after verifying the configuration
    (#2474).

Security

  • A legacy peer's getblocks reply to a FindBlocks request now keeps at
    most 500 block hashes, the most zakurad and zcashd serve, so one peer can
    no longer make the syncer process up to 50,000 hashes per response
    (#2437).

Also in CHANGELOG.md.

Don't miss a new zakura release

NewReleases is sending notifications on new releases.