fix(web3): querying different RPCs returns different head blocks#1702
fix(web3): querying different RPCs returns different head blocks#1702sanbotto wants to merge 4 commits into
Conversation
PR Environment DeployedYour PR environment has been deployed! Environment Details:
Components:
The environment will be automatically cleaned up when this PR is closed or merged. |
|
Just finished running a smoke test. The new code path is functionally correct against our RPC endpoints. |
PR Environment DeployedYour PR environment has been deployed! Environment Details:
Components:
The environment will be automatically cleaned up when this PR is closed or merged. |
PR Environment DeployedYour PR environment has been deployed! Environment Details:
Components:
The environment will be automatically cleaned up when this PR is closed or merged. |
joelorzet
left a comment
There was a problem hiding this comment.
Hi @sanbotto, nice fix. One question on scope: isTipBatch keys off end === range.toBlock, so only the final batch queries "latest". When the range length leaves a small remainder over the 2000 batch size (for example a fromBlock/blockCount that makes the tip batch tiny), the batch right before it ends within a few blocks of the head, and a lagging replica can still reject it with the same -32602 beyond current head. Retries don't reliably help there for the same reason they don't in the tip case, since the mismatch can persist across replicas.
Would it be worth scoping the "latest" batch to the near-head region rather than the exact last batch, so no fixed batch ever ends within replica-lag distance of the head? Low frequency, but it's the same failure one batch over.
Fixes a bug in the "Query Contract Events" web3 step where a resolved (non-user-specified)
toBlockwas computed once via a standaloneeth_blockNumbercall and then reused for a latereth_getLogscall. Because the RPC provider's endpoint is a load-balanced pool of backend nodes that do not sync in unison, the two calls could land on different endpoints, and if the log query landed on a slightly slower endpoint than the one that answered the head check, it would reject the range with-32602 block range extends beyond current head.This was discovered when an unrelated issue caused it to surface during the debugging session (see this PM doc).
The step's reported
toBlockoutput is derived only from that same query's results (the highest block among the returned events, or no forward progress if none) rather than a separategetBlockNumber()call, since a second call could itself land on a different, more-advanced replica and overstate what was actually scanned. An explicit user-providedtoBlockis left untouched so a genuine misconfiguration still surfaces as an error. Unit tests cover the retry/failover wiring and the tip-batch query against a mocked contract, verifying the"latest"tag, the max-of-events derivation, and the no-events fallback.Opening as draft since I wanna test it in a PR env.