On 21 October, CoinDesk reported that Zcash developers had confirmed a November date for NU7, the upgrade that cuts the time between blocks from 75 seconds to 25. The framing everywhere was speed: three times as many blocks, a first confirmation in a third of the time, payments that feel less like waiting. CoinDesk added one careful caveat, which is that the chosen block height still has to be merged into the spec.
That caveat is true, and it is also the smallest version of the story. Eight days before the height was proposed, somebody inside the project sat down and read eleven of the NU7 specification documents line by line against the protocol specification and against the code that is actually deployed. They found a hundred and nineteen problems. They fixed eighty-nine of them in an accompanying pull request, and they published the other thirty in a public issue, itemised, each one named, each one with a sentence explaining exactly what is still wrong.
That list has been sitting in the open since 13 October. Every outlet that reported the November date could have opened it. The activation height is not the thing that has not been merged. The specification is.
TL;DR
- NU7 cuts Zcash block spacing from 75 seconds to 25, a ratio of exactly 3, with mainnet activation proposed for height 3,543,405, roughly 6 November 2026.
- A line-by-line review published on 13 October found 119 gaps across 11 NU7 documents: 89 were fixed, and 30 remain open and individually listed.
- Exactly one of the 30 is marked “Not fixed” rather than “Partly fixed”: the Zcash Protocol Specification cannot render NU7 at all, and none of the rule changes have been applied to it.
- The deployment document still reads “Mainnet: TBD (To be set on OCT 20)”, and the pull request setting the height is still open.
- Both networks’ activation heights MUST be a multiple of 3 under a rule that three documents cite each other for circularly, and that none of them justifies. The proposed height obeys it.
- The wallet best-practices document still tells authors to expire transactions after 40 blocks, which stops meaning 50 minutes and starts meaning 16 minutes 40 seconds.
The ratio is three, and three is the whole problem
Start with what actually changes, because it is simpler than it sounds. ZIP 218 adds a constant called PostNU7PoWTargetSpacing, fixes it at 25 seconds, and derives a second constant from it: NU7PoWTargetSpacingRatio, equal to the post-Blossom spacing divided by the new one, which is 3. Everything else in the upgrade is bookkeeping around that number. The halving interval triples to 5,040,000.
Then comes the part that is easy to state and hard to finish. A block count is not a quantity. It is a clock reading. Any constant written as “N blocks” that was chosen because it meant a certain amount of wall-clock time has just been silently revalued, and every one of them has to be found and either multiplied by three or deliberately left alone with a reason. ZIP 218 says so directly: implementations SHOULD scale by the ratio those constants that represent a time duration, and SHOULD NOT scale the others.
That is a sentence that creates work across an entire ecosystem, and the honest way to judge an upgrade like this is not to ask whether the consensus maths is right. It is to ask whether anybody went and found all the clocks.
Somebody did, and wrote down what they missed
They did. On 13 October a reviewer opened issue 1393 in the ZIP repository under the title “NU7 ZIPs: gaps found in a review of ZIPs 200, 203, 207, 208, 214, 218, 235, 237, 259, 2003 and 2008”. The body is a line-by-line account organised by document, split into what the accompanying pull request fixed and what it did not.
I counted every item in it. Eighty-nine fixed, thirty open. Twenty-four of the thirty are labelled “Partly fixed”, six need an editor decision, and exactly one is labelled “Not fixed”. Here is the distribution.
| Document | Fixed | Still open |
|---|---|---|
| ZIP 200: Network Upgrade Mechanism | 7 | 1 |
| ZIP 203: Transaction Expiry | 8 | 2 |
| ZIP 207: Funding Streams | 13 | 7 |
| ZIP 208: Shorter Block Target Spacing | 5 | 1 |
| ZIP 214: Zcash Development Fund | 10 | 2 |
| ZIP 218: 25-second Block Target Spacing | 24 | 5 |
| ZIP 235: Remove 60% of Transaction Fees | 2 | 3 |
| ZIP 237: Network Sustainability Mechanism | 8 | 5 |
| ZIP 259: Deployment of NU7 | 4 | 1 |
| ZIP 2003: Disallow version 4 transactions | 4 | 1 |
| ZIP 2008: FS_FPF_ZCG_H3 address list | 4 | 2 |
| Total | 89 | 30 |
I want to be careful about the tone here, because the obvious reading is the wrong one. This list is not evidence that Zcash is sloppy. It is the opposite. Almost no chain produces a document like this, and the ones that do not produce it do not have fewer gaps, they have unknown gaps. The reviewer found a hundred and nineteen problems because they went looking, wrote down the ones they could not fix, and signed their name to the list. That is the behaviour you want.
What is strange is that the list exists, is public, is dated, is itemised, and is apparently unread by everyone describing what ships in November.
The one marked “Not fixed”
Twenty-nine of the thirty open items are partial fixes or editorial questions. One is different, and it is the one under ZIP 259, the deployment document:
The Zcash Protocol Specification cannot render NU7 yet. None of the rule changes from ZIPs 218, 235, 237, 2003 and 2008, or from Revision 2 of ZIP 207 and Revision 3 of ZIP 214, has been applied to it.
Read that again with the dates in mind. The protocol specification is the canonical description of Zcash, the document every other document cites when it wants to be precise. As of the review, it does not contain this upgrade.
The item points at a tracking issue for the specification work, opened on 23 September. I checked it. It has not been touched since the day it was created, which is now twenty-eight days. That is not an accusation of negligence, because specification work is slow and the ZIPs themselves are the operative documents for implementers. But it does mean that for a window covering the entire run-up to activation, the one artefact that is supposed to be authoritative has been the one artefact that is wrong, and the people relying on it have no way to know that from the document itself.
The deployment document still says TBD
There is a smaller detail that makes the point better than the big one. ZIP 259 is the deployment document. It is where the activation heights live. Pull up the current version in the repository and the heights section reads:
ACTIVATION_HEIGHT (NU7). Testnet: 4465026. Mainnet: TBD (To be set on OCT 20).
A canonical specification, carrying a to-do with a deadline that has already passed. The pull request that replaces it with 3,543,405 was opened on 20 October by one of the project’s core contributors, carries the note “Height agreed at ZIP editor meeting”, changes sixteen lines, is cleanly mergeable, and is still open as I write this. It will certainly merge. That is not the interesting part. The interesting part is that the gap between “the number is decided” and “the number is written down where it is supposed to be” is a real gap with a real duration, and during it the deployment specification and the thing being deployed disagree.
The same gap shows in the code. Zebra, the Rust node, has the testnet activation height compiled in as a constant. The mainnet module in the same file stops at NU6.3. The implementation does not know the mainnet height either, for the same reason and for the same length of time.
A consensus-level MUST that nobody can justify
My favourite item on the list is the thirteenth. Both ZIP 214 and ZIP 259 require the NU7 activation height to be a multiple of 3. ZIP 214 says it SHALL be. ZIP 259 says it MUST be, “as required by Revision 3 of ZIP 214”. The reviewer’s finding is blunt: no document gives a reason, no NU7 formula needs it, and the three documents that mention it cite each other for it in a circle. The text was left unchanged, with the note that the authors need to either state the property the rule protects or remove it from all three.
So I checked whether the proposed height obeys a rule that nobody can explain. The mainnet height is 3,543,405, and 3,543,405 divided by 3 is 1,181,135 exactly. The testnet height 4,465,026 is likewise divisible by 3. Both networks are complying with a constraint whose purpose is, by the project’s own reviewer’s account, not written down anywhere.
In fairness there is a hint. ZIP 214’s own changelog entry for Revision 3 mentions preserving the address-period duration under 25-second blocks in the same breath as the multiple-of-3 requirement, so there may well be a sound reason involving the funding-stream address rotation. I am not going to adjudicate it, and I do not need to. The point is that a reader of the specification cannot find it, and a consensus requirement whose justification exists only in somebody’s head is a requirement that will eventually be changed or dropped by somebody who could not find it either.
The clock the code fixed and the manual did not
Now the one that matters most to users, and the one with the cleanest shape.
Zcash transactions carry an expiry height. The default has been 40 blocks since Blossom, which at 75-second spacing is about 50 minutes. ZIP 218 is explicit that this must triple to 120 blocks at activation to preserve that 50 minutes, and it goes further: it quotes the exact paragraph in ZIP 315, the wallet best-practices document, and writes out the replacement text it wants, including the new reference entry.
ZIP 203 got its NU7 section. ZIP 401 got updated. The code got it right and then some. In librustzcash, the library underneath most of the Zcash wallet ecosystem, there is now a constant defined as the ratio multiplied by the Blossom delta, a function that selects the delta by consensus branch, and tests that pin the behaviour on both sides of the activation boundary. The same library ships a whole module implementing ZIP 318’s rescaling rules, and it landed before the ZIP text describing them was merged, which happened at 22:07 UTC on 20 October.
ZIP 315 still says 40 blocks. The review names it: “ZIP 315 § Expiration height still recommends 40 blocks for wallets after NU7.” I pulled the current repository and confirmed it, and I checked all fifty-eight open pull requests in that repository to see whether a fix was queued. None of them touches the file. The last substantive change to it was made during the NU7 review round itself, on 14 October, and what that change did was update the recommended transaction version from v5 to v6 and add a creation date. The file was open on somebody’s screen, and the paragraph two hundred lines above was left at 40.
Forty blocks at 25-second spacing is 16 minutes and 40 seconds. A wallet author who implements the document exactly as written ships transactions that expire in a third of the intended window.
The honest version of this finding is not “Zcash broke wallets”. The library almost everyone uses is correct, so in practice the blast radius is small. The honest version is stranger and more interesting: every layer that executes code was rescaled, and the layer that was left behind is the one written for humans to read. The spec is not the system. It never was. We just usually get to pretend otherwise.
The constant that has lost 83% of its window while being marked “no change” twice
One more, because it shows how this compounds across upgrades rather than within one.
ZIP 218 reviews seven block-count constants and publishes the verdict for each. It takes the list verbatim from ZIP 208, the document that did the same exercise for Blossom in 2019, when the spacing went from 150 seconds to 75.
| Constant | Current | After NU7 | Verdict |
|---|---|---|---|
COINBASE_MATURITY |
100 | 100 | Consensus rule, not changed |
MAX_REORG_LENGTH |
99 | At least 600 | Wall-clock target, not a ratio |
TX_EXPIRING_SOON_THRESHOLD |
3 | 3 | No change |
MAX_BLOCKS_IN_TRANSIT_PER_PEER |
16 | 48 | Scale by 3 |
BLOCK_DOWNLOAD_WINDOW |
1024 | 3072 | Scale by 3 |
MIN_BLOCKS_TO_KEEP |
288 | 864 | Scale by 3 |
NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD |
1728 | 1728 | No change, a duration deliberately unscaled |
Blossom reviewed these seven and changed none of them. NU7 reviews the identical seven and changes four. The same physics produced opposite answers seven years apart, and the reversal on the reorg window is substantial: from 99 blocks to at least 600, which restores the roughly four-hour wall-clock margin the chain had at launch. ZIP 218 justifies it by citing a Litecoin incident in April 2026 where a thirteen-block invalid chain took about three hours to recover. Zebra already keeps a thousand blocks, so it complies today.
Now look at the last row. That constant is the window before an upgrade during which nodes prefer connections to peers that have already upgraded. It is, in other words, part of the machinery that makes network upgrades go smoothly. It was 1,728 blocks when a block was 150 seconds, which is three days. Blossom left it alone and it became 1.5 days. NU7 is leaving it alone again and it becomes 12 hours. Both times the table says “no change”. The number has not changed once, and the thing it protects has lost 83% of its duration.
The review caught the knock-on too: ZIP 204 still describes that window as “approximately 1.5 days at the post-Blossom block interval”, which stops being true in November. I checked, and it still says it.
What doing it properly looks like
Before this reads as a pile-on, the control. ZIP 318, which schedules the pool migration, was full of durations stated in block counts. The fix merged at 22:07 UTC on 20 October, and it is genuinely careful work: it introduces a new term, the “reference block”, defines every duration in those units, and specifies a piecewise function so that a delay which straddles the activation height keeps its exact length in wall-clock time rather than being cut short or stretched. It chooses the post-activation boundary grid so that every boundary remains a multiple of 144, meaning a wallet that already retains tree states on that grid keeps all of them.
That is what finding a clock and fixing it looks like, and it is why the ZIP 315 paragraph counts as a gap rather than a judgement call. The project knows exactly how to do this. It did it, thoroughly, in a harder case, the night before the activation height was proposed.
Why this is a gaming post
Because on-chain gaming runs on block counts, and almost nobody writing a game thinks of them as clock readings.
Raffle close heights. Commit-reveal windows. Cooldowns between entries. Timeouts after which a player can claim a refund because the oracle never answered. All of those are typically written as “N blocks” by a developer who was thinking in minutes, and every one of them is a constant that silently changes meaning if the chain ever changes its spacing. Base is not about to triple its block rate, but Ethereum has changed slot timing before and is openly discussing it again, and “the chain under you will never retune its clock” is a strange thing for a supposedly trust-minimised application to assume.
There is a neat illustration sitting in the configuration of the thing Satoshie depends on. I read the Chainlink VRF 2.5 coordinator’s config on Base directly at block 52,891,342. Two of its fields are deadlines. stalenessSeconds is 172,800, which is 48 hours, and it is denominated in seconds, so it means 48 hours no matter what the chain does. minimumRequestConfirmations is 0, and it is denominated in blocks, and what it means in wall-clock terms is entirely at the mercy of Base’s block time. Same struct, same contract, two deadlines, one of which is anchored to physics and one of which is anchored to a convention.
That distinction is the practical content of provable fairness, and it is narrower than the marketing suggests. A VRF proof is a proof whichever block it lands in; the randomness does not care how fast blocks arrive. What does care is every window wrapped around it. Our position has always been that the draw should be verifiable by anyone, and we have made a point of publishing the measurements rather than the claims, including the week we found 13,226 draws where a configuration field was parsed every single time and acted on by nobody. A dormant field is exactly the kind of thing that changes meaning without anyone noticing, which is the same failure mode as a block count that used to mean 50 minutes.
The lesson we take from NU7 is not about Zcash. It is that the artefact which executes and the artefact which explains drift apart by default, and only one of them is binding. If you want a game to be fair, denominate your deadlines in the units you actually mean, say which block you pinned your reading at, and assume the documentation is the stale copy. We have argued the simplicity case from Zcash before, and made the general fairness case at greater length.
Honest limits
Six, as always.
One. ZIP 315 is Draft status and its recommendations are SHOULD, not MUST. A wallet that ignores it is not non-compliant, and the dominant library gets the behaviour right regardless, so the practical risk is low and concentrated on new implementations written from the document.
Two. I read the ZIP repository and librustzcash at a single point in time on 21 October. Any of this can be fixed between my writing and your reading, and some of it probably will be. The dates and item counts are what I could verify, not a prediction.
Three. The thirty open items are not thirty bugs. Most are documentation consistency: stale reference titles, a Status header that does not match ZIP 0’s format, backticks breaking a link. I counted them equally because the review presented them equally, and that flattening is my choice, not the reviewer’s claim.
Four. The seven-constant table names zcashd definitions, and zcashd is end-of-life. Zebra uses different names for the same ideas and I checked only its reorg window directly, which complies. I did not audit every implementation against every row.
Five. I did not independently verify the 25-second spacing will hold in practice. Difficulty adjustment under a tripled block rate is exactly the sort of thing that behaves differently live, and ZIP 218 devotes a long rationale section to the averaging window for that reason.
Six. The activation date is arithmetic, not an announcement. At the chain height I read on 21 October, 3,525,337, the proposed height is 18,068 blocks away, which at the current rate puts it around 6 November. A difficulty swing moves that by hours.
Three questions
Who owns the list? Thirty items, one author, no assignees, and a November deadline. An open issue with nobody’s name against each line is a hope, not a plan, and the same pattern defeated the XRPL amendment queue we looked at on Monday.
What is the multiple of 3 for? Someone knows. Until it is written in the document that imposes it, the rule survives on institutional memory, and institutional memory is the thing network upgrades are worst at preserving.
How many clocks are left? The review covered eleven documents. The ZIP corpus is a hundred and thirty-nine files, and twenty-five of them state something in block counts. Three apply the ratio. Most of the remainder are absolute heights rather than durations, which is fine, but “most” is doing work in that sentence and nobody has published the full audit.
The closer
Zcash is shipping a genuinely good upgrade, and the thirty open items are a sign of health rather than rot. The part worth sitting with is that a public, dated, itemised list of exactly what is still wrong with a November consensus change generated no coverage at all, while the block time, which is one line of it, generated plenty.
We say on-chain systems are transparent, and they are. Transparency is not the hard part and never was. Somebody still has to open the document.


