Skip to content

Comments

supervisor: Trigger Indexing on Local Safe Update#15749

Merged
axelKingsley merged 1 commit intodevelopfrom
supervisor-index-on-safe
May 14, 2025
Merged

supervisor: Trigger Indexing on Local Safe Update#15749
axelKingsley merged 1 commit intodevelopfrom
supervisor-index-on-safe

Conversation

@axelKingsley
Copy link
Contributor

If ever the Managed Node is only receiving L2 blocks via Derivation (like if the P2P is broken, or if the Sequencing Window has Lapsed), the Supervisor still needs to be prompted to index all log events.

This trigger will happen in response to the L1:L2 link being recorded in the Derivation database, and will happen prior to Cross Safe updating.

@axelKingsley axelKingsley requested review from a team as code owners May 7, 2025 15:27
@axelKingsley axelKingsley requested review from pcw109550 and tynes May 7, 2025 15:27
@codecov
Copy link

codecov bot commented May 7, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 81.24%. Comparing base (7cd84fe) to head (c0cda8e).
Report is 13 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #15749      +/-   ##
===========================================
- Coverage    82.41%   81.24%   -1.17%     
===========================================
  Files          178      161      -17     
  Lines        10275     8751    -1524     
===========================================
- Hits          8468     7110    -1358     
+ Misses        1660     1509     -151     
+ Partials       147      132      -15     
Flag Coverage Δ
cannon-go-tests-64 65.40% <ø> (ø)
contracts-bedrock-tests 96.08% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

see 17 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@pcw109550 pcw109550 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to understand more about the code changes. So what happens if we do not have the diff this PR introduced?

If ever the Managed Node is only receiving L2 blocks via Derivation (like if the P2P is broken, or if the Sequencing Window has Lapsed), the Supervisor still needs to be prompted to index all log events.

So supervisor will not be able to index local safe blocks' log messages, and supervisor view of safe blocks will stuck? To be more precise, the return value of supervisor_syncStatus RPC's safe block will not advance, even though the L2CL's admin_syncStatus's safe block advances?

Curious how the out-of-sync scenario happens(if it does).

@axelKingsley
Copy link
Contributor Author

So supervisor will not be able to index local safe blocks' log messages, and supervisor view of safe blocks will stuck? To be more precise, the return value of supervisor_syncStatus RPC's safe block will not advance, even though the L2CL's admin_syncStatus's safe block advances?

If the Supervisor were to stop indexing, you would see an advancement of the local safe only. As the node derives new L2 blocks, it would advance the Local Derivation DB. However all other heads are stuck:

  • Local Unsafe not advancing because no unsafe blocks are occuring
  • Cross Unsafe not advancing for the same reason, and because there is no log data indexed
  • Cross Safe cannot proceed because there is no log data indexed

To your question directly -- the supervisor_syncStatus would show an advancing Safe Head, because new L1->L2 derivation events are occurring. But it would not update the unsafe, nor could it determine cross-heads.

Theoretically, this could also be solved by an indexing event being emitted once every second, or something like that. The root of the issue is that we only ever gather new logs when unsafe blocks are discovered, but we need the logs even if there are only safe blocks on the network.

Curious how the out-of-sync scenario happens(if it does).

I don't know what you mean by this exactly, but the possible cases where this could occur are any time there is safe data, but no unsafe data. That can happen a few ways:

  • Gossip for your node is broken
  • The Sequencer isn't publishing the unsafe blocks (but batches are published)
  • The chain is in a derivation-only mode, like when the Sequencing Window Lapses.

@pcw109550
Copy link
Member

pcw109550 commented May 9, 2025

I made a test case which makes the case where Gossip for your node is broken.
To reproduce, go to commit 42d6925 (not including the diff of this PR) and run

cd optimism/devnet-sdk/devstack/sysgo
go test ./...  -run ^TestTemp$  -v -count=1  | grep XXX

We start with below topology:
image

STEP 1: We first check unsafe heads of every L2CLs. Logs:

    sync_test.go:746:           INFO [05-09|18:18:22.488] make sure verifiers advances unsafe head XXX=XXX target=10
    sync_test.go:752:           INFO [05-09|18:18:25.493] chain A CL view                          XXX=XXX unsafe=000000..000000:0 safe=000000..000000:0
    sync_test.go:753:           INFO [05-09|18:18:25.493] chain A2 CL view                         XXX=XXX unsafe=000000..000000:0 safe=000000..000000:0
    sync_test.go:754:           INFO [05-09|18:18:25.493] chain B CL view                          XXX=XXX unsafe=000000..000000:0 safe=000000..000000:0
    sync_test.go:755:           INFO [05-09|18:18:25.493] chain B2 CL view                         XXX=XXX unsafe=000000..000000:0 safe=000000..000000:0
    sync_test.go:758:           INFO [05-09|18:18:25.494] chain A2 supervisor view                 XXX=XXX unsafe=7db13f..722f35:0 safe=7db13f..722f35:0
    sync_test.go:759:           INFO [05-09|18:18:25.494] chain B2 supervisor view                 XXX=XXX unsafe=1aadc5..288493:0 safe=1aadc5..288493:0
