Repository navigation
fix(watch): emit force-inclusion logs from the runtime's first block - #76
Merged
Merged
Conversation
The first block the watch saw only seeded its local chain, so its ForceInclusionQueued logs never reached revm, nor did those of blocks between startup and the first poll. Revm's queue then lagged the chain by one entry: forced execution of index i ran a different mutation in revm than onchain, and the settlement ran out of gas onchain (simulation seed 0x394b4f35...). Read the start block once, read the code and executionIndex at its hash, and seed the watch with that block so it emits each later block. Reading by hash keeps every read on the same block when requests round-robin across providers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fails enqueue() only pushes onto the queue, so it cannot fail onchain. A revert or halt when revm enqueues the logged mutation means revm's state has diverged from the chain, so fail instead of skipping the log. The runtime assumes revm's state matches the chain once startup and migration have run. Note in migrate() that it should check the queue length as well as executionIndex, and note that a queued mutation revm discards can still be force-executed onchain outside revm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Typewriter settles a whole backlog in one transaction, which can go over Monad's 30M block gas limit, so a burst of mutations failed the run with "intrinsic gas too high" before it reached validation. Raise the limit until typewriter caps a settlement's gas. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kyscott18
force-pushed
the
fix/watch-start-block
branch
from
October 26, 2026 22:09
1b07946 to
465ac5e
Compare
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.
Problem
The first block the watch saw only seeded its local chain and was never emitted, nor were the blocks between startup and the first poll. Their
ForceInclusionQueuedlogs never reached revm, so revm's queue lagged the chain. Forced execution of indexithen ran a different mutation in revm than onchain, and the settlement reverted onchain (out of gas), far from the cause.Fix
requestBlock("latest")), then read the code andexecutionIndexat its hash. Requests round-robin across providers, so pinning by hash keeps every startup read on the same block, or fails, instead of possibly reading a different fork at the same height.fromBlockis that block's hash.makeWatchseeds its local chain with it, so the first poll emits every block after it.EnqueueRevertedError/EnqueueHaltedError) instead of being skipped.enqueue()only pushes onto the queue and can't fail onchain, so a failure in revm means revm has diverged from the chain.--gas-limit 1000000000. Typewriter settles a whole backlog in one transaction, which can go over the 30M block gas limit and end a run before it reaches this bug. ATODO(kyle)says to remove it once settlement gas is capped.The runtime assumes revm's state matches the chain once startup and migration have run, so there is no per-log queue check at runtime. Two TODOs record the gaps:
migrate()should check the queue length as well asexecutionIndex.forceExecuteit afterFORCE_INCLUSION_DELAY, which changes state outside revm, andforceExecuteemits no event the watch could see.Verification
Seed
0x8b56a138d47bbafb1f65fa04c34651a20be73bf40170e3a8eae91ebbc905c443, re-run after rebasing on89ab221:main(89ab221)SettlementRevertedError: settlement transaction reverted onchainSeeds
0x394b4f35…and0x86a299ac…and a sweep of 12 random seeds all pass on this branch.tsc --noEmit, biome and the 27packages/typewriterunit tests pass, and each commit typechecks on its own.Known limits
Reorgedmessages are dropped), so a reorg across aForceInclusionQueuedlog desyncs revm's queue from the chain.🤖 Generated with Claude Code