Skip to content
This repository was archived by the owner on Jan 16, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f1cd65f
initial commit
dhyaniarun1993 Aug 20, 2025
70c2aa3
indexer configured
dhyaniarun1993 Aug 20, 2025
85c78e8
admin api added
dhyaniarun1993 Aug 21, 2025
f40f4ba
test cases added + commented code removed
dhyaniarun1993 Aug 21, 2025
f3a1e05
made admin api configurable
dhyaniarun1993 Aug 21, 2025
f49c2a4
improvements
dhyaniarun1993 Aug 22, 2025
fe11703
deleted index file
dhyaniarun1993 Aug 22, 2025
daf7751
doc fixes
dhyaniarun1993 Aug 22, 2025
507ed4a
lintfixes
dhyaniarun1993 Aug 22, 2025
2bc6d41
Merge branch 'main' into feat/supervisor-admin
dhyaniarun1993 Aug 22, 2025
7cf2a7d
chain id check added
dhyaniarun1993 Aug 22, 2025
0f76a75
timeout added to the admin rpc
dhyaniarun1993 Aug 22, 2025
789fc8c
error handling
dhyaniarun1993 Aug 22, 2025
af8c02f
minor change for sysgo support
dhyaniarun1993 Aug 25, 2025
82c39d7
main merged
dhyaniarun1993 Aug 25, 2025
35450ce
review fixes
dhyaniarun1993 Aug 25, 2025
512ae8e
main merged
dhyaniarun1993 Aug 26, 2025
037a872
Merge branch 'main' into feat/supervisor-admin
dhyaniarun1993 Aug 26, 2025
2fe94ca
fix(supervisor/core): l1_exhaust and reorg race condition
dhyaniarun1993 Aug 27, 2025
cf4fd6c
review fixes
dhyaniarun1993 Aug 27, 2025
70369a5
Merge branch 'feat/supervisor-admin' into fix/reorg_race_condition
dhyaniarun1993 Aug 27, 2025
14cf07e
refactor
dhyaniarun1993 Aug 27, 2025
a02fa43
revert log
dhyaniarun1993 Aug 27, 2025
16b037f
Merge branch 'main' into fix/reorg_race_condition
dhyaniarun1993 Aug 28, 2025
70d685b
test cases added
dhyaniarun1993 Aug 28, 2025
b747d23
Merge branch 'fix/reorg_race_condition' of github.com:op-rs/kona into…
dhyaniarun1993 Aug 28, 2025
6bb6c57
feat(test/supervisor): sysgo integration
dhyaniarun1993 Aug 28, 2025
74bef69
workflow updated
dhyaniarun1993 Aug 28, 2025
d591965
l1reorg added to sysgo
dhyaniarun1993 Aug 28, 2025
ea3a058
added minimal presets for simple interop
sadiq1971 Sep 1, 2025
c67022e
updated l1reorg sysgo test to accept custom preset
sadiq1971 Sep 1, 2025
c57ea0b
merged main
sadiq1971 Sep 1, 2025
d9bfe89
Merge branch 'main' into feat/supervisor-sysgo
sadiq1971 Sep 7, 2025
7c2cfeb
merged main
sadiq1971 Sep 8, 2025
fda31c9
fix main
sadiq1971 Sep 8, 2025
39069b4
fix ci
sadiq1971 Sep 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/node_e2e_sysgo_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ jobs:
cache-dependency-path: "**/go.sum"

- name: common tests for node with sysgo orchestrator
run: just test-e2e-sysgo node/common
run: just test-e2e-sysgo node node/common

- name: restart tests for node with sysgo orchestrator
run: just test-e2e-sysgo node/restart
run: just test-e2e-sysgo node node/restart

- name: l2 reorg tests for node with sysgo orchestrator
run: just test-e2e-sysgo node/l2_reorg
run: just test-e2e-sysgo node node/l2_reorg



2 changes: 1 addition & 1 deletion .github/workflows/supervisor_e2e_kurtosis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- devnet-config: simple-supervisor
test-pkg: rpc
- devnet-config: simple-supervisor
test-pkg: l1reorg
test-pkg: l1reorg/kurtosis
- devnet-config: simple-supervisor
test-pkg: l2reorg
- devnet-config: preinterop-supervisor
Expand Down
42 changes: 42 additions & 0 deletions .github/workflows/supervisor_e2e_sysgo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Sysgo E2E Tests Supervisor
on:
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
jobs:
supervisor-e2e-tests:
runs-on: ubuntu-latest
timeout-minutes: 40
name: ${{ matrix.test-pkg }}-tests
strategy:
fail-fast: false
matrix:
test-pkg: ["pre_interop", "l1_reorg/sysgo"]
steps:
- name: Checkout sources
uses: actions/checkout@v5
with:
submodules: true