...
    sync_test.go:752:           INFO [05-09|18:18:37.489] chain A CL view                          XXX=XXX unsafe=b1ff2f..f418bb:8 safe=2f079d..221ee9:3
    sync_test.go:753:           INFO [05-09|18:18:37.489] chain A2 CL view                         XXX=XXX unsafe=b1ff2f..f418bb:8 safe=2f079d..221ee9:3
    sync_test.go:754:           INFO [05-09|18:18:37.489] chain B CL view                          XXX=XXX unsafe=4f0787..78021a:8 safe=641f17..a87e4a:3
    sync_test.go:755:           INFO [05-09|18:18:37.489] chain B2 CL view                         XXX=XXX unsafe=4f0787..78021a:8 safe=641f17..a87e4a:3
    sync_test.go:758:           INFO [05-09|18:18:37.490] chain A2 supervisor view                 XXX=XXX unsafe=b1ff2f..f418bb:8 safe=2f079d..221ee9:3
    sync_test.go:759:           INFO [05-09|18:18:37.490] chain B2 supervisor view                 XXX=XXX unsafe=4f0787..78021a:8 safe=641f17..a87e4a:3
    sync_test.go:752:           INFO [05-09|18:18:40.490] chain A CL view                          XXX=XXX unsafe=f4572c..561abb:9 safe=2f079d..221ee9:3
    sync_test.go:753:           INFO [05-09|18:18:40.490] chain A2 CL view                         XXX=XXX unsafe=f4572c..561abb:9 safe=2f079d..221ee9:3
    sync_test.go:754:           INFO [05-09|18:18:40.490] chain B CL view                          XXX=XXX unsafe=625e52..43c447:9 safe=641f17..a87e4a:3
    sync_test.go:755:           INFO [05-09|18:18:40.490] chain B2 CL view                         XXX=XXX unsafe=625e52..43c447:9 safe=641f17..a87e4a:3
    sync_test.go:758:           INFO [05-09|18:18:40.491] chain A2 supervisor view                 XXX=XXX unsafe=f4572c..561abb:9 safe=2f079d..221ee9:3
    sync_test.go:759:           INFO [05-09|18:18:40.491] chain B2 supervisor view                 XXX=XXX unsafe=625e52..43c447:9 safe=641f17..a87e4a:3
    sync_test.go:752:           INFO [05-09|18:18:43.494] chain A CL view                          XXX=XXX unsafe=cb0be1..211d39:11 safe=2f079d..221ee9:3
    sync_test.go:753:           INFO [05-09|18:18:43.494] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=2f079d..221ee9:3
    sync_test.go:754:           INFO [05-09|18:18:43.494] chain B CL view                          XXX=XXX unsafe=2e8785..94b3ce:11 safe=641f17..a87e4a:3
    sync_test.go:755:           INFO [05-09|18:18:43.494] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=641f17..a87e4a:3
    sync_test.go:758:           INFO [05-09|18:18:43.495] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=2f079d..221ee9:3
    sync_test.go:759:           INFO [05-09|18:18:43.495] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=641f17..a87e4a:3

As we can see unsafe heads are both advancing, both sequencer and verifier. Also, safe heads are both advancing because the batcher wrote batch to L1, supervisors read it, and sent back to L2 CLs.

STEP 2: Now, we disconnect P2P.
image
Logs:

    sync_test.go:765:           INFO [05-09|18:18:43.495] disconnect p2p between L2CLs             XXX=XXX

In this case, the gossip is intentionally broken, and we may observe

To your question directly -- the supervisor_syncStatus would show an advancing Safe Head, because new L1->L2 derivation events are occurring. But it would not update the unsafe, nor could it determine cross-heads.

