Skip to content

Commit d5fb08c

Browse files
authored
feat(supervisor): Add support for kona-supervisor (#291)
Closes #281
1 parent 989a632 commit d5fb08c

8 files changed

Lines changed: 256 additions & 11 deletions

File tree

main.star

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ ethereum_package = import_module("github.com/ethpandaops/ethereum-package/main.s
22
contract_deployer = import_module("./src/contracts/contract_deployer.star")
33
l2_launcher = import_module("./src/l2.star")
44
superchain_launcher = import_module("./src/superchain/launcher.star")
5-
op_supervisor_launcher = import_module("./src/supervisor/op-supervisor/launcher.star")
5+
supervisor_launcher = import_module("./src/supervisor/launcher.star")
66
op_challenger_launcher = import_module("./src/challenger/op-challenger/launcher.star")
77

88
faucet = import_module("./src/faucet/op-faucet/op_faucet_launcher.star")
@@ -150,7 +150,7 @@ def run(plan, args={}):
150150
)
151151

152152
for supervisor_params in optimism_args.supervisors:
153-
op_supervisor_launcher.launch(
153+
supervisor_launcher.launch(
154154
plan=plan,
155155
params=supervisor_params,
156156
l1_config_env_vars=l1_config_env_vars,

src/observability/observability.star

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ def expose_metrics_port(ports, port_id=METRICS_PORT_ID, port_num=METRICS_PORT_NU
4646
)
4747

4848

49-
# configures the CLI flags and ports for a service using the standard op-service setup
49+
# configures the CLI flags and ports for a service using the standard op-service setup.
50+
# Note: kona services use identical metrics args.
5051
def configure_op_service_metrics(cmd, ports):
5152
cmd += [
5253
"--metrics.enabled",
@@ -85,6 +86,7 @@ def new_metrics_job(
8586
}
8687

8788

89+
# Note: kona services use identical metrics registration.
8890
def register_op_service_metrics_job(helper, service, network_name=None):
8991
register_service_metrics_job(
9092
helper,

src/package_io/registry.star

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ OP_NODE = "op-node"
1212
KONA_NODE = "kona-node"
1313
HILDR = "hildr"
1414

15+
OP_SUPERVISOR = "op-supervisor"
16+
KONA_SUPERVISOR = "kona-supervisor"
17+
1518
OP_BATCHER = "op-batcher"
1619
OP_CHALLENGER = "op-challenger"
17-
OP_SUPERVISOR = "op-supervisor"
1820
OP_PROPOSER = "op-proposer"
1921
OP_CONDUCTOR = "op-conductor"
2022
OP_DEPLOYER = "op-deployer"
@@ -50,8 +52,10 @@ _DEFAULT_IMAGES = {
5052
OP_BATCHER: "us-docker.pkg.dev/oplabs-tools-artifacts/images/op-batcher:develop",
5153
# Challenger
5254
OP_CHALLENGER: "us-docker.pkg.dev/oplabs-tools-artifacts/images/op-challenger:develop",
53-
# Supervisor
55+
# op-supervisor
5456
OP_SUPERVISOR: "us-docker.pkg.dev/oplabs-tools-artifacts/images/op-supervisor:develop",
57+
# kona-supervisor
58+
KONA_SUPERVISOR: "ghcr.io/op-rs/kona/kona-supervisor:latest",
5559
# Proposer
5660
OP_PROPOSER: "us-docker.pkg.dev/oplabs-tools-artifacts/images/op-proposer:develop",
5761
# Conductor

src/supervisor/input_parser.star

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@ _id = import_module("/src/util/id.star")
44
_registry = import_module("/src/package_io/registry.star")
55

66
_DEFAULT_ARGS = {
7+
"type": "op-supervisor",
78
"enabled": True,
89
"superchain": None,
910
"image": None,
1011
"extra_params": [],
1112
}
1213

14+
_IMAGE_IDS = {
15+
"op-supervisor": _registry.OP_SUPERVISOR,
16+
"kona-supervisor": _registry.KONA_SUPERVISOR,
17+
}
18+
1319

1420
def parse(args, superchains, registry):
1521
return _filter.remove_none(
@@ -58,18 +64,19 @@ def _parse_instance(supervisor_args, supervisor_name, superchains, registry):
5864
# in the parsed config, but this is a tradeoff that we are willing to make
5965
supervisor_params["superchain"] = superchain
6066

67+
# And default the image to the one in the registry
68+
supervisor_params["image"] = supervisor_params["image"] or _default_image(
69+
supervisor_params["type"], registry
70+
)
71+
6172
# We add name & service name
6273
supervisor_params["name"] = supervisor_name
63-
supervisor_params["service_name"] = "op-supervisor-{}-{}".format(
74+
supervisor_params["service_name"] = "{}-{}-{}".format(
75+
supervisor_params["type"],
6476
supervisor_name,
6577
superchain_name,
6678
)
6779

68-
# And default the image to the one in the registry
69-
supervisor_params["image"] = supervisor_params["image"] or registry.get(
70-
_registry.OP_SUPERVISOR
71-
)
72-
7380
# We'll also define the ports that this supervisor will expose
7481
#
7582
# This is so that we can reference them before the service is created
@@ -80,3 +87,10 @@ def _parse_instance(supervisor_args, supervisor_name, superchains, registry):
8087
}
8188

8289
return struct(**supervisor_params)
90+
91+
92+
def _default_image(participant_type, registry):
93+
if participant_type in _IMAGE_IDS:
94+
return registry.get(_IMAGE_IDS[participant_type])
95+
else:
96+
fail("Invalid supervisor type: {}".format(participant_type))
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
_file = import_module("/src/util/file.star")
2+
_net = import_module("/src/util/net.star")
3+
4+
_ethereum_package_constants = import_module(
5+
"github.com/ethpandaops/ethereum-package/src/package_io/constants.star"
6+
)
7+
8+
_observability = import_module("/src/observability/observability.star")
9+
_prometheus = import_module("/src/observability/prometheus/prometheus_launcher.star")
10+
11+
12+
DATA_DIR = "/etc/kona-supervisor"
13+
DEPENDENCY_SET_FILE_NAME = "dependency_set.json"
14+
15+
16+
def launch(
17+
plan,
18+
params,
19+
l1_config_env_vars,
20+
l2s,
21+
jwt_file,
22+
deployment_output,
23+
observability_helper,
24+
):
25+
supervisor_l2s = [
26+
l2 for l2 in l2s if l2.network_id in params.superchain.participants
27+
]
28+
29+
config = _get_config(
30+
plan=plan,
31+
params=params,
32+
l1_config_env_vars=l1_config_env_vars,
33+
l2s=supervisor_l2s,
34+
jwt_file=jwt_file,
35+
deployment_output=deployment_output,
36+
observability_helper=observability_helper,
37+
)
38+
39+
service = plan.add_service(params.service_name, config)
40+
41+
_observability.register_op_service_metrics_job(
42+
observability_helper,
43+
service,
44+
)
45+
46+
return struct(service=service, l2s=supervisor_l2s)
47+
48+
49+
def _get_config(
50+
plan,
51+
params,
52+
l1_config_env_vars,
53+
l2s,
54+
jwt_file,
55+
deployment_output,
56+
observability_helper,
57+
):
58+
ports = _net.ports_to_port_specs(params.ports)
59+
datadir = params.superchain.dependency_set.name
60+
61+
cmd = ["kona-supervisor"] + params.extra_params
62+
63+
# apply customizations
64+
65+
if observability_helper.enabled:
66+
_observability.configure_op_service_metrics(cmd, ports)
67+
68+
return ServiceConfig(
69+
image=params.image,
70+
ports=ports,
71+
files={
72+
DATA_DIR: params.superchain.dependency_set.name,
73+
_ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: deployment_output,
74+
_ethereum_package_constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file,
75+
},
76+
env_vars={
77+
"DATADIR": "/db",
78+
"DEPENDENCY_SET": "{0}/{1}".format(
79+
DATA_DIR, params.superchain.dependency_set.path
80+
),
81+
"ROLLUP_CONFIG_PATHS": _ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS
82+
+ "/rollup-*.json",
83+
"L1_RPC": l1_config_env_vars["L1_RPC_URL"],
84+
"L2_CONSENSUS_NODES": ",".join(
85+
[
86+
_net.service_url(
87+
participant.cl_context.ip_addr,
88+
params.superchain.ports[_net.INTEROP_RPC_PORT_NAME],
89+
)
90+
for l2 in l2s
91+
for participant in l2.participants
92+
]
93+
),
94+
"L2_CONSENSUS_JWT_SECRET": _ethereum_package_constants.JWT_MOUNT_PATH_ON_CONTAINER,
95+
"RPC_ADDR": "0.0.0.0",
96+
"RPC_PORT": str(params.ports[_net.RPC_PORT_NAME].number),
97+
"RPC_ENABLE_ADMIN": "true",
98+
},
99+
cmd=cmd,
100+
private_ip_address_placeholder=_ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER,
101+
)

src/supervisor/launcher.star

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
op_supervisor_launcher = import_module("./op-supervisor/launcher.star")
2+
kona_supervisor_launcher = import_module("./kona-supervisor/launcher.star")
3+
4+
5+
def launch(
6+
plan,
7+
params,
8+
l1_config_env_vars,
9+
l2s,
10+
jwt_file,
11+
deployment_output,
12+
observability_helper,
13+
):
14+
supervisor_type = params.type
15+
16+
if supervisor_type == "op-supervisor":
17+
return op_supervisor_launcher.launch(
18+
plan=plan,
19+
params=params,
20+
l1_config_env_vars=l1_config_env_vars,
21+
l2s=l2s,
22+
jwt_file=jwt_file,
23+
deployment_output=deployment_output,
24+
observability_helper=observability_helper,
25+
)
26+
elif supervisor_type == "kona-supervisor":
27+
return kona_supervisor_launcher.launch(
28+
plan=plan,
29+
params=params,
30+
l1_config_env_vars=l1_config_env_vars,
31+
l2s=l2s,
32+
jwt_file=jwt_file,
33+
deployment_output=deployment_output,
34+
observability_helper=observability_helper,
35+
)
36+
else:
37+
fail("Unsupported supervisor implementation {}".format(supervisor_type))

test/supervisor/input_parser_test.star

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ def test_supervisor_input_parser_default_args(plan):
9595
},
9696
service_name="op-supervisor-supervisor0-superchain0",
9797
superchain=_superchains[0],
98+
type="op-supervisor",
9899
),
99100
],
100101
)
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
_kona_supervisor_launcher = import_module(
2+
"/src/supervisor/kona-supervisor/launcher.star"
3+
)
4+
5+
_input_parser = import_module("/src/package_io/input_parser.star")
6+
_observability = import_module("/src/observability/observability.star")
7+
_ethereum_package_constants = import_module(
8+
"github.com/ethpandaops/ethereum-package/src/package_io/constants.star"
9+
)
10+
11+
12+
def test_interop_kona_supervisor_ports(plan):
13+
parsed_input_args = _input_parser.input_parser(
14+
plan,
15+
{
16+
"chains": [
17+
{
18+
"network_params": {
19+
"network_id": 1000,
20+
},
21+
"participants": [
22+
{
23+
"el_type": "op-reth",
24+
"el_image": "op-reth:latest",
25+
"cl_type": "op-node",
26+
"cl_image": "op-node:latest",
27+
}
28+
],
29+
}
30+
],
31+
"superchains": {"superchain0": {}},
32+
"supervisors": {
33+
"supervisor0": {
34+
"superchain": "superchain0",
35+
"type": "kona-supervisor",
36+
}
37+
},
38+
},
39+
)
40+
41+
# Just to make sure
42+
expect.ne(parsed_input_args.supervisors, None)
43+
44+
supervisor_params = parsed_input_args.supervisors[0]
45+
expect.ne(supervisor_params, None)
46+
47+
observability_helper = _observability.make_helper(parsed_input_args.observability)
48+
49+
result = _kona_supervisor_launcher.launch(
50+
plan=plan,
51+
l1_config_env_vars={"L1_RPC_URL": "http://l1.rpc"},
52+
l2s=[],
53+
jwt_file="/jwt_file",
54+
params=supervisor_params,
55+
deployment_output="/deployment_output",
56+
observability_helper=observability_helper,
57+
)
58+
59+
service = plan.get_service(supervisor_params.service_name)
60+
expect.ne(service, None)
61+
62+
expect.eq(service.ports["rpc"].number, 8545)
63+
expect.eq(service.ports["rpc"].application_protocol, "http")
64+
65+
service_config = kurtosistest.get_service_config(supervisor_params.service_name)
66+
expect.ne(service_config, None)
67+
68+
expect.eq(service_config.env_vars["RPC_ADDR"], "0.0.0.0")
69+
expect.eq(service_config.env_vars["RPC_PORT"], "8545")
70+
71+
expect.eq(
72+
supervisor_params.superchain.dependency_set.name,
73+
"superchain-depset-superchain0",
74+
)
75+
expect.eq(
76+
supervisor_params.superchain.dependency_set.path,
77+
"superchain-depset-superchain0.json",
78+
)
79+
expect.eq(
80+
service_config.env_vars["DEPENDENCY_SET"],
81+
"/etc/kona-supervisor/superchain-depset-superchain0.json",
82+
)
83+
expect.eq(
84+
service_config.files["/etc/kona-supervisor"].artifact_names,
85+
["superchain-depset-superchain0"],
86+
)

0 commit comments

Comments
 (0)