- uses: ./.github/actions/setup
with:
channel: stable

- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
large-packages: false

- uses: taiki-e/install-action@just

- uses: jdx/mise-action@v3 # installs Mise + runs `mise install`

- name: Setup Go 1.24.3
uses: actions/setup-go@v5
with:
# Semantic version range syntax or exact version of Go
go-version: '1.24.3'
cache-dependency-path: "**/go.sum"

- name: test ${{ matrix.test-pkg }}
run: just test-e2e-sysgo supervisor "/supervisor/${{ matrix.test-pkg }}"
4 changes: 4 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ default:
build-node:
cargo build --release --bin kona-node

# Build the supervisor
build-supervisor:
cargo build --release --bin kona-supervisor

# Run all tests (excluding online tests)
tests: test test-docs

Expand Down
20 changes: 15 additions & 5 deletions tests/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ devnet DEVNET OP_PACKAGE_PATH="" CUSTOM_DEVNET_PATH="":
cleanup-kurtosis:
kurtosis clean -a

test-e2e-sysgo GO_PKG_NAME="" FILTER="" : unzip-contract-artifacts
test-e2e-sysgo BINARY GO_PKG_NAME="" FILTER="" : unzip-contract-artifacts
#!/bin/bash
if [ -z "{{GO_PKG_NAME}}" ]; then
export GO_PKG_NAME="..."
Expand All @@ -57,10 +57,20 @@ test-e2e-sysgo GO_PKG_NAME="" FILTER="" : unzip-contract-artifacts

export OP_DEPLOYER_ARTIFACTS="{{SOURCE}}/artifacts"
export DISABLE_OP_E2E_LEGACY=true
export KONA_NODE_EXEC_PATH="{{SOURCE}}/../target/release/kona-node"
export DEVSTACK_ORCHESTRATOR=sysgo

cd {{SOURCE}}/.. && just build-node

if [ "{{BINARY}}" = "node" ]; then
export KONA_NODE_EXEC_PATH="{{SOURCE}}/../target/release/kona-node"
export DEVSTACK_ORCHESTRATOR=sysgo
cd {{SOURCE}}/.. && just build-node
elif [ "{{BINARY}}" = "supervisor" ]; then
export DEVSTACK_SUPERVISOR_KIND=kona
export KONA_SUPERVISOR_EXEC_PATH="{{SOURCE}}/../target/release/kona-supervisor"
export DEVSTACK_ORCHESTRATOR=sysgo
cd {{SOURCE}}/.. && just build-supervisor
else
echo "Invalid BINARY specified. Must be either 'node' or 'supervisor'."
exit 1
fi

# Run the test with count=1 to avoid caching the test results.
cd {{SOURCE}} && go test -count=1 -timeout 40m -v ./$GO_PKG_NAME $FILTER
Expand Down
14 changes: 14 additions & 0 deletions tests/supervisor/l1reorg/sysgo/init_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package sysgo

import (
"testing"

"github.com/ethereum-optimism/optimism/op-devstack/presets"
spresets "github.com/op-rs/kona/supervisor/presets"
)

// TestMain creates the test-setups against the shared backend
func TestMain(m *testing.M) {
// Other setups may be added here, hydrated from the same orchestrator
presets.DoMain(m, spresets.WithSimpleInteropMinimal())
}
165 changes: 165 additions & 0 deletions tests/supervisor/l1reorg/sysgo/reorg_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package sysgo

import (
"testing"
"time"

"github.com/ethereum-optimism/optimism/op-devstack/devtest"
"github.com/ethereum-optimism/optimism/op-devstack/presets"
"github.com/ethereum-optimism/optimism/op-devstack/stack"
"github.com/ethereum-optimism/optimism/op-devstack/stack/match"
"github.com/ethereum-optimism/optimism/op-service/apis"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
"github.com/ethereum-optimism/optimism/op-test-sequencer/sequencer/seqtypes"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)

type checksFunc func(t devtest.T, sys *presets.SimpleInterop)

