Skip to content

Commit f9b3519

Browse files
feat: Per-interop-set supervisor (#220)
**Description** Adds a concept of interop sets so that `op-supervisor` can be set up with more nuance. Interop sets get their configuration section under `interop.sets`. A single interop set binds several L2 chains (referenced by their network IDs) into an interoperable system. - The `participants` field refers to network IDs of the L2 chains. Special value `*` can be used to quickly assign all L2s into a single interop set. To simulate misconfiguration, a single L2 can be assigned to multiple interop sets - `supervisor_params` can override default supervisor parameters under `interop.supervisor_params` - Interop is enabled if there is at least one interop set. It can be disabled explicitly either as a whole or per-interop-set using `interop.enabled` and `interop.sets[].enabled` boolean fields
1 parent 9458e27 commit f9b3519

12 files changed

Lines changed: 1023 additions & 58 deletions

File tree

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,31 @@ optimism_package:
133133
image: "grafana/grafana:11.5.0"
134134
# Interop configuration
135135
interop:
136-
# Whether or not to enable interop mode
136+
# Interop can be enabled and disabled using this flag
137+
#
138+
# By default, interop will be enabled if there is at least one interop set specified
137139
enabled: false
140+
# A list of interop sets - connected L2 chains
141+
#
142+
# If left empty, interop is disabled
143+
sets:
144+
# Optional human-readable name for this interop set
145+
- name: "interop-set-0"
146+
# List of L2 network_ids that participate in this set
147+
#
148+
# Please refer to chains[].network_params.network_id for more information
149+
participants: ["2151908"]
150+
# Supervisor overrides for this particular interop set
151+
#
152+
# Leave empty to use the default supervisor configuration
153+
supervisor_params:
154+
# Interop set can be disabled for ease of local development
155+
#
156+
# Defaults to true
157+
enabled: true
158+
- name: "interop-set-1"
159+
# "*" can be used to quickly add all networks into one interop set
160+
participants: "*"
138161
# Default supervisor configuration
139162
supervisor_params:
140163
# The Docker image that should be used for the supervisor; leave blank to use the default op-supervisor image

main.star

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,15 @@ def run(plan, args={}):
124124
)
125125

126126
if interop_params.enabled:
127-
op_supervisor_launcher.launch(
128-
plan,
129-
l1_config_env_vars,
130-
optimism_args.chains,
131-
l2s,
132-
jwt_file,
133-
interop_params.supervisor_params,
134-
observability_helper,
135-
)
127+
for i, interop_set in enumerate(interop_params.sets):
128+
op_supervisor_launcher.launch(
129+
plan=plan,
130+
interop_set=interop_set,
131+
l1_config_env_vars=l1_config_env_vars,
132+
l2s=l2s,
133+
jwt_file=jwt_file,
134+
observability_helper=observability_helper,
135+
)
136136

137137
# challenger must launch after supervisor because it depends on it for interop
138138
for l2_num, l2 in enumerate(l2s):

mise.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[tools]
22

33
# Core dependencies
4-
"ubi:ethereum-optimism/kurtosis-test" = "0.0.1"
4+
"ubi:ethereum-optimism/kurtosis-test" = "0.0.3"
55
"ubi:kurtosis-tech/kurtosis-cli-release-artifacts[exe=kurtosis]" = "1.4.4"
66
"yq" = "v4.44.3"
77

src/interop/constants.star

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
constants = import_module("../package_io/constants.star")
21
util = import_module("../util.star")
32

43
INTEROP_WS_PORT_ID = "interop-ws"

src/interop/op-supervisor/op_supervisor_launcher.star

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ ethereum_package_constants = import_module(
88
"github.com/ethpandaops/ethereum-package/src/package_io/constants.star"
99
)
1010

11-
constants = import_module("../../package_io/constants.star")
1211
observability = import_module("../../observability/observability.star")
1312
prometheus = import_module("../../observability/prometheus/prometheus_launcher.star")
1413

14+
constants = import_module("../../package_io/constants.star")
1515
interop_constants = import_module("../constants.star")
1616

1717

@@ -27,59 +27,90 @@ def get_used_ports():
2727

2828

2929
DATA_DIR = "/etc/op-supervisor"
30-
DEPENDENCY_SET_FILE_NAME = "dependency_set.json"
3130

3231

