Monthly update — the real NU6.3 corpus, and the oracle run against it
Covering 2026-07-28 (Ironwood activation) to 2026-08-04. M1 shipped with NU6.3 vectors
that were builder-synthesized and labelled as such, because Ironwood had not activated and
no such traffic existed. It activated on mainnet at height 3,428,143 on 2026-07-28, so the
synthesized vectors can be replaced with the thing itself. This update reports that corpus
and the first differential run against it.
The corpus (seeds-real/nu6_3_activation/)
- 172 transactions, sampled across heights 3,428,150 - 3,433,400 — every 50th
block, 106 blocks, zero misses - 249 verification items: 143 Orchard-pool bundles and 106 Ironwood-pool
bundles. One bundle carries one halo2 proof, so the bundle is the unit the verifier
actually consumes - 77 dual-pool transactions — a single transaction carrying both an Orchard-pool and
an Ironwood-pool bundle. This is what cross-pool movement looks like when the chain
produces it rather than when a test constructs it - Those bundles hold 1,264 Orchard actions and 216 Ironwood actions (actions, not
bundles — a bundle carries many)
The window opens 7 blocks past activation, so the activation boundary itself is
represented. The extraction ran on 2026-08-02, which is stated rather than implied: when
the chain produced a block and when we fetched it are different facts, and only the first
is visible in the data.
On the T+0 extraction
The M1 post said the corpus would be extracted at T+0. Two facts, stated separately
because they are different: the window opens at the activation boundary — the first
sampled block is 3,428,150, seven blocks past activation — but the fetch ran on
2026-08-02, not at that instant.
We did pull a denser slice on activation night: 11 blocks at stride 4 across heights
3,428,149-3,428,189, spanning 50.8 minutes, carrying 698 Orchard actions, 211 Ironwood
actions, and 96 dual-pool transactions. It is not in this directory. Forty heights is too
narrow a base for an equivalence corpus, so the committed cut trades density for reach —
stride 50 across 5,250 heights, 4.58 days.
Worth stating what that trade costs, because it is the more interesting number: the
activation-night slice runs 8.7 dual-pool transactions per block against 0.73 in the
committed window — twelve times denser in exactly the traffic this grant exists to test.
Cross-pool movement peaks at the boundary and thins out fast. We hold those blocks and can
commit them as a second directory if reviewers want the dense slice in-tree.
The differential run
Every one of the 249 items was verified twice: once through the batch path, with items
grouped into batches of 16, and once through the single path, one item at a time. The
assertion is that the two paths reach the same verdict for the same item — this is the
equivalence property the grant exists to test, run for the first time against real
third-era mainnet data rather than synthesized vectors.
- 249 items over 16 batches — zero disagreements, zero false accepts
- All 249 accepted under the PostNu6_3 verifying key, as real mainnet proofs must
- Mixed-pool batches: Orchard-pool and Ironwood-pool items interleaved into shared
batches also agree item-for-item. Since NU6.3 the two pools share a circuit and a batch
stack, so mixed batches are the ordinary shape of post-activation traffic, not an edge
case
One property is asserted before any of the above is trusted: that both pools actually
loaded. A transaction may carry two bundles, and a loader that takes only the first would
yield 172 items instead of 249, verify zero Ironwood bundles, and still report agreement
on everything it did check. The run fails if the Ironwood count is zero.
Reproducing it
git clone https://github.com/robustfengbin/zebra-batch-equivalence
cd zebra-batch-equivalence
cargo test --test nu6_3_agreement -- --nocapture
The corpus is committed as raw wire bytes, one transaction per file, with the block height
in each filename — heights are load-bearing, since the sighash depends on the network
upgrade in force at that height. The directory carries its own README recording the
sampling stride, the extraction date as distinct from the block heights, and why a prefix
of the directory is not a substitute for a random sample of it.
Next
The dual-pool transactions are the input M3’s turnstile work needs, and until activation
they could only be reasoned about from constructed examples. There are 77 real ones in the
repository now, and the window is sampled rather than exhausted.