func TestL2ReorgAfterL1Reorg(gt *testing.T) {
gt.Run("unsafe reorg", func(gt *testing.T) {
var crossSafeRef, localSafeRef, unsafeRef eth.BlockID
pre := func(t devtest.T, sys *presets.SimpleInterop) {
ss := sys.Supervisor.FetchSyncStatus()
crossSafeRef = ss.Chains[sys.L2ChainA.ChainID()].CrossSafe
localSafeRef = ss.Chains[sys.L2ChainA.ChainID()].LocalSafe
unsafeRef = ss.Chains[sys.L2ChainA.ChainID()].LocalUnsafe.ID()
}
post := func(t devtest.T, sys *presets.SimpleInterop) {
require.True(t, sys.L2ELA.IsCanonical(crossSafeRef), "Previous cross-safe block should still be canonical")
require.True(t, sys.L2ELA.IsCanonical(localSafeRef), "Previous local-safe block should still be canonical")
require.False(t, sys.L2ELA.IsCanonical(unsafeRef), "Previous unsafe block should have been reorged")
}
testL2ReorgAfterL1Reorg(gt, 3, pre, post)
})

gt.Run("unsafe, local-safe, cross-unsafe, cross-safe reorgs", func(gt *testing.T) {
var crossSafeRef, crossUnsafeRef, localSafeRef, unsafeRef eth.BlockID
pre := func(t devtest.T, sys *presets.SimpleInterop) {
ss := sys.Supervisor.FetchSyncStatus()
crossUnsafeRef = ss.Chains[sys.L2ChainA.ChainID()].CrossUnsafe
crossSafeRef = ss.Chains[sys.L2ChainA.ChainID()].CrossSafe
localSafeRef = ss.Chains[sys.L2ChainA.ChainID()].LocalSafe
unsafeRef = ss.Chains[sys.L2ChainA.ChainID()].LocalUnsafe.ID()
}
post := func(t devtest.T, sys *presets.SimpleInterop) {
require.False(t, sys.L2ELA.IsCanonical(crossSafeRef), "Previous cross-safe block should have been reorged")
require.False(t, sys.L2ELA.IsCanonical(crossUnsafeRef), "Previous cross-unsafe block should have been reorged")
require.False(t, sys.L2ELA.IsCanonical(localSafeRef), "Previous local-safe block should have been reorged")
require.False(t, sys.L2ELA.IsCanonical(unsafeRef), "Previous unsafe block should have been reorged")
}
testL2ReorgAfterL1Reorg(gt, 10, pre, post)
})
}

