Skip to content

v3.3.1

Choose a tag to compare

@github-actions github-actions released this 04 Sep 11:48
· 36 commits to main since this release
cb6a44a

One fix, to what every nest asks for and seals. Worth the restart.

A short answer can no longer seal as an empty block (#1144)

Every way a provider answers a log range short lands at the end of the range: a load-balanced
backend a block or two behind the one that answered latest, a height a node has finalised but not
yet executed (Monad), an answer truncated under load. All of them answer correctly a moment later,
and all of them return a list, which is a valid answer. So the rows were sealed as an empty block,
into immutable Parquet, with nothing to say they were missing, and the block's hash was unchanged so
reorg handling could not see it either. Nothing at fetch time can tell a short answer from an empty
block, and the header's logsBloom cannot: measured on mainnet, a sparse address tests positive in
the bloom of a quarter of the blocks it has nothing to do with.

What changed. Every fetched window now starts two blocks before the cursor, in all four
ingestion loops, so the next window asks for the previous window's tail again. Rows are keyed by
(block, log_index), so the second pass adds what the first missed and duplicates nothing, and the
merged block is re-sorted so its content address is what a complete first answer would have
produced. The seal cut is held back until the tail has been asked for again, and a bounded range
ends with one more window over its own last two blocks. On the tip path a refetched row the store
already holds is dropped before it reaches a view, and one stored under a different block hash - a
reorg the handler has not yet rolled back - refuses the window rather than being mistaken for
current.

What it costs. At tip the window is a block or two wide, so the overlap widens the one call the
poll already makes and adds none; an idle nest's RPC bill is unchanged. In backfill it adds two
blocks to a window of hundreds and one two-block window at the end.

What it does not cover. A hole strictly inside a window, and a range short by a few rows within
a block. Neither is a shape any observed provider fault produces, and RFC-0049 §1 says so.

Segment identity is unchanged. The cut is still the block the data dictates; a run against a
provider that answers short once now seals the same rows under the same content addresses as a run
against one that never does, and that equality is a test, mutation-checked seven ways.

No data migration. A binary swap and a restart, as ever; a nest already running gains the guard from
its next window.