However, The test shows that unsafe heads are still advancing, viewed by backup supervisor because of the safe head is advancing:

    sync_test.go:776:           INFO [05-09|18:18:46.517] chain A CL view                          XXX=XXX unsafe=c29f68..df43a5:12 safe=2f079d..221ee9:3
    sync_test.go:777:           INFO [05-09|18:18:46.517] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=2f079d..221ee9:3
    sync_test.go:778:           INFO [05-09|18:18:46.517] chain B CL view                          XXX=XXX unsafe=524e67..9fedb3:12 safe=641f17..a87e4a:3
    sync_test.go:779:           INFO [05-09|18:18:46.517] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=641f17..a87e4a:3
    sync_test.go:782:           INFO [05-09|18:18:46.518] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=2f079d..221ee9:3
    sync_test.go:783:           INFO [05-09|18:18:46.518] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=641f17..a87e4a:3
    sync_test.go:776:           INFO [05-09|18:18:49.514] chain A CL view                          XXX=XXX unsafe=5f5664..e00f93:14 safe=2f079d..221ee9:3
    sync_test.go:777:           INFO [05-09|18:18:49.514] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=2f079d..221ee9:3
    sync_test.go:778:           INFO [05-09|18:18:49.514] chain B CL view                          XXX=XXX unsafe=cdd264..4148b5:14 safe=641f17..a87e4a:3
    sync_test.go:779:           INFO [05-09|18:18:49.514] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=641f17..a87e4a:3
    sync_test.go:782:           INFO [05-09|18:18:49.516] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=2f079d..221ee9:3
    sync_test.go:783:           INFO [05-09|18:18:49.516] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=641f17..a87e4a:3
    sync_test.go:776:           INFO [05-09|18:18:52.515] chain A CL view                          XXX=XXX unsafe=e145ce..fccd30:15 safe=2f079d..221ee9:3
    sync_test.go:777:           INFO [05-09|18:18:52.515] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=2f079d..221ee9:3
    sync_test.go:778:           INFO [05-09|18:18:52.515] chain B CL view                          XXX=XXX unsafe=0d0e9b..3acbd4:15 safe=641f17..a87e4a:3
    sync_test.go:779:           INFO [05-09|18:18:52.515] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=641f17..a87e4a:3
    sync_test.go:782:           INFO [05-09|18:18:52.516] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=2f079d..221ee9:3
    sync_test.go:783:           INFO [05-09|18:18:52.516] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=641f17..a87e4a:3
    sync_test.go:776:           INFO [05-09|18:18:55.515] chain A CL view                          XXX=XXX unsafe=4e8239..b60900:17 safe=50ee36..2d662d:6
    sync_test.go:777:           INFO [05-09|18:18:55.515] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=50ee36..2d662d:6
    sync_test.go:778:           INFO [05-09|18:18:55.515] chain B CL view                          XXX=XXX unsafe=a21b3b..054ed3:17 safe=cdca6e..c941b7:6
    sync_test.go:779:           INFO [05-09|18:18:55.515] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=cdca6e..c941b7:6
    sync_test.go:782:           INFO [05-09|18:18:55.516] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=50ee36..2d662d:6
    sync_test.go:783:           INFO [05-09|18:18:55.516] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=cdca6e..c941b7:6
    sync_test.go:776:           INFO [05-09|18:18:58.516] chain A CL view                          XXX=XXX unsafe=044c65..8e03ad:18 safe=50ee36..2d662d:6
    sync_test.go:777:           INFO [05-09|18:18:58.516] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=50ee36..2d662d:6
    sync_test.go:778:           INFO [05-09|18:18:58.516] chain B CL view                          XXX=XXX unsafe=274100..46bdf5:18 safe=cdca6e..c941b7:6
    sync_test.go:779:           INFO [05-09|18:18:58.516] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=cdca6e..c941b7:6
    sync_test.go:782:           INFO [05-09|18:18:58.518] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=50ee36..2d662d:6
    sync_test.go:783:           INFO [05-09|18:18:58.518] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=cdca6e..c941b7:6
    sync_test.go:776:           INFO [05-09|18:19:01.527] chain A CL view                          XXX=XXX unsafe=59e954..ca5801:20 safe=3c5714..a718f5:7
    sync_test.go:777:           INFO [05-09|18:19:01.527] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=3c5714..a718f5:7
    sync_test.go:778:           INFO [05-09|18:19:01.527] chain B CL view                          XXX=XXX unsafe=72ea91..255e48:20 safe=29d651..0a0924:7
    sync_test.go:779:           INFO [05-09|18:19:01.527] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=29d651..0a0924:7
    sync_test.go:782:           INFO [05-09|18:19:01.528] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=3c5714..a718f5:7
    sync_test.go:783:           INFO [05-09|18:19:01.528] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=29d651..0a0924:7
    sync_test.go:776:           INFO [05-09|18:19:04.516] chain A CL view                          XXX=XXX unsafe=45caaa..4306e5:21 safe=3c5714..a718f5:7
    sync_test.go:777:           INFO [05-09|18:19:04.516] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=3c5714..a718f5:7
    sync_test.go:778:           INFO [05-09|18:19:04.516] chain B CL view                          XXX=XXX unsafe=69f8ce..37fb94:21 safe=29d651..0a0924:7
    sync_test.go:779:           INFO [05-09|18:19:04.516] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=29d651..0a0924:7
    sync_test.go:782:           INFO [05-09|18:19:04.517] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=3c5714..a718f5:7
    sync_test.go:783:           INFO [05-09|18:19:04.517] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=29d651..0a0924:7
    sync_test.go:776:           INFO [05-09|18:19:07.516] chain A CL view                          XXX=XXX unsafe=e1160a..fa837b:23 safe=b1ff2f..f418bb:8
    sync_test.go:777:           INFO [05-09|18:19:07.516] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=b1ff2f..f418bb:8
    sync_test.go:778:           INFO [05-09|18:19:07.516] chain B CL view                          XXX=XXX unsafe=1e9d3c..806f43:23 safe=4f0787..78021a:8
    sync_test.go:779:           INFO [05-09|18:19:07.516] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=4f0787..78021a:8
    sync_test.go:782:           INFO [05-09|18:19:07.517] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=b1ff2f..f418bb:8
    sync_test.go:783:           INFO [05-09|18:19:07.517] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=4f0787..78021a:8
    sync_test.go:776:           INFO [05-09|18:19:10.515] chain A CL view                          XXX=XXX unsafe=90095a..1cd9ee:24 safe=b1ff2f..f418bb:8
    sync_test.go:777:           INFO [05-09|18:19:10.515] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=b1ff2f..f418bb:8
    sync_test.go:778:           INFO [05-09|18:19:10.515] chain B CL view                          XXX=XXX unsafe=10efa6..5ea53d:24 safe=4f0787..78021a:8
    sync_test.go:779:           INFO [05-09|18:19:10.515] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=4f0787..78021a:8
    sync_test.go:782:           INFO [05-09|18:19:10.517] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=b1ff2f..f418bb:8
    sync_test.go:783:           INFO [05-09|18:19:10.517] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=4f0787..78021a:8
    sync_test.go:776:           INFO [05-09|18:19:13.516] chain A CL view                          XXX=XXX unsafe=7f6888..c8b865:26 safe=cb0be1..211d39:11
    sync_test.go:777:           INFO [05-09|18:19:13.516] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=cb0be1..211d39:11
    sync_test.go:778:           INFO [05-09|18:19:13.516] chain B CL view                          XXX=XXX unsafe=51aee6..923229:26 safe=2e8785..94b3ce:11
    sync_test.go:779:           INFO [05-09|18:19:13.516] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=2e8785..94b3ce:11
    sync_test.go:782:           INFO [05-09|18:19:13.518] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=cb0be1..211d39:11
    sync_test.go:783:           INFO [05-09|18:19:13.518] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=2e8785..94b3ce:11
    sync_test.go:776:           INFO [05-09|18:19:16.516] chain A CL view                          XXX=XXX unsafe=78175f..4fd826:27 safe=cb0be1..211d39:11
    sync_test.go:777:           INFO [05-09|18:19:16.516] chain A2 CL view                         XXX=XXX unsafe=cb0be1..211d39:11 safe=cb0be1..211d39:11
    sync_test.go:778:           INFO [05-09|18:19:16.516] chain B CL view                          XXX=XXX unsafe=c51f2a..86cc28:27 safe=2e8785..94b3ce:11
    sync_test.go:779:           INFO [05-09|18:19:16.516] chain B2 CL view                         XXX=XXX unsafe=2e8785..94b3ce:11 safe=2e8785..94b3ce:11
    sync_test.go:782:           INFO [05-09|18:19:16.517] chain A2 supervisor view                 XXX=XXX unsafe=cb0be1..211d39:11 safe=cb0be1..211d39:11
    sync_test.go:783:           INFO [05-09|18:19:16.517] chain B2 supervisor view                 XXX=XXX unsafe=2e8785..94b3ce:11 safe=2e8785..94b3ce:11
    sync_test.go:776:           INFO [05-09|18:19:19.516] chain A CL view                          XXX=XXX unsafe=288c51..f99502:29 safe=5f5664..e00f93:14
    sync_test.go:777:           INFO [05-09|18:19:19.516] chain A2 CL view                         XXX=XXX unsafe=5f5664..e00f93:14 safe=cb0be1..211d39:11
    sync_test.go:778:           INFO [05-09|18:19:19.516] chain B CL view                          XXX=XXX unsafe=f94264..925453:29 safe=cdd264..4148b5:14
    sync_test.go:779:           INFO [05-09|18:19:19.516] chain B2 CL view                         XXX=XXX unsafe=cdd264..4148b5:14 safe=2e8785..94b3ce:11
    sync_test.go:782:           INFO [05-09|18:19:19.517] chain A2 supervisor view                 XXX=XXX unsafe=5f5664..e00f93:14 safe=5f5664..e00f93:14
    sync_test.go:783:           INFO [05-09|18:19:19.517] chain B2 supervisor view                 XXX=XXX unsafe=cdd264..4148b5:14 safe=cdd264..4148b5:14

