Conversation
…de (ethereum-optimism#20064) * chore(deployer): remove OPCMv1 migration, upgrade, and dev feature code Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: remove remaining v1 fields from ReadImplementationAddresses, clean up stale comments - Remove opcmDeployer, opcmUpgrader, opcmGameTypeAdder from ReadImplementationAddresses.s.sol Output struct and Go binding (always zero, v1 inner contracts deleted) - Keep opcmInteropMigrator (live value from opcmV2.opcmMigrator()) - Remove stale OPCMv1 narration comments and TODO(ethereum-optimism#18612) references Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: opcm with zk and tests * fix: remove constructor semgrep * fix: fixing ugrade test * feat: go params * fix: update semgrep excludes * fix: update semgrep excludes * fix: merge with develop * fix: cast interface * fix: comments and tests * feat: checks in upgrade * fix: remove * feat: container in utils * fix: setup types * fix: ci needs zk game * fix: ci * fix: opcm and utils * fix: opcm and utils * fix: ci needs zk game upgrade * fix: comments and merge with develop * fix: mrge * fix: tests bug and merge * feat: revert short * feat: revert short * fix: reordering games * fix: opcmv2 tests * fix: remove duplicate * fix: remove duplicate * fix: deploy super root * fix: validator test * fix: comments * fix: comments * fix: merge with dev * fix: lint * fix: ci * fix: comments * fix: pre pr * fix: ci go game type * fix: pre pr * fix: comment * fix: comment * feat: validator and size issue * fix: tests * fix: tests * fix: tests * fix: expected validator * fix: stack too deep * test: increase test coverage * fix(ci): broken upgarde tests * fix(ci): broken upgarde tests * chore: increase OPCM validator version and increase test coverage * refactor: undo unrelated changes * fix: regenerate NUT bundle with current forge artifacts The merge from develop resolved the bundle conflict by keeping the stale version from this branch. Regenerated via `just generate-nut-bundle` to match the current compiled artifacts. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> * refactor: move validZkArgs check to LibGameArgs * fix: nut bundle * fix: nut bundle * fix: nut bundle * chore: bump OPCMV2 version --------- Co-authored-by: 0xchin <77933451+0xChin@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…eum-optimism#19997) * op-acceptance-tests: migrate TestInteropFaultProofs_IntraBlock from op-e2e Migrate the intra-block fault proof consolidation tests from op-e2e/actions/interop/proofs_test.go to op-acceptance-tests using the devstack DSL and supernode infrastructure. Six of the original seven sub-cases are ported: - CascadeInvalid / SwapCascadeInvalid (transitive invalidation) - CyclicDependencyValid (valid cross-chain cycle) - CyclicDependencyInvalid (both chains invalid) - SameChainValid / SameChainInvalid (same-chain messaging) The longDependencyChainValid case and a faithful cyclicDependencyInvalid (pure exec→exec cycle) are left as TODOs — both require constructing exec messages that reference other exec messages' ExecutingMessage events, which the SameTimestampPair API does not yet support. Closes ethereum-optimism#19010 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * op-acceptance-tests: add exec-referencing-exec intra-block test cases Add PrecomputeExecEventMessage and SubmitExecForMessage to the DSL, enabling construction of exec transactions that reference other exec transactions' ExecutingMessage events before blocks are built. Port the remaining two intra-block test cases from op-e2e: - LongDependencyChainValid: depth-10 exec chain alternating A↔B - CyclicDependencyInvalid: exec roundtrip A→B→A using fabricated pending message, matching the original action test approach Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
) Fix a handful of prose errors and malformed markdown links found across the public-docs directory: Typos / grammar: - flashblocks-and-gas-usage.mdx: "Genrally" → "Generally" - blobs.mdx: "introduced in with" → "introduced with" (duplicate word) - custom-gas-token-guide.mdx: "initent.toml" → "intent.toml" Broken markdown links (spurious `/> ` prefix breaking all href paths): - get-started.mdx: fix Supersim and Interop Docs table links - bridge-crosschain-eth.mdx: fix three Supersim / interop explainer links - deposit-transactions.mdx: fix interop guides link Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…ests (ethereum-optimism#20132) ethereum-optimism#19960 introduced a contracts-feature-tests workflow gated on c-contracts_changed, with a required-contracts-ci status that short-circuits to success via contracts-feature-tests-short when no contract files changed. But the contracts-bedrock-tests / -coverage / -upgrade / -l2-fork / -checks-fast job entries were left in the main workflow too, so every PR that touched any non-docs file ran the full contracts matrix twice. Remove the duplicates from the main workflow: - contracts-bedrock-tests (3 variants: heavy-fuzz-modified, PR, develop) - contracts-bedrock-coverage - contracts-bedrock-tests-upgrade (4 variants) - contracts-bedrock-tests-l2-fork - contracts-bedrock-checks-fast Also drop their entries from ci-gate requires and main-skip, since the required-contracts-ci status now covers the GitHub check. Kept in main: contracts-bedrock-build, contracts-bedrock-upload, check-kontrol-build, diff-fetcher-forge-artifacts, l2-chains-sync-check (these are still depended on by non-contract main-workflow jobs or produce artifacts consumed outside the contracts feature suite). As a side-effect this also resolves the duplicate &features_matrix YAML anchor.
* feat: add ProxyAdminOwnedBase to OptimismMintableERC20Factory * fix: improve tests for atomic upgrades * fix: improve tests * fix: comments
…optimism#20129) * ci: retry apt-get update on transient mirror sync failures archive.ubuntu.com periodically returns a stale Packages.gz during mirror sync, failing apt-get update with "File has unexpected size" and exit 100. This has been a recurring source of CI flakes across contracts-bedrock-coverage, rust builds, cannon builds, etc. Add a shared apt-install CircleCI command that: - passes -o Acquire::Retries=5 so apt retries individual fetches - wraps the whole update in a 3-attempt loop with 10s backoff - standardizes --no-install-recommends plumbing Replace all apt-get update + install call sites in main.yml and rust-ci.yml with this command. The one inline call inside a larger shell script (rust-build-binary) gets the same retry loop inline. ripgrep install in main.yml does not call apt-get update, so it is left untouched; docs-ci.yml uses NodeSource's setup_24.x which manages its own apt config. * ci: fail fast when apt-get update retries are exhausted Previously the retry loop would swallow the error and fall through to apt-get install, which could then succeed against a stale or missing package index. Exit 1 explicitly after the 3rd failed attempt so the job fails loudly instead of silently producing a broken environment.
…optimism#20093) The supernode was hardcoding a 2s L1 HTTP poll interval, causing 2-3x more L1 RPC requests than equivalent separate op-node deployments since L1 blocks only arrive every 12 seconds. - Add --l1.http-poll-interval flag to supernode (default 12s, matching op-node) so the shared L1 client's poll interval is configurable - Add SupernodeOwnedFlags list and warning mechanism: when users set op-node flags at the vn.all.* or vn.<id>.* level that are owned by the supernode's shared resources, a warning is logged - Validate that HTTP L1 endpoints have a positive poll interval; zero is allowed for websocket connections (disables polling) - Set poll interval to 100ms in sysgo test configs for fast CI Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…tegration (ethereum-optimism#20001) * feat(op-reth): align interop tx validity window to 86400s Change TRANSACTION_VALIDITY_WINDOW_SECS from 3600 (1 hour) to 86400 (24 hours) to match op-geth's ingressFilterTxValidityWindow spec. This constant is used for both the interop deadline set on validated transactions and the timeout passed to supervisor_checkAccessList. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs(op-reth): clarify revalidation window vs ingress timeout The revalidation window (600s) is intentionally shorter than the ingress timeout (86400s). Phase 3 evaluation confirmed the block-event-driven revalidation loop meets all 6 evaluation criteria: - Fires on every canonical block commit (~2s on OP chains) - Covers all pooled interop txs with deadlines - Evicts expired txs and revalidates stale ones - Failsafe polling (Phase 4) covers the block-gap edge case Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(op-reth): implement block builder failsafe polling Add background failsafe detection to the interop tx pool: - Add AtomicBool failsafe_enabled to SupervisorClientInner, shared via Arc across all clones - Add query_failsafe() method that calls admin_getFailsafeEnabled RPC and caches the result - Add is_failsafe_enabled() accessor for the cached state - Add poll_failsafe() background task that polls every 1s and evicts all interop txs from the pool on failsafe transition - Wire failsafe polling task in node.rs alongside the existing maintenance task, using ref+clone pattern to share the supervisor client - Narrow SupervisorClientInner visibility to pub(crate) — no external references exist - Remove Clone derive from SupervisorClientInner (AtomicBool is !Clone, inner is always behind Arc) The ingress filter already rejects new interop txs during failsafe via CheckAccessList at the source of truth. The polling task provides the eviction mechanism for already-pooled txs. No changes to the maintenance loop or payload builder are needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(op-devstack): integrate op-interop-filter for op-reth tx validation Add in-process op-interop-filter service to devstack for supernode interop presets: - Refactor startMixedOpRethNode into build+start pattern to allow injecting --rollup.supervisor-http before starting - Add startSupernodeELWithSupervisorURL for both op-geth and op-reth - Create InteropFilter wrapper (sysgo/interop_filter.go) running the filter service in-process with direct Go struct access - Add proxy pattern in supernode runtime to break circular dependency between EL nodes and filter service - Add WithInteropFilter() preset option (supernode presets only) - Add UseInteropFilter to PresetConfig - Expose InteropFilter on MultiChainRuntime and TwoL2SupernodeInterop for direct test access (SetFailsafeEnabled, Ready, FailsafeEnabled) - Add Ready(), SetFailsafeEnabled(), FailsafeEnabled() pass-through methods to filter.Service No changes to supervisor-based presets or multichain_supervisor_runtime. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(op-acceptance-tests): add interop filter acceptance tests Add acceptance tests exercising the op-reth + op-interop-filter topology with the supernode interop preset: - TestInteropFilter_IngressAcceptsValid: valid interop tx with correct cross-chain references passes through the filter - TestInteropFilter_IngressRejectsInvalid: fabricated CrossL2Inbox access list entries are rejected by the filter - TestInteropFilter_FailsafeBlocksInterop: failsafe toggle blocks new interop txs, recovery works after disabling - TestInteropFilter_NonInteropUnaffected: regular transfers succeed regardless of failsafe state - TestInteropFilter_FailsafeEvictsPooled: failsafe transition evicts existing interop txs and rejects new ones All tests use presets.WithInteropFilter() and direct InteropFilter.SetFailsafeEnabled() for in-process failsafe control. Tests are skipped by default (standard interop test pattern). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(op-devstack): defer interop filter readiness wait until after supernode starts The interop filter's chain ingesters need blocks to backfill, but the supernode (which drives block production) starts after the filter. Split the readiness wait out of startInteropFilter and call WaitForReady after the supernode and batchers are running. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test(op-acceptance-tests): keep interop filter tests unskipped All 5 tests pass with RUST_JIT_BUILD=1 DEVSTACK_L2EL_KIND=op-reth. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(op-devstack): address review findings in interop filter integration Convention fixes: - Sort imports alphabetically in multichain_supernode_runtime.go (rollup with op-node group, tcpproxy after sources) - Sort imports alphabetically in interop_filter_test.go (op-core/predeploys before op-devstack) - Remove dead execTrigger variable in FailsafeBlocksInterop test - Revert struct literal alignment to match surrounding style Test robustness: - Replace all time.Sleep waits with waitForFailsafeState() helper that confirms filter-side state then waits for 2 L2 blocks (guarantees op-reth's 1s polling task has had at least 2 poll cycles) - Make initMsg.Tx.Result.Eval() failures hard errors with require.NoError instead of silently skipping the failsafe assertion Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(op-reth): use cached failsafe state for ingress rejection and maintenance eviction Add InvalidCrossTx::FailsafeEnabled variant for fast-path ingress rejection without RPC round-trip. Add failsafe eviction to the block-event maintenance loop as belt-and-suspenders with poll_failsafe. Fix gofmt import ordering in multichain_supernode_runtime.go. Tighten IngressRejectsInvalid test (10s timeout + explicit rejection assert). Merge FailsafeBlocksInterop and FailsafeEvictsPooled into FailsafeLifecycle. Extend NonInteropUnaffected to test both chains. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(op-reth): unify interop tx identification under is_interop_tx Move is_interop_tx to interop.rs as the single pub(crate) helper for identifying interop transactions by access list. Use it in maintain and poll_failsafe eviction paths instead of interop_deadline().is_some(), ensuring all codepaths use the same structural check. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(op-acceptance-tests): use single-attempt submit in IngressRejectsInvalid The test used bob.Plan() which includes WithRetrySubmission (5 retries, exponential backoff). Under CI load, retrying the rejected tx exhausted the 10s context timeout, causing the test to see DeadlineExceeded instead of the filter's explicit rejection error. Fix: override with WithTransactionSubmitter (no retries) and evaluate tx.Submitted instead of tx.Included, so the filter rejection propagates on the first attempt. Also unifies interop tx identification under is_interop_tx in interop.rs so all codepaths (ingress, maintenance, failsafe eviction, reorg) use the same structural access-list check. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(op-acceptance-tests): address review feedback on interop filter tests - Remove TestInteropFilter_IngressAcceptsValid (redundant with existing message tests; enable WithInteropFilter() on TestInteropHappyTx instead) - Remove waitForFailsafeState helper and its 2-block wait heuristic - Relax failsafe error assertion to accept any rejection (both op-reth fast-path and filter HTTP path correctly reject during failsafe) - Replace retry.Do0 recovery loop with single init/exec attempt - Simplify failsafe propagation to single WaitForBlock() calls Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(op-acceptance-tests): accept interop rejection errors from any EL backend Add interopTxRejectedError helper that matches rejection messages from op-geth ("transaction filtered out"), op-reth ("interop failsafe is active"), and op-interop-filter ("failed to parse access entry", "failsafe is enabled"). Use it in both IngressRejectsInvalid and FailsafeLifecycle tests so they pass regardless of which component rejects the transaction. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(op-reth): reduce TRANSACTION_VALIDITY_WINDOW_SECS to 2 hours Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(op-reth): rename to CHECK_ACCESS_LIST_TIMEOUT_SECS and unify timeout Rename TRANSACTION_VALIDITY_WINDOW_SECS to CHECK_ACCESS_LIST_TIMEOUT_SECS and remove the separate TRANSACTION_VALIDITY_WINDOW constant in maintain.rs, sharing a single 7200s timeout for both ingress validation and revalidation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(op-acceptance-tests): use test context instead of context.Background Replace context.Background() with gt.Context() / t.Ctx() so that test contexts are properly cancelled on test failure or timeout. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(op-acceptance-tests): document untested txpool eviction behavior Add a comment explaining why txpool eviction on failsafe activation is not covered: StopSequencer only prevents new payload requests but an in-flight engine API payload can still land, creating a race between block inclusion and failsafe eviction. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: rustfmt --------- Co-authored-by: wwared <541936+wwared@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…mism#20126) * ci: bump factory workflow to node24-compatible version * ci: fix factory attest step (bump to corrected SHA)
…thereum-optimism#20121) * chore(ci): register ci-base-clang image for factory builds Add ci-base-clang to docker-bake.hcl and docker-images.json so the factory workflow builds and publishes the image to Artifact Registry. The image provides cimg/base with clang pre-installed for Rust bindgen jobs, eliminating the ~9 minute apt-get install on every CI run. Depends on ethereum-optimism#20117 which adds the Dockerfile. Closes ethereum-optimism#20119 * chore(ci): add ci-base-clang image and register for factory builds Add a CI base image that pre-bakes clang, llvm-dev, and libclang-dev onto cimg/base:2026.03 for Rust bindgen jobs. Register it in docker-bake.hcl and docker-images.json so the factory workflow builds and publishes to Artifact Registry with provenance attestation. Eliminates the ~9 minute apt-get install on every Rust CI run. Based on the Dockerfile from ethereum-optimism#20117. Closes ethereum-optimism#20119 * chore(ci): apply security patches in ci-base-clang image Run apt-get upgrade before installing packages to pick up security patches that may not yet be in the upstream cimg/base image.
* feat: cleanup contracts * fix: remove fee splitter as predeploy * feat: remove references from l2cm * feat: remove genesis and deploy script paths * fix: tests cleanup * fix: linting * fix: cleanup go packages * fix: deploy configs * fix: further op packages fixes * fix: go tests * fix: just pr * fix: missed refferences in tests * fix: tests and lint * fix: conflicts * fix: missed cleanup * chore: keep audits * fix: conflicts * fix: conflicts * fix: ci * fix: conflicts * fix: conflicts
ethereum-optimism#20140) ethereum-optimism#19685 added zkDisputeGameImpl to VerifyOPCM's implementations map but forgot the corresponding skip path for when DEV_FEATURE__ZK_DISPUTE_GAME is off. OPCM returns address(0) for zkDisputeGameImpl in that case, so VerifyOPCM treats the 0-byte deployed code vs 13.5KB expected artifact as a verification failure. This broke contracts-bedrock-tests-develop on every matrix cell that doesn't set ZK_DISPUTE_GAME (11 of 12), but wasn't caught at merge time because the -develop job runs post-merge only and isn't in required-contracts-ci. Three tests were failing on develop for the same root cause: - test_run_succeeds — VerifyOPCM_Failed, ZK ref mismatches artifact - test_run_implementationDifferentInsideImmutable_succeeds — same - test_run_implementationDifferentOutsideImmutable_reverts — panic 0x11 (vm.randomUint(0, implCode.length - 1) underflows when ZK ref's code is empty) Fix mirrors the existing SuperDisputeGame skip path: - VerifyOPCM.s.sol: skip-or-fail branch inside _verifyOpcmContractRef plus _isZKDisputeGameEnabled / _isZKDisputeGameImplementation helpers. - VerifyOPCM.t.sol: skip the ZK ref in the byte-scramble loops when the feature is off so implCode.length == 0 doesn't underflow, and unconditionally skip ZK in test_runSingle_succeeds (mirrors the existing super-games skip with TODO).
…m-optimism#20142) SchemaResolver (src/vendor/eas/resolver/SchemaResolver.sol) is an abstract contract with zero concrete subclasses anywhere in the monorepo — verified by direct "is SchemaResolver" grep and import-graph analysis. The companion interface ISchemaResolver is still used by EAS.sol, SchemaRegistry.sol, and ISchemaRegistry.sol — that stays. Net: -165 LoC. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…imized (ethereum-optimism#20143) * fix(contracts): skip ZKDisputeGame in VerifyOPCM when feature disabled ethereum-optimism#19685 added zkDisputeGameImpl to VerifyOPCM's implementations map but forgot the corresponding skip path for when DEV_FEATURE__ZK_DISPUTE_GAME is off. OPCM returns address(0) for zkDisputeGameImpl in that case, so VerifyOPCM treats the 0-byte deployed code vs 13.5KB expected artifact as a verification failure. This broke contracts-bedrock-tests-develop on every matrix cell that doesn't set ZK_DISPUTE_GAME (11 of 12), but wasn't caught at merge time because the -develop job runs post-merge only and isn't in required-contracts-ci. Three tests were failing on develop for the same root cause: - test_run_succeeds — VerifyOPCM_Failed, ZK ref mismatches artifact - test_run_implementationDifferentInsideImmutable_succeeds — same - test_run_implementationDifferentOutsideImmutable_reverts — panic 0x11 (vm.randomUint(0, implCode.length - 1) underflows when ZK ref's code is empty) Fix mirrors the existing SuperDisputeGame skip path: - VerifyOPCM.s.sol: skip-or-fail branch inside _verifyOpcmContractRef plus _isZKDisputeGameEnabled / _isZKDisputeGameImplementation helpers. - VerifyOPCM.t.sol: skip the ZK ref in the byte-scramble loops when the feature is off so implCode.length == 0 doesn't underflow, and unconditionally skip ZK in test_runSingle_succeeds (mirrors the existing super-games skip with TODO). * test(contracts): skip VerifyOPCM_Run_Test on coverage only, not unoptimized These three tests compare a locally-compiled deployed address to a locally-compiled artifact on disk. Both sides come from the same build, so the comparison holds under any Foundry profile. Coverage mode does break it (the coverage run instruments the deployed code but not the on-disk artifact), but an unoptimized profile like liteci does not. ethereum-optimism#19332 mechanically renamed every skipIfCoverage() → skipIfUnoptimized() in this file while introducing the liteci profile. That over-broadened the skip: on PRs we now run liteci via contracts-bedrock-tests, and VerifyOPCM_Run_Test short-circuits there, so the script's correctness is only exercised post-merge by contracts-bedrock-tests-develop. That is how the ZK-dispute-game skip miss from ethereum-optimism#19685 slipped past merge and landed red on develop. Reintroduce skipIfCoverage() as a distinct helper and apply it to the three tests whose only real compiler-output dependency is coverage instrumentation: - test_run_succeeds - test_run_implementationDifferentInsideImmutable_succeeds - test_run_implementationDifferentOutsideImmutable_reverts The other skipIfUnoptimized() uses in this file are left alone — some of them genuinely depend on optimized bytecode (e.g. immutable-variable tests, preimage-oracle checks with fixed selectors) and are worth auditing separately if/when someone wants to widen the PR coverage. Stacked on fix/verifyopcm-zk-dispute-skip so the PR-level liteci run doesn't go red on non-ZK matrix cells; land that one first.
…#20141) * chore(contracts): remove 7 unreferenced interfaces Found via import-graph analysis — all 7 have zero importers anywhere in the monorepo: - IL1CrossDomainMessengerV160.sol — also already broken (imports the non-existent IOptimismPortal.sol; only IOptimismPortal2.sol exists) - IL1StandardBridgeV160.sol — archival v1.6.0 sibling - IHasSuperchainConfig.sol — only trace was an entry in the interfaces checker's own exclusion list - IOPContractsManagerUtilsCaller.sol — vestigial stub for an abstract contract; add the concrete OPCM sub-contract to excludeSourceContracts alongside the existing OPContractsManagerStandardValidator - IERC7802.sol — the docs tutorials that reference IERC7802 import it from lib/interop-lib/, not from here - IMintableAndBurnableERC20.sol — zero importers - IERC20Solady.sol — zero importers Companion edit: drop the now-dead "IHasSuperchainConfig" line from the excludeContracts list in scripts/checks/interfaces/main.go. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(contracts): update interface checker exclusion list Companion to the prior commit — interfaces/main.go was modified but not staged before the first commit landed. - Drop "IHasSuperchainConfig" from excludeContracts (the interface file it referenced was deleted) - Add "OPContractsManagerUtilsCaller" to excludeSourceContracts next to the sibling OPContractsManagerStandardValidator (abstract OPCM sub-contract with no interface, same pattern) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…imism#19976) * fix(op-devstack): stabilize flaky TestFlashblocksStream Fix two compounding bugs in the op-node error callback: 1. Goroutine safety: Replace Require().NoError (calls FailNow/Goexit) with Errorf in l2_cl_opnode.go and l2_cl_supernode.go. The errFn callback runs from a background goroutine, so FailNow only exits that goroutine — leaving the test hanging until timeout. 2. Wrong error reported: Pass errCause (the original critical error) to errFn instead of the stop error. The stop context is pre-cancelled, so Stop returns "context canceled" which obscures the real failure. Refs: ethereum-optimism#19883 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(flashblocks): wait for builder P2P sync during rapid block driving When driveViaTestSequencer builds blocks rapidly, the sequencer EL produces blocks faster than P2P can propagate them to the builder EL (op-rbuilder). Under CI load, the builder receives an FCU referencing a parent block it hasn't synced yet, causing "missing parent header" → InvalidPayloadAttributes → CriticalError → test hang. Poll the builder's L2EthClient after each driven block to ensure it has synced the block before driving the next one. This also benefits TestFlashblocksTransfer which uses the same helper. Refs: ethereum-optimism#19883, ethereum-optimism#19934 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: wwared <541936+wwared@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…test (ethereum-optimism#20071) Assert that the P256VERIFY precompile gas cost increases from 3,450 (RIP-7212) to 6,900 (EIP-7951) at Karst activation. Also update the karst() precompile set in op-revm to swap secp256r1::P256VERIFY for secp256r1::P256VERIFY_OSAKA. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…thereum-optimism#20062) * feat(kona-hardforks): add NUT bundle types and deposit tx conversion Add types and conversion logic for JSON-defined Network Upgrade Transaction bundles, enabling future forks to define NUTs as data rather than hardcoded Rust structs. * refactor(op-alloy): move NUT bundle types to op-alloy-consensus Address review feedback: NUT types only depend on alloy, so they belong in op-alloy-consensus where any Rust tooling can use them without pulling in kona. Also uses thiserror, improves test fixtures, and adds explicit hash/encoding regression assertions. * refactor(kona-hardforks): drop unused NUT type re-exports The re-exports of NetworkUpgradeTransaction/NutBundle/NutBundleError from op_alloy_consensus aren't consumed by kona-hardforks or any other crate yet. Add them back when the first downstream user appears. Made-with: Cursor --------- Co-authored-by: maurelian <maurelian@protonmail.com>
ethereum-optimism#20069) Assert that OP Stack chains can build blocks exceeding the EIP-7934 10 MiB RLP block size limit. Submits many transactions with large calldata under a 200M gas limit and verifies a single block exceeds 10 MiB in total transaction data. Also adds WithGasLimit to L2Configurator and WithL2GasLimit deployer option to support custom L2 block gas limits in tests. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…L2 test (ethereum-optimism#20112) * test(op-acceptance-tests): add EIP-7934 block size limit disabled test Assert that OP Stack chains can build blocks exceeding the EIP-7934 10 MiB RLP block size limit. Submits many transactions with large calldata under a 200M gas limit and verifies a single block exceeds 10 MiB in total transaction data. Also adds WithGasLimit to L2Configurator and WithL2GasLimit deployer option to support custom L2 block gas limits in tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(op-acceptance-tests): deduplicate Karst fork setup in Osaka L2 tests Extract shared setup code into setupKarstForkTest helper to reduce repetition across four tests that all activate Karst at block offset 3. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ckTimes tests as flaky (ethereum-optimism#20159) Removes MarkFlaky("ethereum-optimism#19828") from TestPreinteropFaultProofs_VariedBlockTimes and its _FasterChainB variant. Held as draft until a local 15x sweep confirms stability. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ethereum-optimism#20135) * ci: pin ci-base-clang image for Rust jobs and skip runtime apt-install Adds a new pipeline parameter `rust_base_image` pinned by digest to the factory-built ci-base-clang image (cimg/base + clang/llvm-dev/libclang-dev). Switches Rust job executors in main.yml, rust-ci.yml, and rust-e2e.yml to use this image, and replaces the runtime `apt-install clang` step with a fast `command -v clang` verification. Provenance of the pinned digest is verified by a follow-up GitHub Actions workflow (sub-issue ethereum-optimism#20122). Closes ethereum-optimism#20120 * ci: keep apt-install fallback for machine-executor jobs The previous commit replaced the Install clang step with a hard verify, but kona-cargo-lint, kona-build-fpvm, and kona-host-client-offline run on `machine:` executors (raw Ubuntu VMs) where clang isn't pre-baked. Add a guarded fallback: if clang is already present (docker jobs using c-rust_base_image), skip; otherwise apt-install as before. * ci: add apt-get retry loop in clang fallback for machine VMs The previous fallback used a bare `apt-get update` which timed out on machine-executor jobs against transient Ubuntu mirror sync failures. Use the same retry loop as the apt-install orb (3 attempts, 10s sleep). * ci: fail fast if clang missing in rust-prepare Remove apt fallback in rust-prepare (review feedback). Install clang on machine executors via apt-install before rust-prepare. * ci: quote rust-prepare command for valid YAML Unquoted ERROR: in the shell string was parsed as a YAML mapping key and broke CircleCI config generation. * ci: quote rust-ci rust-prepare command for valid YAML Same unquoted ERROR: issue as main.yml; path-filtering merges rust-ci.yml and the setup job failed YAML validation.
…ust test (ethereum-optimism#20161) The `just test` recipe hardcoded `-count=1 -timeout 30m`, which blocked callers from requesting e.g. repeated runs with `-count=10` for flake triage. Now the defaults are applied only when the flag is absent from the forwarded args, so callers can override either. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…hereum-optimism#20171) Adds a workflow that reads the pinned ci-base-clang digest from .circleci/config.yml and runs `gh attestation verify --bundle-from-oci` against it, enforcing the attestation was signed by the factory reusable workflow for `ethereum-optimism/optimism` on `refs/heads/develop`. The workflow runs on push to develop and on PRs that touch the pin or the workflow itself, so a digest swap to any unattested or off-branch image blocks the merge. Also repins `rust_base_image` to the digest built from develop (sha256:00f641689576d7393d83f6fd49fe1592006148305999f1ba2fc4f1f9d2e8a342) so the new check passes on merge. Closes ethereum-optimism#20122
…ptimism#20170) The branch build `prep` job was failing to install `just` via the `jdx/mise-action`. Newer mise releases (>=2026.4.18) changed the `ubi` backend to bypass the `mise-versions.jdx.dev` cache and query GitHub directly, which broke tag resolution for projects like casey/just that use a non-`v` release tag prefix. The resulting HTTP 404 against `https://api.github.com/repos/casey/just/releases/tags/v1.46.0` caused the prep job to fail. Pin the mise version in the composite action to 2026.2.2 to match the mise version used by the CircleCI `install-mise` orb command (`ethereum-optimism/circleci-utils`). Refs failing run: https://github.com/ethereum-optimism/optimism/actions/runs/24638787954
…-optimism#19973) * feat(op-node): offset_derived for EL-sync safe/finalized retraction Add duration-based offset_derived (rollup BlockTime -> block steps) so EL-sync completion sets safe, finalized, and local-safe to an ancestor of the unsafe tip; unsafe stays at tip. Uses a single L2BlockRefByNumber call instead of walking N parent hashes. Default --syncmode.offset-derived is 168h (7d). Plumb through sync config, CLI, EngineController FCU, and FindL2Heads recovery. sync.L2Chain now includes L2BlockRefByNumber. Tests use table-driven subtests. Made-with: Cursor * test(op-e2e): add e2e test for OffsetELSafe after EL sync Refactor PrepareELSyncedNode to accept expected safe/finalized block numbers, and add TestELSyncOffsetELSafe demonstrating that safe and finalized heads retract from the tip when OffsetELSafe is configured. Made-with: Cursor * test(acceptance): add OffsetELSafe acceptance test for EL sync Plumb OffsetELSafe through L2CLConfig into the devstack sync config, and add TestELSyncSafeRetractedByOffset which verifies that safe and finalized heads are retracted from the unsafe tip after EL sync. Made-with: Cursor * test(acceptance): add expected retraction check to OffsetELSafe test Log a warning when observed retraction doesn't match the expected 5-block retraction (10s offset / 2s block time). Made-with: Cursor * fix(op-node): address OffsetELSafe self-review feedback - Default to 0 (full nodes can't progress safe derivation from offset) - DurationToBlocks uses ceiling division so the retraction always covers the full requested duration (e.g. 15s / 4s blockTime = 4) - Extract OffsetBlockNum helper to deduplicate clamped-offset logic between start.go and engine_controller.go - Rename `span` to `maxRetract` for clarity Made-with: Cursor * lint * fix(op-node): align EL-sync offset test with ceiling division The test expected floor(offset/BlockTime) retraction but DurationToBlocks uses ceiling division. With offset=5s and BlockTime=2, ceil(5/2)=3 retracts to genesis (block 0), not block 1. Update expected values and test name accordingly. Made-with: Cursor * fix(op-node): never retract finalized/safe behind prior values after EL sync With SupportsPostFinalizationELSync, EL sync can start even when there is an existing finalized head (Erigon/Reth). The offset retraction must not move finalized or safe backwards, so clamp each against its prior value before applying the forkchoice update. Made-with: Cursor * fix(op-node): reject OffsetELSafe when CL sync is enabled OffsetELSafe only applies to EL sync completion. With CL sync it would needlessly retract the safe head during FindL2Heads recovery paths. Fail at startup instead of silently misbehaving. Made-with: Cursor * fix(acceptance): make OffsetELSafe test deterministic Stop the batcher before advancing the sequencer so new blocks are unsafe-only. This creates a permanent gap between safe and unsafe that derivation can never close, eliminating timing-dependent flakes. Made-with: Cursor * feat(op-supernode): interop log backfill depth and validation gating Add --interop.log-backfill-depth to pre-ingest initiating logs from T_lo = max(activation, tip - depth) through local safe. ChainContainer gains TimestampToBlockNumber. Backfill and T_lo math live in log_backfill.go (run loop, ceiling snapshot, skip-verify gating). SkipPersistFrontierLogs on advance when logs were backfilled. Config validation and table-driven tests; log_backfill_test.go covers bounds + integration. Made-with: Cursor * refactor(op-supernode): replace skip-verification with activation advancement Instead of maintaining a backfillCeilingTimestamp and skip-verification machinery, advance activationTimestamp past the backfilled range after log backfill completes. VerifiedAtTimestamp already treats timestamps before activation as verified, so this naturally does the right thing without shouldSkipVerification, SkipPersistFrontierLogs, or maxL1Inclusion. Made-with: Cursor * fix: remove stale kona and reth submodule entries These gitlink entries were left behind when the rust workspace unification (ethereum-optimism#19034) moved kona to rust/kona/ and removed reth. The dangling references break CI checkout because .gitmodules has no matching URLs. Made-with: Cursor * PR Comments - Retry log backfill when virtual nodes aren't ready instead of failing - Remove deterministic chain ID sorting in runLogBackfill - Delete stale signer_grace_period_Feature.md - Add syncStatusOverride to mock for dynamic SyncStatus control in tests Made-with: Cursor * PR Comments 2 Made-with: Cursor * Acceptance Testing Made-with: Cursor * ensure log backfill in tests Add a test-only primitive to hot-restart just the interop activity (optionally wiping its logs DBs and pre-injecting synthetic backfill failures) while the rest of the supernode keeps running, and use it to drive deterministic happy- path and retry acceptance tests that assert backfill actually populates the logs DB against a fully synced virtual-node cluster. Made-with: Cursor * PR review: fixes and thin-wrapper collapse Addresses reviewer feedback on the interop log-backfill PR and cleans up the test-control surface that grew during the review cycle. Review-response fixes: - Add TestLogBackfill_AsymmetricMultiChain covering the skipped-chain / runtime-activation edge case, backed by a new timestampToBlockNumberOverride hook on mockChainContainer. - Protect simpleChainContainer.verifiers with an RWMutex so ReplaceVerifier (used by RestartInteropActivity) cannot race with VerifierCurrentL1s / VerifiedAt readers. - Protect Supernode.activities with an RWMutex so RestartInteropActivity's slice swap cannot race with onChainReset / InteropActivity readers. - Move the DataDir precheck in RestartInteropActivity ahead of old.Stop() so a misconfigured call fails before tearing down the old activity. - Demote the per-attempt "log backfill: computed lower bound" log line from Info to Debug; the end-of-backfill summary remains the user-visible signal. Thin-wrapper collapse (~180 lines net reduction): - Replace eight pass-through methods on Supernode (PauseInteropActivity, ResumeInteropActivity, InteropBackfillAttempts, InteropBackfillCompleted, InteropActivationTimestamp, InteropRuntimeActivationTimestamp, InteropFirstSealedBlock, InteropLatestSealedBlock) with a single InteropActivity() accessor. RestartInteropActivity stays - it has real logic. - Do the same on sysgo.SuperNode, shrinking the test-control surface to InteropActivity() + RestartInteropActivity. - Shrink stack.InteropTestControl from 11 methods to 2. - Introduce a dsl.Supernode.interopActivity() helper so each DSL method does a single nil-guarded dereference and then calls the real interop method directly (PauseAt, BackfillAttempts, FirstSealedBlock, ...). Made-with: Cursor * fix(op-supernode): fail backfill when a chain is behind T_lo runLogBackfill previously computed minLocalSafeTime over every chain, including ones whose local-safe was behind T_lo in block space and therefore got silently skipped by the "startNum > localSafeNum" branch. After backfill, runtimeActivationTimestamp = minLocalSafeTime + 1; the main loop then advanced past the unbackfilled range on the skipped chain, leaving its [T_lo, minLocalSafeTime] logs unsealed. Any future executing message that referenced an initiating message in that range would be unverifiable. By the supernode's own invariants (minCrossSafeTime <= every chain's localSafeTime, and T_lo <= minCrossSafeTime) the skip branch is unreachable in steady state; hitting it means SyncStatus and TimestampToBlockNumber disagreed (chain still warming up, derivation indexing lag, etc.). The right response is to fail the round and let the retry loop re-query once the inconsistency resolves, rather than silently lose logs. Replace the skip branch with a fail-fast error that names the chain and both block numbers. Fold localSafeTime into minLocalSafeTime only after the consistency check, so the runtime-activation advancement always reflects the set of chains whose logs DB is now populated up to T_lo. Rewrite TestLogBackfill_AsymmetricMultiChain as a healthy three-chain case with asymmetric cross-safe and local-safe positions, and add TestLogBackfill_FailsWhenChainBehindTLo to pin the new safety property. Made-with: Cursor * refactor(op-supernode): export backfill-lower-bound sentinel, split multichain tests Follow-up to the fail-fast fix: callers now have a sentinel (ErrChainBehindBackfillLowerBound) to match on, and the error message includes localSafeTime and minCrossSafeTime so the operator can see exactly which SyncStatus field is inconsistent. Split TestLogBackfill_AsymmetricMultiChain back into a clean healthy three-chain case (all chains backfill, runtimeActivation pins to the smallest localSafe+1) and a dedicated TestLogBackfill_FailsWhenChainBehindLowerBound that uses the timestampToBlockNumberOverride hook to force the inconsistent-SyncStatus path and asserts the error wraps the sentinel and runtimeActivation stays at activationTimestamp on failure. Made-with: Cursor * refactor(op-acceptance-tests): inline AssertBackfillCovered wrapper AssertBackfillCovered in backfillutil was a two-line shim around Supernode.AssertBackfillCovers. Inline the call at both test sites so the DSL assertion is reached directly, and drop the helper. Matches the thin-wrapper cleanup already done across the DSL/stack/sysgo layers in this PR. Made-with: Cursor * refactor(op-supernode): use op-service/clock.SleepCtx for backoff waits Swap the three wall-clock calls in Interop.Start for clock.SystemClock.SleepCtx. Two consequences beyond the import swap: - The backfill retry loop's `select { <-ctx.Done; <-time.After }` becomes a single SleepCtx call with identical semantics. - The main loop's `time.Sleep(errorBackoffPeriod)` and `time.Sleep(backoffPeriod)` previously ignored ctx mid-sleep, so a cancellation would stall the goroutine for up to 2s. SleepCtx returns ctx.Err() immediately on cancel, and Start now propagates that error so Stop is observed without waiting out a backoff. The `time` import stays for the `time.Second` / `time.Duration` constants on the backoff vars, which clock also uses. Made-with: Cursor * fix(op-supernode): allow rollup-derived activation to satisfy backfill pairing config.Check() previously rejected --interop.log-backfill-depth=... unless --interop.activation-timestamp was also set on the CLI, but activation can equally come from each chain's rollup config (vnCfg.Rollup.InteropTime). CLIConfig can't see rollup configs, so the old pairing check ran in the wrong layer and blocked a valid configuration. Move the pairing check to supernode.New, after resolveInteropActivationTimestamp has picked a source (CLI override wins, otherwise consistent rollup configs). Depth+rollup now works; depth with no activation source anywhere still fails, with an error that names both remediation paths. Extract the check into checkLogBackfillRequiresInteropActivation so it's unit-testable without standing up a full supernode, and update the config-level test to only assert Check()'s actual contract (well-formed CLI inputs, independent of rollup). Made-with: Cursor * lint and move util to testutil * lint * address karlfloersch PR comments - Remove backfillFailuresToInject test-only injection and the synthetic failure path in runLogBackfill; retry behavior is already covered by the TestLogBackfill_RetriesWhenVirtualNodesNotReady / TestLogBackfill_RetriesStopOnContextCancel unit tests, so keeping the injection check in the production function was unnecessary noise. - Drop the preInjectBackfillFailures parameter from RestartInteropActivity across supernode / sysgo / stack / dsl layers. - Delete the now-redundant backfill/retry acceptance test; happy path still exercises restart + wipe + backfill end-to-end. - Revert unrelated findMonorepoRoot bump (10 -> 6). - Restore "/restart" in the SuperNode.snCfg/vnCfgs comment; Stop+Start is a restart of the whole supernode and uses those stored configs. Made-with: Cursor * fix(op-supernode): accept pre-activation pairing anchor in backfill When interop activation does not land on a (genesis + k*blockTime) boundary, rollup.TargetBlockNumber(activation) floors to the last block whose Time() is strictly before activation. That block *is* the chain state as of the fork — the correct pairing anchor for the first post-activation block — but the previous check in verifyCanAddTimestamp required ts >= activationTimestamp, so backfill's first seal returned ErrPreviousTimestampNotSealed and the retry loop in Interop.Start spun forever with a misleading "virtual nodes may not be ready" warning. Relax the empty-DB backfill branch to ts+blockTime > activationTimestamp: the first seal may be up to one blockTime before activation, and strictly earlier ts still errors. The main-loop path (isBackfill=false) is untouched. AssertBackfillCovers' first-timestamp invariant is widened in lockstep. Add TestLogBackfill_MisalignedActivation, which wires blockTime=3, activation=1000, and a floor-rounding TimestampToBlockNumber so the mock exercises the exact misalignment path. The mock grows blockTimeOverride and blockInfoTimeFn hooks; FetchReceipts now derives parentHash from blockID.Number-1 (previously from ts-1, which coincided only when blockNum==ts). Made-with: Cursor * fix(op-devstack): raise findMonorepoRoot search depth to 10 The backfill acceptance tests live at op-acceptance-tests/tests/supernode/interop/backfill/happy (6 levels under the monorepo root), which exceeds the 6-iteration cap and trips "failed to find monorepo root using packages/contracts-bedrock". The earlier 6->10 change was rolled back per review feedback, but the reviewer and I missed that this specific test depth required it. Reinstate 10 with a comment naming why. Made-with: Cursor
…-optimism#20190) Replaced multiple `ci-gate-skip` jobs with a single `ci-gate` job that always succeeds and includes a context for the CircleCI API token. This simplifies the workflow and ensures consistent execution of the CI pipeline.
… number (ethereum-optimism#20162) The is_interop_active() function expects a block timestamp but was receiving a block number. Since block numbers are always smaller than timestamps, interop was never detected as active in the proof driver, causing EndOfSource errors to be silently swallowed instead of propagated to the caller. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(contracts-bedrock): fix contract typos * chore(contracts-bedrock): clean up contract comments * chore(contracts-bedrock): update contract version checks
… update in CL-sync mode (ethereum-optimism#20310) When an execution client (e.g. op-reth) is restarted, it may lose its in-memory canonical state and return SYNCING to forkchoice updates. Without this check, the SYNCING response gets recorded as the last-accepted forkchoice via `e.lastForkchoice = fc`, and the subsequent `if fc == e.lastForkchoice { return nil }` guard suppresses further FCU retries — op-node stalls until restarted. This fix uses the existing checkForkchoiceUpdatedStatus method to validate the FCU response before recording lastForkchoice. In CL-sync mode, SYNCING triggers a ResetError, so FindL2Heads re-discovers the EL's actual chain state. In EL-sync mode, SYNCING remains accepted (existing behavior preserved). This resolves the issue where op-reth reboots require an op-node restart to recover. Co-authored-by: Samuel Stokes <sam.adam.stokes@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…um-optimism#20352) * fix(op-node/engine-controller): management of e.localSafeHead in initializeUnknowns. Fix initializUnknowns to set localSafeHead to a nonzero ref rather than to e.SafeL2Head() which would erroneously just set it to zero again. Rename SetSafeHead to SetDeprecatedSafeHead Mark the method as deprecated for supervisor-only pathways. * Fix typo in SetDeprecatedSafeHead doc comment * Add regression test for localSafeHead initialization bug Tests that initializeUnknowns properly sets localSafeHead when restarting op-node. The bug caused safe head to never advance after restart because SetSafeHead was setting deprecatedSafeHead instead of localSafeHead.
…optimism#20288) Mirrors kona PR op-rs/kona#3158. When set (non-zero), bypasses the beacon /eth/v1/config/spec fetch and uses the given value as SECONDS_PER_SLOT. Useful for devnets where the beacon spec endpoint is unavailable (e.g. anvil).
…thereum-optimism#20347) * fix(op-fetcher): guard against zero mipsImpl before calling oracle() Guard mipsImpl != address(0) before calling oracle() so the script handles disabled or zeroed-out permissioned game implementations gracefully. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * use LibGameArgs in _processFaultProofs primary path --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…imism#20303) * feat(kona-interop): add cycle detection to MessageGraph MessageGraph validated executing messages independently via check_single_dependency, which cannot detect circular dependencies between same-timestamp cross-chain messages. op-supernode rejects these cycles using Kahn's topological sort; kona accepted them. Add cycle detection to MessageGraph::resolve() that runs before per-message validation. The implementation matches op-supernode's buildCycleGraph/checkCycle semantics: intra-chain sequential edges, cross-chain edges via executingMessageBefore, and Kahn's algorithm to identify cycle participants while sparing bystander chains. - Add CyclicDependency error variant to MessageGraphError - Add executing_log_index to EnrichedExecutingMessage for graph construction - Handle CyclicDependency in the consolidation retry loop - Fix test_derive_and_resolve_simple_graph_with_cycles to assert rejection - Add tests for triangle cycles, one-way deps, and bystander chains Closes ethereum-optimism#20196 * improve tests * fmt/clippy * fix(kona-interop): filter historical-timestamp EMs from cycle graph Address review feedback on ethereum-optimism#20303 (ajsutton). Layer a second filter on detect_cycles so an executing message is admitted into the same-timestamp cycle graph only when its *executing block* timestamp **and** its referenced *initiating message* timestamp both equal the target timestamp. Previously only the executing-block timestamp was checked, matching op-supernode's primary filter in verifyCycleMessages but missing the secondary filter in buildCycleGraph (em.Timestamp == ts, sourced from MessageIdentifier.Timestamp). Without the secondary filter, EMs that reference historical initiating messages were drawn into the current-ts graph and could fabricate spurious cross-chain edges through executingMessageBefore, producing false-positive cycles. Fold in the regression test from ethereum-optimism#20305 and add a direct unit test for the new filter condition. Generalize the make_em helper so tests can specify the initiating-message timestamp independently of the executing block timestamp. Tighten the MessageGraph doc comment: blocks in the graph may be at different timestamps, one per chain, and expand the CyclicDependency variant doc to record that each error represents a single cycle at a single timestamp; multi-timestamp cycles surface iteratively through the consolidation retry loop. * test(kona-interop): add op-supernode parity cycle-detection cases (ethereum-optimism#20354) Mirrors four boundary cases from op-supernode's cycle_test.go that did not have Kona equivalents: - triangle with missing leg (cycle_test.go:454-462) - diamond pattern (cycle_test.go:268-287, from TestCheckCycle) - bystander chain refs absent chain (cycle_test.go:418-426) - multi-hop one-way dependency (cycle_test.go:428-434) All added at the existing `test_detect_cycles_*` layer using the existing `make_em` helper — no new test scaffolding. Diamond layout co-locates the sink EM on the same chain as one of its parents so the intra-chain edge provides the second incoming dependency. Co-authored-by: wwared <541936+wwared@users.noreply.github.com> --------- Co-authored-by: wwared <wwared@users.noreply.github.com> Co-authored-by: wwared <541936+wwared@users.noreply.github.com>
* U19 Notice page update Updates U19 notice page with additional details for improved clarity * Clarify update instructions for op-reth version * Apply suggestion from @geoknee Co-authored-by: George Knee <georgeknee@googlemail.com> * Update docs/public-docs/notices/upgrade-19.mdx Co-authored-by: soyboy <85043086+sbvegan@users.noreply.github.com> * Apply suggestion from @sbvegan Co-authored-by: soyboy <85043086+sbvegan@users.noreply.github.com> --------- Co-authored-by: George Knee <georgeknee@googlemail.com> Co-authored-by: soyboy <85043086+sbvegan@users.noreply.github.com>
* feat(op-node): add signer grace period for unsafe block signer rotation When the unsafe block signer address is rotated on L1, verifier nodes can reject valid blocks during the window between the L1 update and the runtime config reload. Add a grace period so both the old and new signers are accepted for up to 20 minutes after a rotation is detected. The grace period ends early when a block from the new signer is verified, confirming the rotation is complete. Closes ethereum-optimism#19981 Made-with: Cursor * test(op-node): add tests for signer grace period Tests for verifyBlockSignature grace period behavior: - Previous signer accepted during grace period - New signer confirmation ends grace period - Expired grace period rejects old signer - Third-party signer rejected even with grace active - Normal flow still calls ConfirmCurrentSigner Tests for RuntimeConfig grace period lifecycle: - Signer change starts grace period - First load (zero -> addr) does not start grace period - ConfirmCurrentSigner clears previous - Same signer reload preserves grace state - Timeout expiry returns zero previous address - Double rotation (A->B->C) tracks only most recent previous Made-with: Cursor * refactor(op-node): table-drive grace period gossip tests Collapse 5 individual grace period subtests into a single table-driven loop, reducing ~60 lines to ~20 with no behavior change. Made-with: Cursor * fix(op-node): address self-review on signer grace period - Remove redundant zero-check early return in PreviousP2PSequencerAddress - Invert ConfirmCurrentSigner guard: warn on nil current address, then unconditionally log + clear previous signer - Extract signer rotation logic from Load into rotateSigner helper Made-with: Cursor * docs(op-node): clarify DefaultSignerGracePeriod is an arbitrary value Made-with: Cursor * add comment * Update to 3h grace period * fix(op-node): address wwared review comments on signer grace period - gossip.go: capture current and previous signature verification errors and include both in the "invalid block signature" warning so operators can distinguish malformed signatures from legitimate rotation mismatches. - runtime_config.go: make ConfirmCurrentSigner a no-op (no log, no write lock) when no grace period is active, avoiding log spam and write-lock traffic on every accepted block in steady state. Made-with: Cursor * docs(op-node): document unsafe block signer rotation grace period Address Sebastian's review feedback on PR ethereum-optimism#20063: - README: add an "Unsafe Block Signer Rotation" section under Failure modes describing the 3h grace period, why it exists, when it ends early, and that it is not consensus code. - runtime_config_test: strengthen TestSignerGracePeriod_Expiry to cover the case where the new signer never confirms. Assert P2PSequencerAddress() before and after expiry, and clarify in the test docstring that this models the "no confirmation" path. Made-with: Cursor * minimize readme
…optimism#20242) * feat(op-supernode): add supernode-level prometheus metrics Introduces a SupernodeMetrics struct for metrics that outlive individual virtual node restarts, served alongside per-chain VN metrics via MetricsFanIn.AddGatherer. Metrics added: - supernode_virtual_node_restarts_total (counter, chain_id) - supernode_interop_timestamps_verified_total (counter) - supernode_interop_invalidations_total (counter, chain_id) - supernode_interop_verified_timestamp (gauge) - supernode_interop_round_decisions_total (counter, decision) - supernode_interop_rewinds_total (counter) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(op-supernode): linting fixes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ism#19781) * fix: update interop filter to use time.Duration flags * chore: remove op-interop-filter gitignore --------- Co-authored-by: Karl Floersch <karl@oplabs.co>
…m-optimism#20252) * feat(op-challenger): age run-trace game inputs by ~16/7 days Select a game L1 head ~16 days behind the current chain head, and a disputed L2 block derived from an L1 block a further ~7 days earlier. This simulates a dispute game created on a proposal just above the anchor state and played out over the maximum game duration with clock extensions. Refs ethereum-optimism#19517 (interop side left unchanged). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(op-challenger): gate aged run-trace inputs and harden young-chain fallback Add an --age-game-inputs flag (default off) so vm-runner keeps validating recent blocks against kona by default and operators can run a separate deployment with aging enabled. Make the young-chain fallback explicit instead of relying on safedb.ErrNotFound: skip the aged candidate when the L1 chain itself is younger than the offset, and reject any candidate whose L2 safe head is 0 (L1 block predates the L2 chain's first batch — SafeHeadAtL1Block returns the L2 genesis safe head, not ErrNotFound, in that case). Also error when the chosen dispute L2 block lands at or below genesis. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eum-optimism#20250) Adds the Karst hardfork input size limit (57,600 bytes = 300 pairs × 192) for the bn254 pairing precompile, replacing the inherited Jovian limit of 81,984 bytes at OpSpecId::KARST and OpSpecId::INTEROP. Jovian itself is unchanged. The reduction restores Jovian-era headroom under the EIP-7825 L1 gas cap, accommodating the proposed EIP-7904 pairing cost increase plus plausible variance without requiring another adjustment. op-geth and op-program are intentionally not updated (post-Glamsterdam deprecation); op-revm and kona are the only live paths after Karst. Changes: - op-revm: add KARST_MAX_INPUT_SIZE, bn254_pair::KARST, run_pair_karst; karst() precompile set now extends with KARST instead of inheriting JOVIAN. Hoist the canonical EIP-197 pairing identity test vector to a shared tests-module constant so Jovian and Karst tests reuse it. - kona fpvm_evm: add BN256_MAX_PAIRING_SIZE_KARST, fpvm_bn128_pair_karst, accelerated_karst(); provider dispatches KARST|INTEROP to accelerated_karst, JOVIAN keeps accelerated_jovian. - test_post_jovian_specs_use_jovian_precompiles: rename osaka_addrs → karst_addrs, restructure the address-set assertions along fork ancestry (KARST ≡ JOVIAN, INTEROP ≡ KARST), and reword messages so they describe what's actually compared (addresses match; functions may differ). Tests: - op-revm: 3 new tests — direct calls to run_pair_karst for valid input and oversize input, plus provider dispatch via OpSpecId::KARST. - kona: 2 new bn128_pair tests mirroring the Jovian pair, plus test_karst_bn128_pair_enforces_karst_limit proving the KARST provider's dispatched function rejects a 301-pair input (57,792 bytes) with Bn254PairLength. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…validation (ethereum-optimism#19946) * feat: add OPContractsManagerMigrationValidator scaffold Add new contract and interface for validating L1 contracts after an interop migration. Separated from OPContractsManagerStandardValidator due to EIP-170 contract size limits. The contract takes a reference to the existing standard validator for shared configuration (impl addresses, l1PAOMultisig, etc.) and exposes validateMigration/validateMigrationWithOverrides entry points. Implementation is a stub — validation logic will be added in follow-up commits. * refactor: StandardValidator business logic into helper to make room for migration validation * feat: wire MigrationValidator into StandardValidator - Remove standardValidator back-reference from MigrationValidator - Make MigrationValidator constructor no-arg (like StandardValidatorUtils) - Add migrationValidator state var to StandardValidator - Add validateMigratedChain and validateMigratedChainWithOverrides - Deploy MigrationValidator in DeployImplementations and pass to StandardValidator * feat: implement MigrationValidator validation logic with happy path tests Add validation for post-interop-migration state in OPContractsManagerMigrationValidator: - assertValidSharedDGFShape: verify super game types registered and legacy types cleared on the shared DGF - assertValidSharedSuperGame: validate game args, impl params, anchor root, proposer, and challenger for each super game type - assertValidPerChainMigration: verify portal ASR, per-chain DGF cleared, lockbox authorization per chain - Guard against empty chainSystemConfigs input Add happy path test file with TestInit base contract and two core validation tests exercising the full validation pipeline. * feat(migration-validator): add l2SequenceNumber check to assertValidSharedSuperGame Add l2SequenceNumber == 0 validation as error code -70, aligning with StandardValidator convention. Renumber downstream codes: anchor root -70 to -80, proposer -80 to -90, challenger -90 to -100. * feat: migration checks for standard validator * fix: pre-pr check failures in MigrationValidator tests - Replace abi.encodeWithSignature with abi.encodeCall(IDisputeGame.l2SequenceNumber, ()) to satisfy semgrep - Merge underscore-separated test name parts to conform to 3-4 part convention - Fix invalid test suffix returnsErrors -> succeeds - Add test file to function_name_validation exclusions (organized by section, not function) * fix: bump OPContractsManagerStandardValidator version to 2.8.0 * fix: add missing SUPER_CANNON_KONA shape check and INTEROP precondition guard H-3: Add SCKDG-SHAPE check in assertValidSuperRootDisputeGames to verify SUPER_CANNON_KONA is registered, matching the existing SPDG-SHAPE check for SUPER_PERMISSIONED_CANNON. H-4: Add explicit Features.INTEROP precondition check in _migratePortal before any state changes. Fails fast with a clear error instead of reverting deep inside OptimismPortal2._isUsingInterop(). * fix(validators): address medium findings M-1 through M-6 M-6: Move misplaced ETHMigrated event to events section in OptimismPortal2 M-5: Extract game depth/clock magic numbers to shared file-level constants M-4: Use IFaultDisputeGame for permissionless game type casts M-3: Wire l1PAOMultisig override through in migration validator M-1: Add proxy impl and ProxyAdmin checks to SharedDelayedWETH * fix(validators): allow SUPER_CANNON in standard and migration validators Remove assertions that SUPER_CANNON == address(0) from both StandardValidatorUtils and OPContractsManagerMigrationValidator. The interop migration uses SUPER_CANNON (type 4) as the StartingRespectedGameType, so these checks incorrectly reject valid post-migration state. TODO(ethereum-optimism#20030): Re-add checks once SUPER_CANNON is disabled in migrator. * fix(migrator): allow SUPER_CANNON as startingRespectedGameType The OPContractsManagerMigrator rejected SUPER_CANNON (type 4) as a valid startingRespectedGameType, but the Go devstack passes exactly that during migration. This caused delegatecall to revert, failing 18 acceptance tests in memory-all-kona-op-reth and memory-all-opn-op-reth. Add SUPER_CANNON to the allowed game types in the migrator validation. TODO(ethereum-optimism#20030): Remove once SUPER_CANNON is disabled in migrator. * fix: goimports formatting in multichain_proofs.go * fix: remove wrongly-nested current-upgrade-bundle.json snapshot * chore: remove stale TODO comment in StandardValidatorUtils * fix: add missing != address(0) checks for non-super games in StandardValidatorUtils * refactor: extract magic values to named constants in StandardValidatorUtils * test: add happy path coverage for StandardValidator.validateMigratedChain * test: add skipped SCDG-SHAPE test for SUPER_CANNON in super mode (blocked on ethereum-optimism#20030) * chore: add commented-out SUPER_CANNON checks next to TODO(ethereum-optimism#20030) markers * test: add per-chain DGF clearing checks (MIG-CHAIN-*-20 through -70) * test: add coverage for validateMigratedChainWithOverrides override path * fix: add virtual/override to _enableSuperCannonKona * fix: bump OPContractsManagerStandardValidator version to 2.9.0 * Update test expectations for new validator checks * Add missing ZK_DISPUTE_GAME config to migration validator test setup * docs: add natspec to StandardValidatorUtils.internalRequire * docs: add natspec to standardValidatorUtils state variable * chore: clean up migration validator and address graphite review - Drop ISemver/version() from OPContractsManagerMigrationValidator - Remove unused ValidationOverrides struct from StandardValidatorUtils - Name internalRequire return value as errors_ per style guide * fix: apply challenger override in validateMigrationWithOverrides The challenger field on ValidationOverrides was accepted by validateMigrationWithOverrides but never applied to _input.challenger, so callers supplying a challenger override had it silently dropped and validation ran against the original expected address. Add coverage for both the match and mismatch cases via validateMigratedChainWithOverrides. * feat(opcm): tighten migrate guards - Require at least two chains (rename NoChains -> TooFewChains) - Require ETH_LOCKBOX feature enabled in _migratePortal * revert(opcm): restore NoChains guard (length == 0) Keep ETH_LOCKBOX precondition from prior commit; single-chain migrate path must still work for existing op-deployer integration tests. * docs(migration-validator): clarify required interop game types * refactor(opcm): move OPContractsManagerMigrationValidator into opcm folder * refactor(migration-validator): derive shared DGF from first chain config * refactor(migration-validator): split refs into SharedImplementations + SharedConfig, source from StandardValidator * feat(contracts-bedrock): extract assertValidDisputeGame into StandardValidatorUtils Hoists assertValidDisputeGame, assertValidDelayedWETH, and assertValidAnchorStateRegistry out of OPContractsManagerStandardValidator into StandardValidatorUtils so OPContractsManagerMigrationValidator can share the same dispute-game drill-down logic. - StandardValidatorUtils: adds DisputeGameImpls/DisputeGameConfig structs and public view methods that take all state-dependent values as params. - StandardValidator: delegates to the utility via _buildDisputeGameImpls and _buildDisputeGameConfig helpers. - MigrationValidator: assertValidSharedSuperGame now delegates the per-game drill-down to the utility while keeping the migration-unique cross-checks (GARGS-30 weth-discovery match, proposer/challenger overrides). - Removes the now-redundant assertValidSharedASR and assertValidSharedDelayedWETH paths; the shared ASR/WETH invariants surface under both MIG-SPDG-* and MIG-SCKDG-* drill-downs. - Renumbers MIG-SPDG-* / MIG-SCKDG-* error codes to align with StandardValidator's scheme. Tests updated accordingly. - Adds standardValidatorUtils to SharedImplementations so MigrationValidator can reach it without storing its own reference. * fix(migration-validator): preserve respectedGameType invariant + polish - Add MIG-SASR-RGT inline check: shared ASR's respectedGameType must be a super game type. The drill-down via assertValidDisputeGame does not cover this — it's a migration-shape invariant that lived in the deleted assertValidSharedASR. Restore as a one-line check after shared-DGF discovery. - Interface fixups: drop unused DisputeGameImplementation import and add the named return errors_ to assertValidDisputeGame to match impl. - Replace numbered step comments in assertValidMigration with descriptive one-liners explaining why each block runs. - Rename test functions from s* abbreviations (sdgf/sasr/slockbox/sdweth/anchorp/dweth) to shared* for clarity. * fix: resolve rebase conflicts with develop * fix(standard-validator): correct PreimageOracle expected version to 1.1.5
… natspec (ethereum-optimism#20348) * chore(contracts-bedrock): drop v1 mention from _decodeDisputeGameImpl natspec v1 dispute game support was removed in ethereum-optimism#18208; the function now only decodes v2 game args. Also fix a stray `// @notice` so the comment is recognized as natspec. * chore(contracts-bedrock): regenerate semver-lock for source comment edit * chore(contracts-bedrock): bump OPContractsManagerStandardValidator to 2.9.1
…ism#20361) * fix(op-acceptance): default cannon-kona challenger on Invert the op-devstack preset config flag so zero-value presets enable cannon-kona challenger support by default, then remove the now-dead opt-in helpers and acceptance-test boilerplate. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: always enable cannon kona challenger support --------- Co-authored-by: wwared <541936+wwared@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This allows unknown fields to be present in rollup config json files, which allows a smooth transition from the recent removal of the protocol versions field in ethereum-optimism#20317
…optimism#20374) Fail PR target branch resolution when the GitHub API cannot return a usable base branch instead of falling back to CIRCLE_BRANCH. Also fail semver diff checks when the upstream ref is missing so missing fetches cannot look like an unchanged lockfile. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: merge with dev * feat: merge with dev * fix: merge with dev * fix: merge with dev * feat: op deployer zk * feat: op deployer zk * feat: acceptance tests and fix * fix: lint * feat: merge with develop * fix: comments and merge * fix: comments and merge * fix: lint * fix: comments
…timism#20157) * feat(kona): execute NUT bundles at Karst fork activation Add build.rs that reads karst_nut_bundle.json at compile time and generates Rust code to construct the NutBundle. The derive pipeline now adds upgrade gas to the block gas limit at fork activation, matching op-node's gas accounting behavior. * test(op-e2e): add generic NUT bundle activation block action test Verifies that every fork with an embedded NUT bundle produces an activation block containing exactly the bundle's deposit transactions. Discovery uses forks.All + derive.UpgradeTransactions, so future forks with NUT bundles are covered automatically without test changes. * fix(kona): mirror NUT bundles into kona-hardforks crate The Docker build context for kona images is scoped to rust/, so build.rs cannot reach op-core/nuts/bundles/ via ancestor walk and the kona-client/ host/node images fail to build. Keep a byte-identical copy inside the crate, written and verified automatically by the existing snapshot/lock tooling so the two sources cannot silently drift. * Revert "fix(kona): mirror NUT bundles into kona-hardforks crate" This reverts commit 941e15a. * build(docker): pass NUT bundles as named context to kona images The kona-hardforks build.rs walks ancestors of CARGO_MANIFEST_DIR to find op-core/nuts/bundles/ during compilation. The kona-{client,host,node} images scope their Docker context to rust/, so the ancestor walk can't reach op-core/ and the images fail to build. Pass op-core/nuts/bundles as an additional named BuildKit context (nuts-bundles) and copy it into /workspace/op-core/nuts/bundles so the ancestor walk succeeds. Keeps the primary rust/ context small and avoids mirroring the bundle JSON into the crate tree. * test(op-e2e): tighten NUT bundle activation test coverage Iterate forks.From(forks.Karst) with a NoError assertion on derive.UpgradeTransactions rather than silently skipping forks whose bundle fails to load, so a broken bundle surfaces as a test failure. Also assert every tx in the activation block has a successful receipt so a reverted upgrade tx can't hide behind the byte-equality check. * refactor(kona-hardforks): extract impl_hardfork_from_bundle macro The Hardfork impl for each NUT-bundle-backed fork is identical boilerplate (decode, EIP-2718 encode, sum gas). Move that pattern into a single internal macro so adding future forks is a one-liner next to the build-script-generated constructor. * refactor(kona-hardforks): make build.rs testable with shared codegen Split parsing + codegen into build_helpers.rs, included via #[path] from both the build script and a new integration test. Use anyhow to carry error context up to a single panic in main. The integration test runs the generator on a fixture JSON and asserts the exact Rust source output, so codegen changes surface as a test failure rather than a downstream compile error. * test(op-e2e): add karst_fork_test with pre/post impl slot assertion Follows the per-fork test convention from ecotone/fjord/isthmus/holocene. Asserts the EIP-1967 implementation slot of representative predeploy proxies (L1Block, GasPriceOracle) changes across Karst activation — a Karst-specific smoke test that the bundle's proxy upgrades took effect. Not generalized into the NUT bundle activation test because it does not hold for future forks that may not upgrade proxies. * refactor(op-core/forks): add Prev() sibling to Next() Share the initialization between the next/prev maps and replace the manual forks.All index walk in nut_bundle_activation_test.go with forks.Prev(fork). Keeps neighbor-navigation centralized in the forks package rather than re-derived at call sites. * test(op-e2e): run fault-proof program and fold karst assertions in The generic activation test was missing the core RunFaultProofProgram call (preceded by BatchMineAndSync to advance the safe head), so it only exercised the sequencer, not the proof pipeline it lives under actions/proofs/ to validate. Fold the Karst-specific impl-slot assertions back in via a switch on fork name, establishing the pattern for future forks to register their own post-activation checks alongside the universal ones. Delete karst_fork_test.go. * test(op-e2e): tighten activation-block checks Use RollupCfg.IsActivationBlockForFork instead of the unguarded IsActivationBlock(time-blockTime, time) — the helper avoids a uint64 underflow when actHeader.Time < blockTime. Assert the safe head lands exactly on the activation block rather than just past it; BatchMineAndSync adds no new L2 blocks, so equality is the right invariant. * test(op-core/forks): add unit tests for Next, Prev, From Table-driven coverage of edge cases (first, middle, last, unknown) plus a NextPrev/PrevNext inverse check that guards against the two maps drifting out of sync. * perf(kona-hardforks): cache NUT bundle in OnceCell Generated bundle constructors now wrap construction in a function-scoped once_cell::sync::OnceCell and return &'static NutBundle. The first call allocates and stores the bundle; subsequent calls return a cached reference. Activation-path calls to txs() and upgrade_gas() no longer reallocate on each invocation. Consumers are unchanged — method calls auto-deref through the reference. * style(kona-hardforks): apply nightly rustfmt and clippy fixes cargo fmt -- collapses a few multi-line statements onto one line per the use_small_heuristics = "Max" rustfmt.toml setting. cargo clippy -- replaces a match-on-Option in the bundle codegen with Option::map_or_else per the option_if_let_else lint. * build(docker): mount NUT bundles into kona-cannon-prestate build The cannon-repro.dockerfile's client-build stage runs cargo build on the kona workspace, which triggers the kona-hardforks build script. That script walks ancestors of CARGO_MANIFEST_DIR looking for op-core/ and panicked because the context only contained kona/. Pull in op-core/nuts/bundles from the existing 'monorepo' named context so the ancestor walk succeeds — same pattern as the kona-node/host/client image fix. * fix: address nightly rustfmt and go-lint findings - stateful.rs: collapse the u64::from_be_bytes call onto one line per nightly rustfmt's use_small_heuristics = "Max" setting. Introduced by the original Karst upgrade_gas change; caught by rust-fmt CI. - nut_bundle_activation_test.go: use bigs.Uint64Strict(bigInt) instead of bigInt.Uint64() per the repo's bigint custom golangci-lint rule. * fix(kona-hardforks): use OnceBox to avoid critical-section dep on no_std sync::OnceCell with the critical-section feature requires an impl of _critical_section_1_0_{acquire,release} to be linked in, which the MIPS64 cannon and RISC-V asterisc fault-proof VM targets don't provide. This broke kona-client on those targets. Switch the generator to emit once_cell::race::OnceBox, which uses a single AtomicPtr for the cache slot — lock-free and requires no critical-section impl. The NutBundle is heap-allocated via Box on first call and then cached as &'static NutBundle for all subsequent calls. Enables the `race` feature on once_cell. * build(kona): mount op-core/nuts/bundles in build-cannon-client recipe The cannon-target docker run mounted only the rust/ directory at /workdir, leaving /workdir/op-core/ absent. The kona-hardforks build script walks ancestors of CARGO_MANIFEST_DIR looking for op-core/ and panics when it can't find the directory. Add a second read-only volume mount that exposes op-core/nuts/bundles at /workdir/op-core/nuts/bundles, mirroring the named-context fix used by the kona-node/host/client image bake and the cannon-prestate Dockerfile. Unblocks kona-build-fpvm-cannon-client and kona-host-client-offline-cannon. * test(op-e2e): tombstone forks-without-NUT-bundle exception list Interop is post-Karst chronologically but still uses the legacy hardcoded upgrade-transactions path rather than a JSON NUT bundle, so require.NoError on derive.UpgradeTransactions(forks.Interop) failed. Replace the simple no-error assertion with a bidirectional check against forksWithoutNUTBundle = {forks.Interop: true}. The exception list cannot go stale silently: - Fork lacks bundle and isn't on the list → test fails (forces a decision: implement the bundle or update the list). - Fork has bundle and is on the list → test fails with "remove it from forksWithoutNUTBundle". When Interop gets its NUT bundle in a follow-up PR, this test will fail until forks.Interop is removed from the exception list, ensuring the list stays in lockstep with the codebase. * chore(kona-hardforks): propagate std feature to new dependencies Zepter's `lint propagate-feature` check requires kona-hardforks's `std` feature to also enable the `std` feature of every dependency (runtime, build, and dev) that has one. Add propagation entries for the deps introduced by the NUT bundle work: anyhow, once_cell, serde, and serde_json. * fix(op-e2e): wire KarstTime into rollup config builder Why: TestActivationBlockNUTBundle is the first test to probe Karst activation; without KarstTime in the rollup config, IsActivationBlockForFork never fires for Karst. * fix(kona-hardforks): probe for bundle file in build.rs ancestor walk Why: Docker bind-mounts auto-create empty op-core/ ancestor stubs on the host; an is_dir() check picks those up before reaching the real op-core at the monorepo root. Probe for the karst bundle file directly. * feat(op-core/nuts): Update karst bundle snapshot * fix(docker): include nut bundles for kona host builds * fix(kona-hardforks): update karst test expectations --------- Co-authored-by: maurelian <maurelian@protonmail.com>
…-optimism#20366) * chore(rust/scr): update superchain registry for rust crates * chore(rust/scr): update superchain registry to cc07e96d91a1647cbce7eef6572098bece1f7fca for rust crates
…#20371) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
sieniven
approved these changes
Apr 30, 2026
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.
No description provided.