33-
def create_dependency_set(chains):
32+
def create_dependency_set_filename(interop_set):
33+
return "dependency_set-{}.json".format(interop_set.name)
34+
35+
36+
def create_dependency_set(l2s):
3437
result = {
3538
"dependencies": {
36-
str(chain.network_params.network_id): {
37-
"chainIndex": str(chain.network_params.network_id),
39+
str(l2.network_id): {
40+
"chainIndex": str(l2.network_id),
3841
"activationTime": 0,
3942
"historyMinTime": 0,
4043
}
41-
for chain in chains
44+
for l2 in l2s
4245
}
4346
}
4447
return result
4548

4649

4750
def launch(
4851
plan,
52+
interop_set,
4953
l1_config_env_vars,
50-
chains,
5154
l2s,
5255
jwt_file,
53-
supervisor_params,
5456
observability_helper,
5557
):
56-
dependency_set_json = supervisor_params.dependency_set
57-
if not dependency_set_json:
58-
dependency_set = create_dependency_set(chains)
59-
dependency_set_json = json.encode(dependency_set)
58+
# First we check that the supervisor is enabled for this interop set
59+
if not interop_set.enabled:
60+
plan.print(
61+
"op-supervisor is not enabled for interop set {}, skipping launch".format(
62+
interop_set.name
63+
)
64+
)
65+
return None
66+
67+
# Then we check that we have some participants
68+
if len(interop_set.participants) == 0:
69+
plan.print(
70+
"op-supervisor has no participants for interop set {}, skipping launch".format(
71+
interop_set.name
72+
)
73+
)
74+
return None
75+
76+
# Now we filter out the participating L2s
77+
interop_set_l2s = [l2 for l2 in l2s if l2.network_id in interop_set.participants]
78+
79+
# Now we create dependency set if none was provided
80+
dependency_set_json = interop_set.supervisor_params.dependency_set or json.encode(
81+
create_dependency_set(interop_set_l2s)
82+
)
6083

84+
# And write it to an artifact
85+
dependency_set_filename = create_dependency_set_filename(interop_set)
6186
dependency_set_artifact = utils.write_to_file(
62-
plan, dependency_set_json, DATA_DIR, DEPENDENCY_SET_FILE_NAME
87+
plan, dependency_set_json, DATA_DIR, dependency_set_filename
88+
)
89+
90+
# We create a service name based on the interop set name
91+
service_name = "{}-{}".format(
92+
interop_constants.SUPERVISOR_SERVICE_NAME, interop_set.name
6393
)
6494

6595
config = get_supervisor_config(
66-
plan,
67-
l1_config_env_vars,
68-
l2s,
69-
jwt_file,
70-
dependency_set_artifact,
71-
supervisor_params,
72-
observability_helper,
96+
plan=plan,
97+
l1_config_env_vars=l1_config_env_vars,
98+
l2s=interop_set_l2s,
99+
jwt_file=jwt_file,
100+
dependency_set_artifact=dependency_set_artifact,
101+
dependency_set_filename=dependency_set_filename,
102+
supervisor_params=interop_set.supervisor_params,
103+
observability_helper=observability_helper,
73104
)
74105

75-
service = plan.add_service(interop_constants.SUPERVISOR_SERVICE_NAME, config)
106+
service = plan.add_service(service_name, config)
76107

77108
observability.register_op_service_metrics_job(
78109
observability_helper,
79110
service,
80111
)
81112

82-
return "op_supervisor"
113+
return service
83114

84115

85116
def get_supervisor_config(
@@ -88,6 +119,7 @@ def get_supervisor_config(
88119
l2s,
89120
jwt_file,
90121
dependency_set_artifact,
122+
dependency_set_filename,
91123
supervisor_params,
92124
observability_helper,
93125
):
@@ -110,7 +142,7 @@ def get_supervisor_config(
110142
env_vars={
111143
"OP_SUPERVISOR_DATADIR": "/db",
112144
"OP_SUPERVISOR_DEPENDENCY_SET": "{0}/{1}".format(
113-
DATA_DIR, DEPENDENCY_SET_FILE_NAME
145+
DATA_DIR, dependency_set_filename
114146
),
115147
"OP_SUPERVISOR_L1_RPC": l1_config_env_vars["L1_RPC_URL"],
116148
"OP_SUPERVISOR_L2_CONSENSUS_NODES": ",".join(

0 commit comments

Comments
 (0)