The test shows otherwise: as the safe head advances, the unsafe head appears to progress as well. The backup supervisor view of safe heads advanced, and also the unsafe heads(block number 11 -> block number 14).

@axelKingsley
Copy link
Contributor Author

@pcw109550 I appreciate the test and explanation, thank you very much!

While your test does show that this unsafe head references are advancing in the situation provided, it does not prove the absence of this issue I've described.

Indexing logs is handled by chain_processor.go, which can be triggered only by OnEvent ChainProcessEvent. These events can only come from the following places:

  • Emitted by itself if the indexing it just did does not completely sync it up to nextNum
  • Emitted by itself if no logs are found, if there are multiple sources to check (as a fallback if the first data source is down)
  • Emitted by the Backend on LocalUnsafeReceivedEvent

I will have to look at your test more closely on Monday, but just because the unsafe head reference is advancing does not indicate to me that log items are being indexed at all.

A counter-example of this not working is the RC-Alphanet Supervisor-0. This host is currently broken for other reasons at the moment, but I've selected a time-range which shows what I'm talking about HERE. You can see:

  • Derivation events from the nodes are happening, and NextL1 being provided
  • Local Safe Updates
  • Attempted Cross Safe Updates
  • No logs from the chain_processor
  • Critically: failed to get unsafe block at derived height" component=rewinder chain=420120003 height=1694001 err="block 1694001 is not known yet: future data

This illustrates to me that this Supervisor is advancing safe data, but does not have any unsafe logs being indexed. While your test seems to show otherwise in the situation you've constructed, you should check if you see indexing events happening, and if so, we should understand why.

It is possible that the Broken P2P case does not cause this kind of failure, as maybe it is still emitting unsafe block events from the node?

@pcw109550
Copy link
Member

pcw109550 commented May 13, 2025

@axelKingsley To answer this question:

It is possible that the Broken P2P case does not cause this kind of failure, as maybe it is still emitting unsafe block events from the node?

Here is the entire log produced by go test ./... -run ^TestTemp$ -v -count=1 > test.log: test.log

By grepping the log, we may filter first with verifier log: grep -E 'L2CLNode-verifier-901|disconnect p2p between L2CLs' test.log > verifier.log:verifier.log

  • Before the P2P disconnection: I see Received signed execution payload from p2p, Optimistically queueing unsafe L2 execution payload, Inserted new L2 unsafe block (synchronous) from the verifier(L2CL).
  • After the P2P disconnection: I only see Inserted new L2 unsafe block (Note that (synchronous) is gone.)

By grepping the log, we may filter next with backup supervisor log: grep -E 'Supervisor-backup|disconnect p2p between L2CLs' test.log > supervisor.log: supervisor.log

  • Before and after the P2P disconnection, I see Updated local unsafe logs.
  • Call Trace: ChainProcessor::onRequest->rangeUpdate->process->ProcessLogs->SealBlock->initializedSealBlock

func (db *ChainsDB) initializedSealBlock(chain eth.ChainID, block eth.BlockRef) error {
logDB, ok := db.logDBs.Get(chain)
if !ok {
return fmt.Errorf("cannot SealBlock: %w: %v", types.ErrUnknownChain, chain)
}
err := logDB.SealBlock(block.ParentHash, block.ID(), block.Time)
if err != nil {
return fmt.Errorf("failed to seal block %v: %w", block, err)
}
db.logger.Info("Updated local unsafe", "chain", chain, "block", block)
db.emitter.Emit(superevents.LocalUnsafeUpdateEvent{
ChainID: chain,
NewLocalUnsafe: block,
})
return nil
}

So, supervisor emits LocalUnsafeUpdateEvent to itself, and OnEvent picks it up. The L2CL does not emit the event.

It is possible that the Broken P2P case does not cause this kind of failure, as maybe it is still emitting unsafe block events from the node?

My answer:

  • Broken P2P causes this kind of failure.
  • L2CL does not emit unsafe block events to supervisor
  • Supervisor itself emits unsafe block event to itself

@axelKingsley
Copy link
Contributor Author

@pcw109550

ChainProcessor::onRequest->rangeUpdate->process->ProcessLogs->SealBlock->initializedSealBlock

So then, the problem exists here in the call-chain. We see that the thing which initiates the event is SealBlock. This function is only going to ever be called if there are unsafe updates. This circular logic is self sustaining, until it isn't.

All that needs to happen is for no calls to process be made, and there are two ways I can see that happening:

One way to make this happen is to restart the Supervisor. I took the test you uploaded above and added a 3rd advancement check after Stopping and Starting the Supervisor, and indeed the advancement is no longer ever satisfied. Without an initial unsafe head event from the node, the loop never begins in the first place.

Another way to make this happen is much more likely in real life -- if the first result in the rangeUpdate is an error, no call to process is made, breaking the loop you've described. These errors include if the block is not found because it doesn't exist yet. If rangeUpdate finds no blocks to process, naturally, no processing work will be done. You can also simulate this case in your test by stopping and restarting the CL Nodes for a block, letting the self-feeding loop break on a results error.

