op-batcher: cover the safety-critical espresso batcher logic with tests - #509
Open
philippecamacho wants to merge 2 commits into
Open
op-batcher: cover the safety-critical espresso batcher logic with tests#509philippecamacho wants to merge 2 commits into
philippecamacho wants to merge 2 commits into
Conversation
Covers the untested logic listed in #496: - The active-batcher gate: every quadrant of the isBatcherActive mode check (an inverted check compiles and passes CI), the identity gate for both modes, the batcherHash low-20-byte slicing, and every shouldSkipPublishForActiveSeq path including the fail-closed error paths and the pre-fork fallback batcher never touching the contract. - nextBlockRange's reset/reorg/prune branches, in particular the safe-chain-reorg hash check that is the sole defense against re-queueing orphaned blocks to Espresso. - EnqueueBlocks reorg detection (reset must be requested via the clearState handshake, never performed inline) and the requestClearState/performClearState CAS handshake, with a concurrent regression test for the earlier data-race fix that runs under -race. - evaluateVerification's decision table: the HotShot block-count timeout with its zero-startHeight guard, the wall-clock safety backstop, and an end-to-end re-submission test where FetchLatestBlockHeight works, so the timeout path is exercised through the whole worker pipeline. - rollbackFailedStart and waitForLocalSafeHead. The latter hardcoded its one-minute anchor timeout, so the timing is now injected through waitForLocalSafeHeadWithTiming (production behavior unchanged) to make the retry and give-up paths testable, covering the caffeination gate. Closes #496. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
Review pass over the tests added for #496: - Dispatch the contract mock per (address, method) instead of selector alone: the two ABIs share several selectors (owner, version, ...), so the old table's uniqueness premise was false, and address keying makes the tests prove batcherHash is read from the contract systemConfig() returned, not merely called somewhere. Handlers now receive the resolved abi.Method, which removes the duplicated selector plumbing and the double-naming in every table entry. - Reuse eth.AddressAsLeftPaddedHash instead of a local addressAsBytes32. - Fold waitForLocalSafeHeadWithTiming back into waitForLocalSafeHead with the timing as parameters: one function, and the tests exercise exactly what production runs. - Replace the clearState handshake's goroutine choreography with a coalescing check: its bounds could not fail (atomics are treated as synchronization by the race detector), and the actual data-race regression is locked by TestEnqueueBlocksReorgDetection's requested-not-performed assertions; the comment now says so. - Drop derivable state from stuckReceiptEspressoClient, a redundant context wrapper, and a redundant nil L1Client override. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #496. Stacked on #459 (
espresso/batcher), which is where all of the code under test lives.What is covered
Active-batcher gate (
espresso_active.go,shouldSkipPublishForActiveSeq)isBatcherActivemode check (activeIsEspresso×Espresso.Enabled) — an inverted mode check compiles and passes CI, so each quadrant is pinned explicitly.batcherHashlow-20-byte slicing (with a nonzero-high-bytes case so a future versioned batcherHash can't break address extraction).shouldSkipPublishForActiveSeqpath: the fail-closed error paths, and proof that the pre-fork fallback batcher never consults the BatchAuthenticator (the mock rejects unregistered calls, and a consult would flip the result).batcherHashis read from the contractsystemConfig()returned — not merely that the method was called somewhere.nextBlockRangereset/reorg/prune branches (espresso.go)EnqueueBlocksreorg detection + clearState CAS handshake (espresso.go)derivetestblocks and a fakeChainSigner, and the transient-fetch-failure path keeps the queue for the next tick.evaluateVerification(espresso.go)startHeightguard for a tracker with no height yet), the wall-clock safety backstop, and unclassified errors treated as retryable.FetchLatestBlockHeightworks — both existing mocks failed it, sostartHeightstayed 0 and the re-submission path had never executed. The test drives a stuck transaction through the tracker, the worker'sstartHeightsnapshot, and back onto the submission queue.rollbackFailedStart/waitForLocalSafeHead(espresso_driver.go)rollbackFailedStartclears the running flag and cancels both contexts, with and without a constructed streamer.waitForLocalSafeHeadcovers the caffeination gate: anchoring at/past the point, retrying through transient sync-status failures and empty local-safe heads, the give-up error naming the height, and the zero-height (flag unset) semantics.Production change
One, minimal:
waitForLocalSafeHeadhardcoded its one-minute anchor timeout and one-second retry interval, so its retry/give-up paths were untestable as written (as noted in the issue). The timeout and retry interval are now parameters, passed as the same constants at the single production call site — behavior unchanged, and the tests exercise exactly the function production runs.Testing
go test ./op-batcher/... -count=1— all green.-race(repeated runs on the timing-sensitive ones for flake-checking).gofmt/go vetclean.🤖 Generated with Claude Code