v2.7.1
A fix release. 2.7.0 was the binary an evaluator actually ran, and it lied in four places that
matter: --rpc still dialled public endpoints, /ready was green on a dead pool, init of stETH
scaffolded a nest that would index nothing, and an oversized eth_getLogs range retried forever.
Drop-in. Swap the binary and restart; no config changes, no data migration.
--rpc is the whole pool
Passing --rpc used to prepend your endpoint to the bundled public defaults. init wrote all of
them into rpc_urls, and dev --rpc still failed over onto nodies and drpc. A paid-only run was
neither paid-only nor measurable.
An explicit --rpc is now the complete pool, at init, add, dev, metadata, and in the
runtime. No --rpc still uses the configured or built-in list unchanged.
/ready is no longer green on a dead RPC
A nest whose only endpoint was http://127.0.0.1:1 announced API live and answered /ready 200
with ready: true, last_block: 0, stalled: false. A load balancer would have sent traffic at an
empty process.
A failed first poll now sets initial_poll_failed. /ready is 503 immediately. The 90-second
start-grace no longer covers a pool that has already proved itself dead.
init no longer scaffolds a nest that silently indexes nothing
stETH. The proxy is EIP-897. 2.7.0 resolved the proxy ABI (one table, ProxyDeposit) and warned
that zero rows would index. init now follows implementation(), then Sourcify, then keyless
Blockscout, then keyed Etherscan. Live: 32 tables, and a 4,000-block tip backfill stored 1,559
Transfer, 1,559 TransferShares, 152 Submitted.
Sourcify miss. 2.7.0 demanded ETHERSCAN_API_KEY as if it were the only option. Blockscout
serves the same getabi API with no key on mainnet, Base, and Gnosis. BSC has no instance we have
measured; the error now says so, and names --abi.
Upgraded proxies. init/add resolve the current implementation. For Graph staking that is
Horizon-era names; ~400 million blocks of Arbitrum StakeDeposited decode to empty tables and look
healthy. Two guards, neither of which reconstructs history: a height heuristic when the current impl
was deployed after the proxy, and a tip-vs-deploy log sample (HistoricalMismatch) when recent
events match and history near deployment does not. The operator is told to add a second
[[contracts]] entry with the legacy ABI. We warn. We do not auto-vendor the earlier ABI.
Oversized getLogs ranges shrink
Alchemy free-plan ranges over 10000 blocks are not supported classified as a blip, so
index_loop retried the same 81,920-block window until /ready went stalled. That phrasing is a
range cap. Chainstack's Block range limit exceeded is the same class. Both shrink.
What a nest costs, honestly
nuthatch_rpc_requests_total is HTTP POSTs: one per request or batch envelope. It cannot price a
provider bill. nuthatch_rpc_methods_total{method="…"} counts individual JSON-RPC methods,
including those inside a batch. A batch of 200 eth_getBlockByNumber is 200 on the method series
and 1 on the request series.
docs/operators.md prices Arbitrum tip-following against Alchemy pay-as-you-go as ~$134/month,
of which ~$93 is header fetches. Computation from published CU rates, not an invoice. Paid RPC (or
your own node) is the golden path; bundled public endpoints are the two-minute on-ramp.
Also on this tag
The nocturnal-nightjar machines landed in the same window and ride along: a recorded RPC tape for
bench (--record / --replay), a mutation-coverage nightly on the delightful core (red-capable,
required nowhere), and a CI gate that every documented command and flag is one the binary accepts.
Upgrading
Binary swap. On-disk state is forward-readable, dev flags are unchanged, no re-index. --rpc
behaviour is the one change an existing invocation will feel: if you passed it and relied on the
bundled public fallbacks, those fallbacks are gone. That was the bug. Minimum supported Rust is
1.95.