Zebra 6.1.0 Release

Zebra 6.1.0 Release

Zebra 6.1.0: New getstandardfee RPC and Four Security Fixes

We are releasing Zebra 6.1.0 today. This release adds a new getstandardfee RPC and fixes four security issues affecting block verification, node liveness, and mining. There are no consensus changes. All node operators are encouraged to upgrade.

New Features

getstandardfee RPC

A new getstandardfee RPC returns the ZIP-317 marginal fee, giving wallets and other clients a direct way to query the current standard fee. The value is also exposed to Rust consumers as transaction::zip317::MARGINAL_FEE. (#10717)

Security Advisories

GHSA-95m2-vx53-v2jw: getblocktemplate Can Produce Oversized, Invalid Blocks (Low)

When Zebra built a block template, its ZIP-317 transaction selector budgeted mempool transactions against the full maximum block size while reserving space only for the coinbase transaction, not for the serialized block header or the transaction-count field, both of which count toward the limit (roughly 1,490 bytes on Mainnet and Testnet). If the selected transactions filled that margin, the assembled block exceeded the consensus size limit, so a miner would perform proof-of-work on a block that every node rejects, wasting the work; an attacker able to place valid, selectable transactions in a victim miner’s mempool could deliberately shape templates into the affected range. Non-mining nodes were unaffected, and because oversized blocks are correctly rejected there was no consensus divergence. Zebra now reserves the network-specific header size and the maximum transaction-count width before selecting transactions, so templates stay within the limit. Thanks to @ebfull of Project Tachyon for reporting this issue via coordinated disclosure

GHSA-g7c4-2w6c-cr3r: Unattributed Pushed-Transaction Failures Allow Batch-Verification Poisoning (Moderate)

When a directly pushed mempool transaction failed verification, Zebra did not record the sending peer’s address on the failure, so the peer was never misbehavior-scored or banned. Because Orchard proof verification runs through a process-global batch verifier shared by mempool and block verification, a peer could repeatedly push transactions carrying invalid Orchard proofs at no cost, forcing each shared batch onto the slow per-proof path, including honest proofs from block processing batched alongside, and sustaining a measured block-processing slowdown for as long as the traffic continued. There was no crash, consensus divergence, or state corruption. Zebra now attributes pushed-transaction verification failures to the sending peer so the existing misbehavior scoring can ban it. This closes the verification-failure attribution gap left by the admission-accounting fix in GHSA-m9xx-8rcj-vmgp. Thanks to @ebfull of Project Tachyon and @ValarDragon of Valar Group for reporting this issue via coordinated disclosure.

GHSA-4g24-549m-hp75: Quadratic Transparent Value Check in Block Verification (Moderate)

During contextual verification, Zebra checked the remaining transparent value of every non-coinbase transaction by cloning and converting the entire block-level spent-output map once per transaction, turning a linear check into quadratic work. A block near the size limit packed with minimal single-input transactions (up to roughly 26,000) could take over 52 seconds to validate on fast hardware. Because the affected code runs only after proof-of-work checks pass, triggering it requires a validly mined block (produced directly or by seeding the mempool for an honest miner), which bounds the attack to a one-time, self-clearing stall per block with no crash, consensus divergence, or state corruption. Zebra now passes each transaction only the outputs it spends, making the check linear in total inputs. Thanks to @ebfull of Project Tachyon and @ValarDragon of Valar Group for reporting this issue.

GHSA-8gxx-hc65-vv82: Chain Stall via Stale parent_error_map Entry (Moderate)

When a block failed contextual verification, Zebra recorded its hash in an in-memory map and propagated that failure to any child block whose parent was in the map, but entries were only removed by a fixed size limit or a restart, never when the canonical block at that hash later committed successfully. Using the same ZIP-244 coinbase-malleability primitive as GHSA-4m69-67m6-prqp, an unauthenticated peer that won the propagation race could get a poisoned block sharing a canonical block’s hash rejected first, so the canonical successor was then rejected against the stale entry, stalling the node at that height for roughly 41 hours per trigger and repeatable on each new block. The stall cleared on restart, with no crash, consensus divergence, or state corruption. Zebra now removes a hash from the map when the canonical block at that hash commits successfully. Thanks to @deedim for reporting this issue, including a deterministic proof of concept and analysis of its relationship to GHSA-4m69-67m6-prqp.

Thank You to Our Contributors

This release was made possible by the work of @aphelionz, @evan-forbes, @jvff, @oxarbitrage, @upbqdn, and @weifanglab. Thank you for your continued contributions to Zebra.


Zebra is the Zcash Foundation’s independent, Rust-based implementation of the Zcash protocol. Learn more at github.com/ZcashFoundation/zebra.

4 Likes