Faster transaction gossip and mining RPCs, with revised block announcements. Check your config before upgrading.
Supported on Mainnet until block 3,643,309, around December 5, 2026. Upgrade warnings start about three days earlier.
Before you upgrade
- Rename block advert settings. Rename
advert_window_min/advert_window_maxtoadvert_window_full_block/advert_window_small_block, including theirZAKURA_NETWORK__environment variables. Old config keys still load, but old variables plus regenerated configs can fail startup (#2081). - Check block announcement delays. Peers outside the initial group now receive announcements after one 500 ms delay. Use
advert_delayinstead ofadvert_delay_minandadvert_delay_max; old configs still load, using the maximum and ignoring the minimum (#2237). - Update state request metric labels. Update dashboards and alerts:
raw_blockreplacesblock,any_chain_raw_transactionreplacesany_chain_transaction, andmined_transaction_idsreplacestransactionfor the affected reads (#2201, #2206). - Historical audit commands need a custom build.
audit-historical-treestatesandverify-historical-treestatesare no longer in defaultzakuradbuilds. Build withdebug-commandsif you need them (#2226).
Highlights
- One slow peer no longer delays transaction propagation by up to 6 seconds per hop; transaction gossip also keeps pending IDs when the network is not ready (#2220).
- Per 2 MB block on x86-64,
getblocktemplateencoding drops from about 7 ms to 2 ms andsubmitblockdecoding from about 2 ms to 0.6 ms; parsing legacy or work-ID submissions saves about 3.6 ms (#2207, #2219). - Use
network.unconditional_peersto exempt trusted IPs and CIDR ranges from scoring, bans, and mempool cooldowns and disconnects; the default is empty, and CIDRs must have no host bits set (#1231). rpc.allow_unauthenticated_admin, disabled by default, permitsinvalidateblock,reconsiderblock, andpreciousblockwithout cookies on the primary listener. Restrict access to trusted clients with firewall rules (#2088).- Common 5.4.0 brings faster proof verification, point decompression, and Orchard bundle decoding (#2274).
Library users
Breaking changes affect This node release uses an explicitly approved patch-version exception, includingzakura-chain, zakura-consensus, and zakura-state: PayingKey/CommitmentRandomness are removed and state reads expand; zakura-rpc adds serialized-data constructors. The new default-on sprout feature gates Sprout verification; disabling it can stall pre-NU7 sync (#2149, #2167, #2171, #2200, #2201, #2205, #2206).
Full changelog
the removals documented below. Published library crates retain their independently
required version bumps (#2278).
Added
network.unconditional_peers, a list of peer IP addresses and CIDR
ranges that Zakura never scores, bans, or penalizes with mempool cooldowns
and their disconnects. CIDR entries must have no host bits set. Zakura ignores misbehavior reports
for these peers, so tip lag, upgrade boundaries, or bugs cannot get your own
nodes, miners, or sidecars banned. The default is empty
(#1231).
rpc.allow_unauthenticated_admin (disabled by default) to allow
invalidateblock, reconsiderblock, and preciousblock without cookie
authentication on the primary RPC listener. Enabling this assumes the
administrator has correctly configured firewall rules restricting access to
trusted clients. Browser requests, which carry an Origin header, are
rejected so web pages can't reach these methods
(#2088).
sprout cargo feature that gates Sprout JoinSplit proof
verification. It is enabled by default for now. Builds without it refuse
JoinSplits as a retryable verifier failure, so they stall rather than fork
on a pre-NU7 block above the last checkpoint
(#2149).
sync.header.peer.lifecycle_refused.total metric, which counts
header sync sessions refused because the node fell behind on peer
connections and disconnections
(#2211).
zakurad writes when
network.zakura.trace_dir is set: chain_tip.jsonl, mempool.jsonl, and
mining_template.jsonl. They record each stage from a new best tip to the
getblocktemplate response, with the state writer's queue and commit times.
The ts field in every trace table now counts from one origin per process,
so rows from different tables can be compared
(#2261).
Changed
[network] settings advert_window_min to advert_window_full_block and
advert_window_max to advert_window_small_block, so each name says which block size
it applies to. The old names still load from a config file. Rename the
ZAKURA_NETWORK__ADVERT_WINDOW_MIN and ZAKURA_NETWORK__ADVERT_WINDOW_MAX
environment variables to ZAKURA_NETWORK__ADVERT_WINDOW_FULL_BLOCK and
ZAKURA_NETWORK__ADVERT_WINDOW_SMALL_BLOCK too: an old variable plus a regenerated
config that holds the new name fails startup with a duplicate field error
(#2081).
sprout cargo feature now also gates Sprout Ed25519 joinSplitSig
verification, so builds without it contain no Sprout verifier. It remains
enabled by default
(#2167).
zakura-network's ZakuraNodeRecord::signature is now [u8; 64]
instead of an ed25519-zebra signature. Discovery records and their wire
format are unchanged
(#2170).
zakura-chain holds a transaction's joinSplitPubKey and joinSplitSig
as plain bytes (JoinSplitPubKey, JoinSplitSig) and no longer re-exports
ed25519-zebra as primitives::ed25519. Their serialized forms are
unchanged. zakura-consensus's TransactionError::Ed25519 now carries the
error message
(#2171).
the spent transparent outputs that contextual validation already resolved
(#2188).
getblock and getrawtransaction with verbosity 0 return finalized blocks
and transactions from their stored bytes instead of decoding and
re-serializing them. Responses are unchanged. State request metrics label
these reads raw_block and any_chain_raw_transaction instead of block
and any_chain_transaction
(#2201).
zakura-state adds ReadRequest::RawBlock and
ReadRequest::AnyChainRawTransaction, answered by ReadResponse::RawBlock
and ReadResponse::RawTransaction. Code that matches every ReadRequest or
ReadResponse variant must handle them
(#2201).
GetBlock method and the hex field of verbose
getrawtransaction return finalized blocks and transactions from their
stored bytes instead of re-serializing them. Responses are unchanged
(#2205).
zakura-state's ReadResponse::AnyChainTransaction also carries the
transaction's consensus serialization, and zakura-rpc adds
BlockAndHash::from_serialized and
TransactionObject::from_serialized_transaction
(#2205).
transaction index lookup per transaction, instead of reading and decoding
each transaction after every block. A queued transaction whose transaction
ID was mined with different authorizing data is now removed instead of
being retried until it expires. State request metrics label these reads
mined_transaction_ids instead of transaction
(#2206).
zakura-state adds ReadRequest::MinedTransactionIds, answered by
ReadResponse::MinedTransactionIds. Code that matches every ReadRequest
or ReadResponse variant must handle them
(#2206).
Per 2 MB block, getblocktemplate transaction encoding drops from about
7 ms to 2 ms and submitblock decoding from about 2 ms to 0.6 ms on x86-64.
Responses and accepted inputs are unchanged
(#2207).
twice, which saves about 0.7 ms per 2 MB block in submitblock on x86-64.
Requests and responses are unchanged
(#2210).
zakura-network: HeaderSyncStartup::new now takes the node's admitted
connection count as a required argument instead of defaulting it to 92,
since that count now sizes the header sync lifecycle queue
(#2211).
submitblock calls with a work ID, and calls
from JSON-RPC 1.0 and bitcoind-style clients, once instead of re-encoding
them, which saves about 3.6 ms per 2 MB block on x86-64. Requests and
responses are unchanged
(#2219).
before sending the next batch, so one slow peer can't delay transaction
propagation by up to 6 seconds per hop. The gossip task now also times out
while waiting for the network to be ready, and keeps the waiting transaction
IDs pending until it can send them
(#2220).
500 ms delay instead of immediately. advert_delay replaces
advert_delay_min and advert_delay_max; configs with the old names still
load, using advert_delay_max as the delay and ignoring advert_delay_min
(#2237).
decompression, and Orchard bundle decoding
(#2274).
Removed
zakura-chain no longer defines the unused Sprout types
sprout::keys::PayingKey and sprout::commitment::CommitmentRandomness
(#2200).
audit-historical-treestates and verify-historical-treestates
subcommands from default zakurad builds. Build with the
debug-commands feature to use them
(#2226).
Fixed
by reusing outputs in retained block records
(#2151).
hides ready storage completions or committed-state changes from the run
loop's per-turn checks. Before, a VCT apply that finished at its hard
deadline could stay hidden while the loop read the state it published, and
the deadline check then shut the node down
(#2152).
completion or VCT repair status that would retire that work. Before, a
VCT apply that finished at its hard deadline could still shut the node
down, and a repair supplier could be charged for a request the repair no
longer needed (#2178).
replaces its session. Before, a peer could open a new session just before
each request timeout and hold a header slot without ever answering
(#2182).
Security
header peers, so a stream of fresh identities that each fault can no longer
grow that state and the reactor work on it without bound
(#2131).
HistoryPruned backoffs as it
admits header peers, so peers that keep reconnecting under new identities
can no longer grow that state and the reactor's scan over it without bound
(#2209).
connection and control-handshake slots (69 of 92 and 24 of 32 by default),
so inbound load can no longer stop the node from dialing peers it picks
itself (#2242).
connection and handshake limits, so one machine can no longer bypass the
16-connection cap by using a fresh address from its /64 for each identity.
IPv4 and non-global IPv6 addresses still count one by one
(#2243).
Also in CHANGELOG.md.