// testL2ReorgAfterL1Reorg tests that the L2 chain reorgs after an L1 reorg, and takes n, number of blocks to reorg, as parameter
// for unsafe reorgs - n must be at least >= confDepth, which is 2 in our test deployments
// for cross-safe reorgs - n must be at least >= safe distance, which is 10 in our test deployments (set in
// op-e2e/e2eutils/geth/geth.go when initialising FakePoS)
// pre- and post-checks are sanity checks to ensure that the blocks we expected to be reorged were indeed reorged or not
func testL2ReorgAfterL1Reorg(gt *testing.T, n int, preChecks, postChecks checksFunc) {
t := devtest.SerialT(gt)
ctx := t.Ctx()

sys := presets.NewSimpleInterop(t)
ts := sys.TestSequencer.Escape().ControlAPI(sys.L1Network.ChainID())

cl := sys.L1Network.Escape().L1CLNode(match.FirstL1CL)

sys.L1Network.WaitForBlock()

sys.ControlPlane.FakePoSState(cl.ID(), stack.Stop)

// sequence a few L1 and L2 blocks
for range n + 1 {
sequenceL1Block(t, ts, common.Hash{})

sys.L2ChainA.WaitForBlock()
sys.L2ChainA.WaitForBlock()
}

// select a divergence block to reorg from
var divergence eth.L1BlockRef
{
tip := sys.L1EL.BlockRefByLabel(eth.Unsafe)
require.Greater(t, tip.Number, uint64(n), "n is larger than L1 tip, cannot reorg out block number `tip-n`")

divergence = sys.L1EL.BlockRefByNumber(tip.Number - uint64(n))
}

// print the chains before sequencing an alternative L1 block
sys.L2ChainA.PrintChain()
sys.L1Network.PrintChain()

// pre reorg trigger validations and checks
preChecks(t, sys)

tipL2_preReorg := sys.L2ELA.BlockRefByLabel(eth.Unsafe)

// reorg the L1 chain -- sequence an alternative L1 block from divergence block parent
sequenceL1Block(t, ts, divergence.ParentHash)

// continue building on the alternative L1 chain
sys.ControlPlane.FakePoSState(cl.ID(), stack.Start)

// confirm L1 reorged
sys.L1EL.ReorgTriggered(divergence, 5)

// wait until L2 chain A cross-safe ref caught up to where it was before the reorg
sys.L2CLA.Reached(types.CrossSafe, tipL2_preReorg.Number, 50)

// test that latest chain A unsafe is not referencing a reorged L1 block (through the L1Origin field)
require.Eventually(t, func() bool {
unsafe := sys.L2ELA.BlockRefByLabel(eth.Unsafe)

block, err := sys.L1EL.Escape().EthClient().InfoByNumber(ctx, unsafe.L1Origin.Number)
if err != nil {
sys.Log.Warn("failed to get L1 block info by number", "number", unsafe.L1Origin.Number, "err", err)
return false
}

sys.Log.Info("current unsafe ref", "tip", unsafe, "tip_origin", unsafe.L1Origin, "l1blk", eth.InfoToL1BlockRef(block))

// print the chains so we have information to debug if the test fails
sys.L2ChainA.PrintChain()
sys.L1Network.PrintChain()

return block.Hash() == unsafe.L1Origin.Hash
}, 120*time.Second, 7*time.Second, "L1 block origin hash should match hash of block on L1 at that number. If not, it means there was a reorg, and L2 blocks L1Origin field is referencing a reorged block.")

// confirm all L1Origin fields point to canonical blocks
require.Eventually(t, func() bool {
ref := sys.L2ELA.BlockRefByLabel(eth.Unsafe)
var err error

// wait until L2 chains' L1Origin points to a L1 block after the one that was reorged
if ref.L1Origin.Number < divergence.Number {
return false
}

sys.Log.Info("L2 chain progressed, pointing to newer L1 block", "ref", ref, "ref_origin", ref.L1Origin, "divergence", divergence)

for i := ref.Number; i > 0 && ref.L1Origin.Number >= divergence.Number; i-- {
ref, err = sys.L2ELA.Escape().L2EthClient().L2BlockRefByNumber(ctx, i)
if err != nil {
return false
}

if !sys.L1EL.IsCanonical(ref.L1Origin) {
return false
}
}

return true
}, 120*time.Second, 5*time.Second, "all L1Origin fields should point to canonical L1 blocks")

// post reorg test validations and checks
postChecks(t, sys)
}

func sequenceL1Block(t devtest.T, ts apis.TestSequencerControlAPI, parent common.Hash) {
require.NoError(t, ts.New(t.Ctx(), seqtypes.BuildOpts{Parent: parent}))
require.NoError(t, ts.Next(t.Ctx()))
}
5 changes: 4 additions & 1 deletion tests/supervisor/pre_interop/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import (
"testing"

"github.com/ethereum-optimism/optimism/op-devstack/presets"
spresets "github.com/op-rs/kona/supervisor/presets"
)

// TestMain creates the test-setups against the shared backend
func TestMain(m *testing.M) {
// sleep to ensure the backend is ready

presets.DoMain(m,
presets.WithSimpleInterop(),
spresets.WithSimpleInteropMinimal(),
presets.WithSuggestedInteropActivationOffset(30),
presets.WithInteropNotAtGenesis())

}
3 changes: 1 addition & 2 deletions tests/supervisor/pre_interop/pre_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ func testPreInteropCheckAccessList(t devtest.T, sys *presets.SimpleInterop) {

// Acceptance Test: https://github.com/ethereum-optimism/optimism/blob/develop/op-acceptance-tests/tests/interop/upgrade/pre_test.go
func TestPreNoInbox(gt *testing.T) {
gt.Skip("This test requires op_contract_deployer_params setup in the kurtosis network, which is not available in the devnet setup.")
t := devtest.ParallelT(gt)
sys := presets.NewSimpleInterop(t)
require := t.Require()
Expand All @@ -131,7 +130,7 @@ func TestPreNoInbox(gt *testing.T) {
interopTime := net.Escape().ChainConfig().InteropTime

_, err := sys.Supervisor.Escape().QueryAPI().SyncStatus(t.Ctx())
require.ErrorContains(err, "supervisor status tracker not ready")
require.ErrorContains(err, "chain database is not initialized")

// confirm we are still pre-interop
require.False(net.IsActivated(*interopTime))
Expand Down
Loading