So yes you are correct that this event trigger is self-feeding and you are correct that broken P2P indeed no longer emits unsafeUpdates from the node. But we can make this test break simply by breaking that self-triggering loop you highlighted, and we can see that it is actually very easy to break that loop by interrupting the Supervisor, or by having the Supervisor not find any new blocks during any single rangeUpdate.

Self-triggering loops are only sustainable as long as they are certain to fire themselves, which this one is not. And the only external source of this trigger is the presence of new unsafe blocks. But we already know that new safe blocks should also trigger indexing if applicable, since there is new known data which the Supervisor should seek to index.

Copy link
Member

@pcw109550 pcw109550 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the detailed response.

@axelKingsley axelKingsley added this pull request to the merge queue May 14, 2025
Merged via the queue into develop with commit 877b74f May 14, 2025
54 checks passed
@axelKingsley axelKingsley deleted the supervisor-index-on-safe branch May 14, 2025 14:45
maurelian added a commit that referenced this pull request Jun 2, 2025
* Bump mipsversion (#15739)

* op-service: Fix length checks when parsing super roots (#15708)

* op-service: Fix length checks when parsing super roots.

* op-program: Fix unmarshalTransitionSate spelling

* feat(devstack): propagate observability context (#15727)

This change introduces optional propagation of context through
environment variables.
This is helpful if a calling test runner (such as op-acceptor) generates
its own observability information, as the relationships are preserved
across processes.

* op-program: Optimisations recommended by audit (#15709)

* op-program: Check block timestamp before retrieving receipts.

* op-program: Stop checking chains once a replacement block is inserted.

The replacement block means all blocks will be re-checked so checking further chains now is likely to be a waste as a valid response can't be trusted anyway.

* op-program: Skip HazardUnsafeFrontierChecks

op-program only ever progresses one block per chain at a time so the frontier checks performed by op-supervisor aren't required since the parent of any available initiating message block is always the agreed block or earlier and thus already cross-unsafe (and cross-safe and cross-finalized).

* supervisor: Fix finality log message (#15738)

* devstack: split options into lifecycle stages, make interop customizable (#15720)

* devstack: split options into lifecycle stages, make interop customizable

* devstack: fix useInterop usage, handle scheduled interop fork

* devstack: devnet-sdk/devstack/dsl/l2_network.go

Co-authored-by: Teddy Knox <teddy@oplabs.co>

* devstack: debug-logs when option does not apply

* devstack: dsl: generalize await fork time

* devstack: fix CI

* op-e2e: fix intentbuilder test

---------

Co-authored-by: Teddy Knox <teddy@oplabs.co>

* op-e2e: Add action test for consolidation step prior to interop being active (#15637)

* op-e2e: Add action test for consolidation step prior to interop being active.

Mostly checks the supervisor can return super roots prior to interop.

* op-e2e: Include invalid executing message prior to interop activating.

Currently fails because both op-supervisor and op-program incorrectly re-org out the invalid message.

* op-e2e: Don't deploy interop contracts in L2 genesis unless interop is active.

Update pre-activation test to expect the executing message to revert.

* op-e2e: make `NewL2FaultProofEnv` more defensive (#15713)

* panic if HF is not explicitly handled

* address comment

* op-conductor: add warn log when miner proxy call fails (#15747)

* op-deployer: remove legacy DeployAlphabetVM script (#15725)

* op-deployer: remove legacy DeployAsterisc script (#15728)

* chore: Dump logs when acceptance tests fail (#15742)

* op-deployer: remove legacy DeployAltDA script (#15722)

* op-deployer: remove legacy DeployAltDA script

* DeployAltDA2: allow input.resolverRefundPercentage to be 0

* DeployAltDA2: remove test revert for resolverRefundPercentage=0

* rename DeployAltDA2 to DeployAltDA

* op-acceptance-tests: interop: explicitly wait until l2 genesis pass (#15750)

* chore(devnet-sdk): relocate telemetry package (#15752)

* chore: descope interop bridges (#15726)

Co-authored-by: AgusDuha <81362284+agusduha@users.noreply.github.com>

* op-proposer: clarify documentation for `poll-interval` (#15717)

* improve flags

* tweak

* feat: updated standard validator tests (#15745)

* feat: updated standard validator tests

Updates the StandardValidator tests to look like the rest of the
test suite. StandardValidator tests now run on upgrades without
being mocked out.

* fix: simplified sysconfig check

* feat: add mising tests

* fix: old console log

* wip: Collect authoriship metrics (#15527)

* op-challenger/op-dispute-mon: Load dispute game factory from multiple network args (#15744)

* op-challenger: Support loading factory address with multiple networks

Validates that the DisputeGameFactoryProxy address for all specified chains matches. Can still be overridden with --game-factory-address if required.

* op-dispute-mon: Support loading factory address with multiple networks

Validates that the DisputeGameFactoryProxy address for all specified chains matches. Can still be overridden with --game-factory-address if required.
Increases safety of monitoring by allowing operators to name all networks they expect to be monitoring via the shared factory and dispute-mon will fail to start if one of them isn't actaully sharing that factory (according to the superchain-registry).

* op-e2e: Generic program precompile action test (#15767)

* op-e2e: Generic program precompile action test

* fixup goimports

* also assert on deactivated precompiles

* fix semgrep solidity lint

* fix mutating forks

* op-acceptance-test: interop: TestMessagePassing: wait until supervisor sync (#15773)

* op-node: move MeteredL1Fetcher (#15778)

* op-supervisor: include chain id at logs in resuming from sealed block (#15781)

* fix(telemetry): improve setup (#15776)

We can be a little bit more precise in our telemetry enablement code:
- disable traces and metrics defaults independently
- keep the ability for the caller to override these choices

In effect it only deactivates pointing to the local exporter by default,
and does not longer disable opentelemetry altogether.

* more cleanup (#15688)

* more cleanup

* more cleanup

* add set init bond

* add set init bond

* improvements

* improvements

* improvements

* improvements

* fix failing standard validator tests

* rm unnecessary import

---------

Co-authored-by: Maurelian <john@oplabs.co>

* op-chain-ops: use generic CheckNoZeroAddresses instead of struct-specific methods (#15785)

* op-program: Fix regeneration of optimistic blocks when they have been pruned (#15741)

* op-program: Fix regeneration of optimistic blocks when they have been pruned.

Update action tests to create a verifier node to run FPP against that only contains canonical blocks so replaced optimistic blocks are not available without regeneration.

* op-program: Update tests to expect fetching output roots and block data.

* op-program: Update baseline to include new call stacks into rawdb.NewStateFreezer

Only the in-memory version is ever actually used but the analyzer can't detect that so reports issues with the alternate path that goes through newResettableFreezer.

* Add comment.

* Improve comment.

* Panic on Failed to Enqueue (#15740)

* feat(kurtosis-devnet): add telemetry support for provisioning (#15777)

Add tracing information to the most relevant parts of devnet
provisioning:
- pre-requisite builds (docker images, contracts, ...)
- kurtosis execution

For the most part it involves passing the context around a bit more.
The kurtosis "integration" is hacked around the logs handler though,
which is a bit dodgy, especially around span management. It'd be better
to have native kurtosis support, but in the meantime it gets the job
done.

* op-program: Simplify op-program analysis baseline (#15743)

* op-program: Fix regeneration of optimistic blocks when they have been pruned.

Update action tests to create a verifier node to run FPP against that only contains canonical blocks so replaced optimistic blocks are not available without regeneration.

* op-program: Update tests to expect fetching output roots and block data.

* op-program: Update baseline to include new call stacks into rawdb.NewStateFreezer

Only the in-memory version is ever actually used but the analyzer can't detect that so reports issues with the alternate path that goes through newResettableFreezer.

* Add comment.

* Improve comment.

* op-program: Remove file, line and absPath fields from baseline.

These are ignored by vm-compat but create a lot of noise in diffs.

* Resort baseline to match output from vm-compat.

* Restore usage of baseline.

* Add readme.

* feat(op-acceptance-tests): base; rpc connectivity. (#15696)

* feat(op-acceptance-tests): base; rpc connectivity.

* check chainid

* cannon: Noop mprotect syscall (#15792)

* op-devstack: split from devnet-sdk, update docs (#15804)

* feat(op-challenger): Super kona/asterisc support (#15805)

* ci: cover op-devstack (#15813)

* op-conductor: ensure a transparent proxy for miner_setMaxDASize (#15772)

* op-conductor: ensure a transparent proxy for miner_setMaxDASize

Previously we were translating an error from the origin server into a "false" boolean return value. This messes up the error handling in downstream software like the batcher.

Adds an integration test to ensure correct behaviour.

Only use debug logging because errors are part of normal proxy behavior.

* noncomplicant sequencer returns an http 200 but with JSON-RPC error response

* tidy up

* fix lint

* use op-service MockRPC to simplify test

* switch on error and warn log if not an RPC err

* add test case for "sequencer down" and assert on logs

* op-supervisor: migrate remaining geth interop type functionality (#15814)

* init and exec msgs (#15624)

Co-authored-by: Anton Evangelatov <anton.evangelatov@oplabs.co>

* feat(op-acceptance-tests): added protocol discord (#15808)

* fix(op-acceptance-tests): temporarily remove failing test. (#15809)

* fix(op-acceptance-tests): temporarily remove failing test.

* fixup acceptance-tests.yaml

fix TODO format

---------

Co-authored-by: Yann Hodique <yann@oplabs.co>

* feat(op-acceptance-tests): add telemetry-friendly runner (#15818)

This change basically moves some of the logic (creation of devnet,
followed by test runs) for acceptance tests out of justfile, and into a
trivial Go binary.

This in particular enables us to tie together the telemetry traces
across those 2 phases, and gain full visibility over the various
activities involved.

* op-fetcher: make output-file flag optional (#15819)

* op-fetcher: make output-file flag optional

* update FetchChainInfo forge artifacts

* update docs for output-file flag

* op-supervisor,op-service: rm deprecated CrossDerivedFrom, remove unused stale old supervisor test backends (#15815)

* Update rc patch guidance (#15795)

* Update rc patch guidance

* Apply suggestions from code review

* Fix Devnet Metrics Collect (#15807)

* testing

* test bucket

* bucket storage

* fix

* fix

* fix(kt-devnet): reflect op-deployer changes (#15822)

some naming/casing has changed in op-deployer

adjust the downstream code accordingly

* op-devstack, op-acceptance-tests: interop: minimal sync test for sysgo + sysext with dsl (#15816)

* ignore invalid addrbook

* make backend constant

* sysext skeleton for sequencer

* fine grained preset per backend

* we love dsl

* rename for consistency

* sync test that targets sysgo AND sysext

* add an issue and lint

* also target sysext

* happy lint

* dedup

* do not enable sync test in acceptor yet

* graceful

* convention

* rename restart->start for dsl

* global level backend detection and refactor

* dsl helper

* Refactor using dsl

* Fix hardcoded block label

* convention for init devstack

* op-devstack, op-acceptance-tests: interop: minimal messaging test for sysgo + sysext with dsl (#15840)

* Temporal sysext op-faucet fix for path

* EOA DSL for interop msg

* Supervisor DSL for advancing unsafe head per chain

* Minimal NAT messaging test poc

* op-node,op-supervisor: support emitter/executor prioritization (#15828)

* op-node,op-supervisor: support emitter/executor prioritization

* op-node: event priority enum

* feat(kt-devnet): support redundant services (#15830)

* feat(kt-devnet): support redundant services

* fix(kt-devnet): recover dependency set retrieval

* fix(kt-devnet): rewrite endpoints parsing logic

The previous approach was becoming unsustainable, and increasingly
brittle.

As we are changing the shape of naming conventions in
optimism-package, use a pluggable approach instead, where each service
type can have its own parsing logic associated to it.

* fix(kt-devnet): adjust devnet definitions

* fix: interop defaults

* chore: Bump `kona` + `asterisc` (#15823)

* fix(kt-devnet): expose faucet as a feature (#15856)

* fix(devstack): honor RPC endpoint path (#15857)

Ensure we don't mutate the environment descriptor with information
that doesn't come from kurtosis, as it gets in the way of passing it
around in a stable form.

Instead, teach the client generation code to take path into
consideration.

* op-deployer: Add addGameType command (#15746)

* op-deployer: Add addGameType command

* lint

* add unmarshal test

* contracts nits

* CR items

* lint

* cr updates

* lint

* fix(kt-devnet): explicitly enable interop (#15865)

* fix(op-acceptance-tests): test; base - rpc connectivity (#15833)

* remove dead code (#15751)

* op-deployer: use op-supervisor StaticConfigDependencySet struct (#15855)

* op-deployer: use op-supervisor StaticConfigDependencySet struct

* fix chainId type conversion

* feat(op-acceptance-tests): op-acceptor v0.1.11 (#15867)

* op-supervisor: add custom toml methods to StaticConfigDependency (#15888)

* op-supervisor: add custom toml methods to StaticConfigDependency

* add toml tags for StaticConfigDependency fields

* chore: bump foundry version (#15766)

* op-acceptance-tests, op-devstack: refactor to remove global state (#15890)

Specifically, the backend variable and `SimpleInterop` functions.

* op-acceptance-tests: interop: add first load test (#15768)

Also set a deadline on the top-level test context that times out
30s before the `*testing.T.Deadline()` to avoid panics.

* op-batcher: wire up `AdditionalThrottlingEndpointsFlag` (#15906)

* op-batcher: wire up AdditionalThrottlingEndpointsFlag properly

* add test

* Revert "add test"t

This reverts commit 146f03d.

* supervisor: Trigger Indexing on Local Safe Update (#15749)

* op-devstack: fix orchestrator option system hooks (#15927)

* op-acceptance-tests: Pre-interop proofs readiness checks (#15905)

* op-acceptance-tests: Pre-interop proofs readiness checks

These checks ensure that chains are ready for the interop upgrade

* add timeout to preinterop gate

* op-acceptance-tests, op-devstack: use proxyd in load test if available (#15914)

* op-acceptance-tests, op-devstack: use proxyd in load test if available

Fall back to a standard EL if unavailable.

Also expands on a design principle in op-devstack/README.md to highlight a papercut
encountered by and partially fixed in this PR.

* address review comments

* use constant instead of string

* [U16] StandardValidator Validation Overrides (#15834)

* ...

* fix error concatenation

* fix checks

* fix checks

* better approach, add some tests

* better approach, add more tests

* add more tests

* improvementz

* rm guardian override, fixes

* fixes

* fixes

* fixes...

* optimized approach

* add tests for no allow failure error with overrides

* feat: add u16 reviews from Wonderland and Cantina (#15929)

* feat: u16 audit fixes (#15939)

* fix: use internal modifier for guardian checks

Updates the AnchorStateRegistry to use an internal modifier for
checking that functions can only be called by the Guardian
address.

* fix: clean up upgrade functions

* fix: uniform names in upgrade function

* fix: use same version in encoding function

* fix: add warning comment to ProxyAdminOwnedBase

* fix: allow claiming credit when paused if mode set

* fix: no migration while paused

* fix: no pause extension if not already paused

* fix: various minor miscellaneous improvements

* chore: pre-pr work

* fix: test failures

* fix: versions in tests

* fix: remove old spacer assertions

* contracts: Prepare MIPS64 semver for release (#15945)

* Update op-conductor to track rollup-boost state (#15316)

* op-supervisor: add StaticConfigDependencySet.Dependencies() getter (#15951)

* op-supervisor: add StaticConfigDependencySet.Dependencies() getter

* return copy of ds.dependencies for safety

* more detailed comment

* fix(kt-devnet): expose L2 rollup config (#15933)

* op-acceptance-tests: interop: Avoid messaging test race (#15954)

* feat: add script for opcm verification (#15420)

* feat: add script for opcm verification

* testing

* testing

* feat: switch to separated verification and presentation

* feat: opcm verification for v200

* feat: use a contract instead

* fix: ci checks

* fix: use randomness not fuzzing

* fix: skip tests for coverage

* feat: automatically scan opcm prefixed properties

* fix: few more test fixes

* feat: add single verification check

* feat: add etherscan constructor verification

* fix: errors found while testing

* op-devstack: allow for shorter test deadlines (#15943)

* op-node: consume L1 signals and p2p blocks as events (#15793)

* op-node: simplify L1 and p2p input events

* op-devstack: fix synctest flake

* op-node: implement review suggestions

* op-{acceptance-tests|devstack}: sync test: op-supervisor ahead of op-node, unsafe chain known with DSL (#15878)

* Move simpleinterop sync test to subdir

* embed chainid to dsl L2CL

* dsl can choose second l2cl and l2el

* redundancy interop dsl

* More traversal of fetching monorepo contracts

* DSL for l2 components + supervisor

* better L2CL DSL

* Add TestUnsafeChainKnownToL2CL test with DSL

* bad copy paste

* DSL consistency

* rebase fix

* better naming

* type safety

* refactor

* better DSL helper names and godoc

* naming error

* go: Update op-geth to v1.101511.0-rc.1, based on geth v1.15.11 (#15829)

* go: Update op-geth to v1.101507.0, based on geth v1.15.7

* op-program: Refresh cannon compat report

* add missing mt64 vm profile config

* go: Update op-geth to v1.101510.0, based on geth v1.15.10

* go: Update op-geth to v1.101511.0, based on geth v1.15.11

---------

Co-authored-by: inphi <mlaw2501@gmail.com>

* fix: have SuperchainConfig expose legacy paused function (#15959)

Updates the SuperchainConfig so that it exposes the legacy
paused function. Paused is the only function that was removed
from the interface.

* fix: small issues in portal comments (#15960)

* fix: small issues in portal comments

* fix: pre-pr

* feat: update StandardValidator for U16 (#15923)

* [U16] Update Anchor Root Validation approach (#15918)

* [U16] Update Anchor Root Validation approach

* Update packages/contracts-bedrock/src/L1/StandardValidator.sol

Co-authored-by: Adrian Sutton <adrian@oplabs.co>

* fix tests

* fixes

* fix failing tests

* improve, add tests

---------

Co-authored-by: Adrian Sutton <adrian@oplabs.co>

* ctb: Add natspec to the StandardValidator (#15969)

* ctb: Add natspec to the StandardValidator

* Remove @return comments, we don't use them in most other contracts

* remove @param too

* Remove stringEq

* fix(op-acceptance-tests): make sure to use provisioned devnet (#15970)

By default devstack-based tests use the sysgo backend.
In the context of acceptance tests we want to make sure the devnet we
just provisioned is being used.

* fix(devnet-sdk): allow overriding ctrl interface detection (#15971)

In the context of op-acceptor, we now potentially override the
definition of the received devnet to graft add-ons.
This loses the ability to reach the control interface though.

This change re-enables this, by providing an override mechanism that
op-acceptor can make use of.

* op-{acceptance-tests|devstack}: sync test: op-node ahead of op-supervisor with DSL (#15908)

* DSL for l2 components + supervisor

* type safety

* support multisupervisor system

* expose interopRPC towards DSL

* Add TestL2CLAheadOfSupervisor with DSL

* better naming

* godoc and better DSL naming and typing

* prefix with decimal for supervisor ordering

* Capitalize test log msgs

* rebase fix

* More graceful rewind

* spread out godoc scenario in test

* Add comment about shim L2CL interop fields

* feat(op-acceptance-tests): run AT's pre-merge (#15953)

Runs a subset of acceptance tests pre-merge to develop, in a non-blocking way.
Also makes the test workflow at least 5 minutes faster.

* Update CODEOWNERS (#15956)

Add a CODEOWNERS comment used to require a minimal number of reviews for that specific path

* feat(op-acceptance-tests): op-acceptor v0.2.0 (#15975)

* fix: StandardValidator incorrect checks (#15977)

Fixes a number of incorrect checks added to the StandardValidator
recently.

* refactor(test): improve DataAvailabilityChallenge test structure and documentation (#15650)

* refactor(test): improve DataAvailabilityChallenge test structure and documentation

- consolidate test initialization into a single DataAvailabilityChallenge_TestInit contract
- organize individual test functions into separate contracts inheriting from TestInit
- add @title and @notice tags to all test contracts
- ensure comment lines stay within 100 character limit

* refactor(test): add natspec comments to test functions

* refactor(test): fix formatting and enforce documentation line limits

- ran `just pre-pr` to resolve format check failures
- ensured all inline comments stay within the 100-character limit

* refactor(test): improve L1ERC721Bridge test structure and documentation (#15735)

* refactor(test): improve L1ERC721Bridge test structure and documentation

- consolidate test initialization into a single L1ERC721Bridge_TestInit contract
- organize individual test functions into separate contracts inheriting from TestInit
- add @title and @notice tags to all test contracts
- convert @dev to @notice tags where appropriate
- ensure comment lines stay within 100 character limit
- move test_pause_finalizeBridgeERC721_reverts into FinalizeBridgeERC721 contract
- rename test_pause_finalizeBridgeERC721_reverts to test_finalizeBridgeERC721_paused_reverts
- inline PauseFail contract's setup directly into the renamed test function

* fix(test): fix bridge reference and remove @dev tag in L1ERC721Bridge tests

- Replace l1StandardBridge with l1ERC721Bridge in test_pause_matchesSuperchainConfig_succeeds test assertions
- Remove @dev tag from inside test_finalizeBridgeERC721_paused_reverts function test comment

* Increase MAX_GAS_LIMIT to a new value that's safe with MT Cannon (#15864)

---------

Co-authored-by: mbaxter <meredith@oplabs.co>
Co-authored-by: Adrian Sutton <adrian@oplabs.co>
Co-authored-by: Yann Hodique <yann@oplabs.co>
Co-authored-by: Axel Kingsley <axel.kingsley@gmail.com>
Co-authored-by: protolambda <proto@protolambda.com>
Co-authored-by: Teddy Knox <teddy@oplabs.co>
Co-authored-by: zhiqiangxu <652732310@qq.com>
Co-authored-by: George Knee <georgeknee@googlemail.com>
Co-authored-by: Sam Stokes <35908605+bitwiseguy@users.noreply.github.com>
Co-authored-by: Ján Jakub Naništa <jan.jakub.nanista@gmail.com>
Co-authored-by: Park Changwan <pcw109550@gmail.com>
Co-authored-by: Hex <165055168+hexshire@users.noreply.github.com>
Co-authored-by: AgusDuha <81362284+agusduha@users.noreply.github.com>
Co-authored-by: smartcontracts <kelvin@optimism.io>
Co-authored-by: Inphi <mlaw2501@gmail.com>
Co-authored-by: Michael Amadi <amadimichaeld@gmail.com>
Co-authored-by: Stefano Charissis <stefano@oplabs.co>
Co-authored-by: clabby <ben@clab.by>
Co-authored-by: Anton Evangelatov <anton.evangelatov@gmail.com>
Co-authored-by: Anton Evangelatov <anton.evangelatov@oplabs.co>
Co-authored-by: Raffaele <151576068+raffaele-oplabs@users.noreply.github.com>
Co-authored-by: Matthew Slipper <me@matthewslipper.com>
Co-authored-by: steven <12021290+stevennevins@users.noreply.github.com>
Co-authored-by: Josh Klopfenstein <git@joshklop.com>
Co-authored-by: Sebastian Stammler <seb@oplabs.co>
Co-authored-by: Ariel Diaz <65925295+aliersh@users.noreply.github.com>
Co-authored-by: Paul Dowman <paul@pauldowman.com>
iquidus pushed a commit to Layr-Labs/optimism that referenced this pull request Jul 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants