diff --git a/README.md b/README.md index 6b7a4144..ca265579 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -## Welcome to Optimism Package +# Welcome to Optimism Package + The default package for Optimism. The kurtosis package uses [op-deployer](https://github.com/ethereum-optimism/optimism/tree/develop/op-deployer) to manage the L2 chains and all associated artifacts such as contract deployments. @@ -33,7 +34,8 @@ Please note, by default your network will be running a `minimal` preset Ethereum You can also completely remove `ethereum_package` from your configuration in which case it will default to a `minimal` preset Ethereum network. ## Quickstart -#### Run with your own configuration + +### Run with your own configuration Kurtosis packages are parameterizable, meaning you can customize your network and its behavior to suit your needs by storing parameters in a file that you can pass in at runtime like so: @@ -51,7 +53,7 @@ kurtosis clean -a This will stop and remove all running enclaves and **delete all data**. -#### Run with changes to the optimism package +### Run with changes to the optimism package If you are attempting to test any changes to the package code, you can point to the directory as the `run` argument @@ -60,11 +62,11 @@ cd ~/go/src/github.com/ethpandaops/optimism-package kurtosis run . --args-file ./network_params.yaml ``` -# L2 Contract deployer -The enclave will automatically deploy an optimism L2 contract on the L1 network. The contract address will be printed in the logs. You can use this contract address to interact with the L2 network. +## L2 Contract deployer -Please refer to this Dockerfile if you want to see how the contract deployer image is built: [Dockerfile](https://github.com/ethpandaops/eth-client-docker-image-builder/blob/master/op-contract-deployer/Dockerfile) +The enclave will automatically deploy an optimism L2 contract on the L1 network. The contract address will be printed in the logs. You can use this contract address to interact with the L2 network. +Please refer to this Dockerfile if you want to see how the contract deployer image is built: [Dockerfile](https://github.com/ethereum-optimism/optimism/blob/develop/op-deployer/Dockerfile.default) ## Configuration @@ -73,6 +75,20 @@ The full YAML schema that can be passed in is as follows with the defaults provi ```yaml optimism_package: + # Interop configuration + interop: + # Whether or not to enable interop mode + enabled: false + # Default supervisor configuration + supervisor_params: + # The Docker image that should be used for the supervisor; leave blank to use the default op-supervisor image + image: "" + + # A JSON string containing chain dependencies + dependency_set: "" + + # A list of optional extra params that will be passed to the supervisor container for modifying its behaviour + extra_params: [] # An array of L2 networks to run chains: # Specification of the optimism-participants in the network @@ -403,7 +419,7 @@ ethereum_package: #### L1 customization -It is required you to launch an L1 Ethereum node to interact with the L2 network. You can use the `ethereum_package` to launch an Ethereum node. The `ethereum_package` configuration is as follows: +It is required for you to launch an L1 Ethereum node to interact with the L2 network. You can use the `ethereum_package` to launch an Ethereum node. The `ethereum_package` configuration is as follows: ```yaml optimism_package: @@ -501,6 +517,7 @@ ethereum_package: - dora - blockscout ``` + Note: if configuring multiple L2s, make sure that the `network_id` and `name` are set to differentiate networks. #### Rollup Boost for External Block Building @@ -525,49 +542,51 @@ optimism_package: #### Run tx-fuzz to send l2 transactions -Compile https://github.com/MariusVanDerWijden/tx-fuzz locally per instructions in the repo. Run tx-fuzz against the l2 EL client's RPC URL and using the pre-funded wallet +Compile [tx-fuzz](https://github.com/MariusVanDerWijden/tx-fuzz) locally per instructions in the repo. Run tx-fuzz against the l2 EL client's RPC URL and using the pre-funded wallet: -``` +```bash ./livefuzzer spam --sk "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" --rpc http://127.0.0.1: --slot-time 2 ``` ### Additional configurations + Please find examples of additional configurations in the [test folder](.github/tests/). ### Useful Kurtosis commands #### Inspect enclave -- Container/Port information -* List information about running containers and open ports +- List information about running containers and open ports -``` +```bash kurtosis enclave ls kurtosis enclave inspect ``` -* Inspect chain state. +- Inspect chain state. -``` +```bash kurtosis files inspect op-deployer-configs ``` -* Dump all files generated by kurtosis to disk (for inspecting chain state/deploy configs/contract addresses etc.). A file that contains an exhaustive +- Dump all files generated by kurtosis to disk (for inspecting chain state/deploy configs/contract addresses etc.). A file that contains an exhaustive set of information about the current deployment is `files/op-deployer-configs/state.json`. Deployed contract address, roles etc can all be found here. -``` -kurtosis enclave dump -- dumps all files to a enclave-name prefixed directory under the current directory +```bash +# dumps all files to a enclave-name prefixed directory under the current directory +kurtosis enclave dump kurtosis files download op-deployer-configs ``` -* Get logs for running services +- Get logs for running services -``` -kurtosis service logs -f . (-f tails the log) +```bash +kurtosis service logs -f . # -f tails the log ``` -* Stop/Start running service (restart sequencer/batcher/op-geth etc.) +- Stop/Start running service (restart sequencer/batcher/op-geth etc.) -``` +```bash kurtosis service stop kurtosis service start ``` @@ -576,6 +595,6 @@ kurtosis service start If you have made changes and would like to submit a PR, test locally and make sure to run `lint` on your changes -``` -kurtosis lint --format . +```bash +kurtosis lint --format . ``` diff --git a/main.star b/main.star index 66baba2f..fe00ae2c 100644 --- a/main.star +++ b/main.star @@ -1,8 +1,14 @@ ethereum_package = import_module("github.com/ethpandaops/ethereum-package/main.star") contract_deployer = import_module("./src/contracts/contract_deployer.star") l2_launcher = import_module("./src/l2.star") +op_supervisor_launcher = import_module( + "./src/interop/op-supervisor/op_supervisor_launcher.star" +) wait_for_sync = import_module("./src/wait/wait_for_sync.star") input_parser = import_module("./src/package_io/input_parser.star") +ethereum_package_static_files = import_module( + "github.com/ethpandaops/ethereum-package/src/static_files/static_files.star" +) def run(plan, args): @@ -34,6 +40,8 @@ def run(plan, args): global_log_level = optimism_args_with_right_defaults.global_log_level persistent = optimism_args_with_right_defaults.persistent + interop_params = optimism_args_with_right_defaults.interop + # Deploy the L1 l1_network = "" if external_l1_args: @@ -82,12 +90,19 @@ def run(plan, args): l1_network, ) + jwt_file = plan.upload_files( + src=ethereum_package_static_files.JWT_PATH_FILEPATH, + name="op_jwt_file", + ) + + all_participants = [] for l2_num, chain in enumerate(optimism_args_with_right_defaults.chains): - l2_launcher.launch_l2( + all_participants += l2_launcher.launch_l2( plan, l2_num, chain.network_params.name, chain, + jwt_file, deployment_output, l1_config_env_vars, l1_priv_key, @@ -96,6 +111,16 @@ def run(plan, args): global_node_selectors, global_tolerations, persistent, + interop_params, + ) + + if interop_params.enabled: + op_supervisor_launcher.launch( + plan, + l1_config_env_vars, + all_participants, + jwt_file, + interop_params.supervisor_params, ) diff --git a/src/cl/op-node/op_node_launcher.star b/src/cl/op-node/op_node_launcher.star index 31b14783..42262aa4 100644 --- a/src/cl/op-node/op_node_launcher.star +++ b/src/cl/op-node/op_node_launcher.star @@ -17,6 +17,7 @@ ethereum_package_input_parser = import_module( constants = import_module("../../package_io/constants.star") util = import_module("../../util.star") +interop_constants = import_module("../../interop/constants.star") # ---------------------------------- Beacon client ------------------------------------- @@ -73,6 +74,7 @@ def launch( existing_cl_clients, l1_config_env_vars, sequencer_enabled, + interop_params, ): beacon_node_identity_recipe = PostHttpRequestRecipe( endpoint="/", @@ -104,6 +106,7 @@ def launch( l1_config_env_vars, beacon_node_identity_recipe, sequencer_enabled, + interop_params, ) beacon_service = plan.add_service(service_name, config) @@ -148,6 +151,7 @@ def get_beacon_config( l1_config_env_vars, beacon_node_identity_recipe, sequencer_enabled, + interop_params, ): EXECUTION_ENGINE_ENDPOINT = "http://{0}:{1}".format( el_context.ip_addr, @@ -223,10 +227,27 @@ def get_beacon_config( ], ) - ports = {} - ports.update(used_ports) + ports = dict(used_ports) + + env_vars = dict(participant.cl_extra_env_vars) + + if interop_params.enabled: + ports[ + interop_constants.INTEROP_WS_PORT_ID + ] = ethereum_package_shared_utils.new_port_spec( + interop_constants.INTEROP_WS_PORT_NUM, + ethereum_package_shared_utils.TCP_PROTOCOL, + ) + + env_vars.update( + { + "OP_NODE_INTEROP_SUPERVISOR": interop_constants.SUPERVISOR_ENDPOINT, + "OP_NODE_INTEROP_RPC_ADDR": "0.0.0.0", + "OP_NODE_INTEROP_RPC_PORT": str(interop_constants.INTEROP_WS_PORT_NUM), + "OP_NODE_INTEROP_JWT_SECRET": ethereum_package_constants.JWT_MOUNT_PATH_ON_CONTAINER, + } + ) - env_vars = participant.cl_extra_env_vars config_args = { "image": participant.cl_image, "ports": ports, @@ -263,9 +284,10 @@ def get_beacon_config( return ServiceConfig(**config_args) -def new_op_node_launcher(deployment_output, jwt_file, network_params): +def new_op_node_launcher(deployment_output, jwt_file, network_params, interop_params): return struct( deployment_output=deployment_output, jwt_file=jwt_file, network_params=network_params, + interop_params=interop_params, ) diff --git a/src/el/op-besu/op_besu_launcher.star b/src/el/op-besu/op_besu_launcher.star index a47571cb..d47dc3d0 100644 --- a/src/el/op-besu/op_besu_launcher.star +++ b/src/el/op-besu/op_besu_launcher.star @@ -105,6 +105,7 @@ def launch( existing_el_clients, sequencer_enabled, sequencer_context, + interop_params, ): log_level = ethereum_package_input_parser.get_client_log_level_or_default( participant.el_log_level, global_log_level, VERBOSITY_LEVELS @@ -275,10 +276,12 @@ def new_op_besu_launcher( jwt_file, network, network_id, + interop_params, ): return struct( deployment_output=deployment_output, jwt_file=jwt_file, network=network, network_id=network_id, + interop_params=interop_params, ) diff --git a/src/el/op-erigon/op_erigon_launcher.star b/src/el/op-erigon/op_erigon_launcher.star index 264985a7..6d67972d 100644 --- a/src/el/op-erigon/op_erigon_launcher.star +++ b/src/el/op-erigon/op_erigon_launcher.star @@ -97,6 +97,7 @@ def launch( existing_el_clients, sequencer_enabled, sequencer_context, + interop_params, ): log_level = ethereum_package_input_parser.get_client_log_level_or_default( participant.el_log_level, global_log_level, VERBOSITY_LEVELS @@ -270,10 +271,12 @@ def new_op_erigon_launcher( jwt_file, network, network_id, + interop_params, ): return struct( deployment_output=deployment_output, jwt_file=jwt_file, network=network, network_id=network_id, + interop_params=interop_params, ) diff --git a/src/el/op-geth/op_geth_launcher.star b/src/el/op-geth/op_geth_launcher.star index 71a64503..7de38d9f 100644 --- a/src/el/op-geth/op_geth_launcher.star +++ b/src/el/op-geth/op_geth_launcher.star @@ -22,6 +22,7 @@ ethereum_package_constants = import_module( ) constants = import_module("../../package_io/constants.star") +interop_constants = import_module("../../interop/constants.star") RPC_PORT_NUM = 8545 WS_PORT_NUM = 8546 @@ -104,6 +105,7 @@ def launch( existing_el_clients, sequencer_enabled, sequencer_context, + interop_params, ): log_level = ethereum_package_input_parser.get_client_log_level_or_default( participant.el_log_level, global_log_level, VERBOSITY_LEVELS @@ -124,6 +126,7 @@ def launch( cl_client_name, sequencer_enabled, sequencer_context, + interop_params, ) service = plan.add_service(service_name, config) @@ -166,6 +169,7 @@ def get_config( cl_client_name, sequencer_enabled, sequencer_context, + interop_params, ): init_datadir_cmd_str = "geth init --datadir={0} --state.scheme=hash {1}".format( EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, @@ -248,7 +252,12 @@ def get_config( constants.EL_TYPE.op_geth + "_volume_size" ], ) - env_vars = participant.el_extra_env_vars + + env_vars = dict(participant.cl_extra_env_vars) + + if interop_params.enabled: + env_vars["GETH_ROLLUP_INTEROPRPC"] = interop_constants.SUPERVISOR_ENDPOINT + config_args = { "image": participant.el_image, "ports": used_ports, @@ -280,14 +289,12 @@ def get_config( def new_op_geth_launcher( - deployment_output, - jwt_file, - network, - network_id, + deployment_output, jwt_file, network, network_id, interop_params ): return struct( deployment_output=deployment_output, jwt_file=jwt_file, network=network, network_id=network_id, + interop_params=interop_params, ) diff --git a/src/el/op-nethermind/op_nethermind_launcher.star b/src/el/op-nethermind/op_nethermind_launcher.star index 7ff3d466..414fd12f 100644 --- a/src/el/op-nethermind/op_nethermind_launcher.star +++ b/src/el/op-nethermind/op_nethermind_launcher.star @@ -99,6 +99,7 @@ def launch( existing_el_clients, sequencer_enabled, sequencer_context, + interop_params, ): log_level = ethereum_package_input_parser.get_client_log_level_or_default( participant.el_log_level, global_log_level, VERBOSITY_LEVELS @@ -260,10 +261,12 @@ def new_nethermind_launcher( jwt_file, network, network_id, + interop_params, ): return struct( deployment_output=deployment_output, jwt_file=jwt_file, network=network, network_id=network_id, + interop_params=interop_params, ) diff --git a/src/el/op-reth/op_reth_launcher.star b/src/el/op-reth/op_reth_launcher.star index 3b9a8f4f..70211929 100644 --- a/src/el/op-reth/op_reth_launcher.star +++ b/src/el/op-reth/op_reth_launcher.star @@ -94,6 +94,7 @@ def launch( existing_el_clients, sequencer_enabled, sequencer_context, + interop_params, ): log_level = ethereum_package_input_parser.get_client_log_level_or_default( participant.el_log_level, global_log_level, VERBOSITY_LEVELS @@ -257,10 +258,12 @@ def new_op_reth_launcher( jwt_file, network, network_id, + interop_params, ): return struct( deployment_output=deployment_output, jwt_file=jwt_file, network=network, network_id=network_id, + interop_params=interop_params, ) diff --git a/src/el_cl_launcher.star b/src/el_cl_launcher.star index 82d9cc26..36588f3b 100644 --- a/src/el_cl_launcher.star +++ b/src/el_cl_launcher.star @@ -37,6 +37,7 @@ def launch( global_tolerations, persistent, additional_services, + interop_params, ): el_launchers = { "op-geth": { @@ -45,6 +46,7 @@ def launch( jwt_file, network_params.network, network_params.network_id, + interop_params, ), "launch_method": op_geth.launch, }, @@ -54,6 +56,7 @@ def launch( jwt_file, network_params.network, network_params.network_id, + interop_params, ), "launch_method": op_reth.launch, }, @@ -63,6 +66,7 @@ def launch( jwt_file, network_params.network, network_params.network_id, + interop_params, ), "launch_method": op_erigon.launch, }, @@ -72,6 +76,7 @@ def launch( jwt_file, network_params.network, network_params.network_id, + interop_params, ), "launch_method": op_nethermind.launch, }, @@ -81,6 +86,7 @@ def launch( jwt_file, network_params.network, network_params.network_id, + interop_params, ), "launch_method": op_besu.launch, }, @@ -89,7 +95,7 @@ def launch( cl_launchers = { "op-node": { "launcher": op_node.new_op_node_launcher( - deployment_output, jwt_file, network_params + deployment_output, jwt_file, network_params, interop_params ), "launch_method": op_node.launch, }, @@ -223,6 +229,7 @@ def launch( all_el_contexts, sequencer_enabled, sequencer_context, + interop_params, ) if rollup_boost_enabled: @@ -241,6 +248,7 @@ def launch( all_el_contexts, sequencer_enabled, sequencer_context, + interop_params, ) else: el_builder_context = struct( @@ -282,6 +290,7 @@ def launch( all_cl_contexts, l1_config_env_vars, sequencer_enabled, + interop_params, ) sequencer_enabled = False diff --git a/src/interop/constants.star b/src/interop/constants.star new file mode 100644 index 00000000..a48ac7c3 --- /dev/null +++ b/src/interop/constants.star @@ -0,0 +1,10 @@ +INTEROP_WS_PORT_ID = "interop-ws" +INTEROP_WS_PORT_NUM = 9645 + +SUPERVISOR_SERVICE_NAME = "op-supervisor" +SUPERVISOR_RPC_PORT_ID = "rpc" +SUPERVISOR_RPC_PORT_NUM = 8545 + +SUPERVISOR_ENDPOINT = "http://{0}:{1}".format( + SUPERVISOR_SERVICE_NAME, SUPERVISOR_RPC_PORT_NUM +) diff --git a/src/interop/op-supervisor/op_supervisor_launcher.star b/src/interop/op-supervisor/op_supervisor_launcher.star new file mode 100644 index 00000000..1c8a1d16 --- /dev/null +++ b/src/interop/op-supervisor/op_supervisor_launcher.star @@ -0,0 +1,96 @@ +utils = import_module("../../util.star") + +ethereum_package_shared_utils = import_module( + "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" +) + +ethereum_package_constants = import_module( + "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" +) + +interop_constants = import_module("../constants.star") + + +def get_used_ports(): + used_ports = { + interop_constants.SUPERVISOR_RPC_PORT_ID: ethereum_package_shared_utils.new_port_spec( + interop_constants.SUPERVISOR_RPC_PORT_NUM, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, + ), + } + return used_ports + + +DATA_DIR = "/etc/op-supervisor" +DEPENDENCY_SET_FILE_NAME = "dependency_set.json" + + +def launch( + plan, + l1_config_env_vars, + all_participants, + jwt_file, + supervisor_params, +): + dependency_set_artifact = utils.write_to_file( + plan, supervisor_params.dependency_set, DATA_DIR, DEPENDENCY_SET_FILE_NAME + ) + + config = get_supervisor_config( + plan, + l1_config_env_vars, + all_participants, + jwt_file, + dependency_set_artifact, + supervisor_params, + ) + + supervisor_service = plan.add_service( + interop_constants.SUPERVISOR_SERVICE_NAME, config + ) + + return "op_supervisor" + + +def get_supervisor_config( + plan, + l1_config_env_vars, + all_participants, + jwt_file, + dependency_set_artifact, + supervisor_params, +): + cmd = ["op-supervisor"] + supervisor_params.extra_params + + ports = get_used_ports() + return ServiceConfig( + image=supervisor_params.image, + ports=ports, + files={ + DATA_DIR: dependency_set_artifact, + ethereum_package_constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, + }, + env_vars={ + "OP_SUPERVISOR_DATADIR": "/db", + "OP_SUPERVISOR_DEPENDENCY_SET": "{0}/{1}".format( + DATA_DIR, DEPENDENCY_SET_FILE_NAME + ), + "OP_SUPERVISOR_L1_RPC": l1_config_env_vars["L1_RPC_URL"], + "OP_SUPERVISOR_L2_CONSENSUS_NODES": ",".join( + [ + "http://{0}:{1}".format( + participant.cl_context.ip_addr, + interop_constants.INTEROP_WS_PORT_NUM, + ) + for participant in all_participants + ] + ), + "OP_SUPERVISOR_L2_CONSENSUS_JWT_SECRET": ethereum_package_constants.JWT_MOUNT_PATH_ON_CONTAINER, + "OP_SUPERVISOR_RPC_ADDR": "0.0.0.0", + "OP_SUPERVISOR_RPC_PORT": str(interop_constants.SUPERVISOR_RPC_PORT_NUM), + "OP_SUPERVISOR_RPC_ENABLE_ADMIN": "true", + }, + cmd=cmd, + private_ip_address_placeholder=ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + ) diff --git a/src/l2.star b/src/l2.star index fa7428d5..532a7dde 100644 --- a/src/l2.star +++ b/src/l2.star @@ -2,9 +2,6 @@ participant_network = import_module("./participant_network.star") blockscout = import_module("./blockscout/blockscout_launcher.star") contract_deployer = import_module("./contracts/contract_deployer.star") input_parser = import_module("./package_io/input_parser.star") -ethereum_package_static_files = import_module( - "github.com/ethpandaops/ethereum-package/src/static_files/static_files.star" -) util = import_module("./util.star") @@ -13,6 +10,7 @@ def launch_l2( l2_num, l2_services_suffix, l2_args, + jwt_file, deployment_output, l1_config, l1_priv_key, @@ -21,6 +19,7 @@ def launch_l2( global_node_selectors, global_tolerations, persistent, + interop_params, ): network_params = l2_args.network_params batcher_params = l2_args.batcher_params @@ -29,10 +28,6 @@ def launch_l2( mev_params = l2_args.mev_params plan.print("Deploying L2 with name {0}".format(network_params.name)) - jwt_file = plan.upload_files( - src=ethereum_package_static_files.JWT_PATH_FILEPATH, - name="op_jwt_file{0}".format(l2_services_suffix), - ) all_l2_participants = participant_network.launch_participant_network( plan, @@ -52,6 +47,7 @@ def launch_l2( global_tolerations, persistent, l2_args.additional_services, + interop_params, ) all_el_contexts = [] @@ -90,3 +86,5 @@ def launch_l2( l1_bridge_address ) ) + + return all_l2_participants diff --git a/src/package_io/input_parser.star b/src/package_io/input_parser.star index 6282ce16..37a06ba6 100644 --- a/src/package_io/input_parser.star +++ b/src/package_io/input_parser.star @@ -25,6 +25,10 @@ DEFAULT_CHALLENGER_IMAGES = { "op-challenger": "us-docker.pkg.dev/oplabs-tools-artifacts/images/op-challenger:develop", } +DEFAULT_SUPERVISOR_IMAGES = { + "op-supervisor": "us-docker.pkg.dev/oplabs-tools-artifacts/images/op-supervisor:develop", +} + DEFAULT_PROPOSER_IMAGES = { "op-proposer": "us-docker.pkg.dev/oplabs-tools-artifacts/images/op-proposer:develop", } @@ -51,11 +55,23 @@ def external_l1_network_params_input_parser(plan, input_args): def input_parser(plan, input_args): sanity_check.sanity_check(plan, input_args) results = parse_network_params(plan, input_args) + results["global_log_level"] = "info" results["global_node_selectors"] = {} results["global_tolerations"] = [] results["persistent"] = False + return struct( + interop=struct( + enabled=results["interop"]["enabled"], + supervisor_params=struct( + image=results["interop"]["supervisor_params"]["image"], + dependency_set=results["interop"]["supervisor_params"][ + "dependency_set" + ], + extra_params=results["interop"]["supervisor_params"]["extra_params"], + ), + ), chains=[ struct( participants=[ @@ -155,6 +171,19 @@ def input_parser(plan, input_args): def parse_network_params(plan, input_args): results = {} + + # configure interop + + results["interop"] = default_interop_args() + results["interop"].update(input_args.get("interop", {})) + + results["interop"]["supervisor_params"] = default_supervisor_params() + results["interop"]["supervisor_params"].update( + input_args.get("interop", {}).get("supervisor_params", {}) + ) + + # configure chains + chains = [] seen_names = {} @@ -257,10 +286,14 @@ def parse_network_params(plan, input_args): chains.append(result) results["chains"] = chains + + # configure op-deployer + results["op_contract_deployer_params"] = default_op_contract_deployer_params() results["op_contract_deployer_params"].update( input_args.get("op_contract_deployer_params", {}) ) + results["global_log_level"] = input_args.get("global_log_level", "info") return results @@ -268,6 +301,7 @@ def parse_network_params(plan, input_args): def default_optimism_args(): return { + "interop": default_interop_args(), "chains": default_chains(), "op_contract_deployer_params": default_op_contract_deployer_params(), "global_log_level": "info", @@ -277,6 +311,20 @@ def default_optimism_args(): } +def default_interop_args(): + return { + "enabled": False, + } + + +def default_supervisor_params(): + return { + "image": DEFAULT_SUPERVISOR_IMAGES["op-supervisor"], + "dependency_set": "", + "extra_params": [], + } + + def default_mev_params(): return { "rollup_boost_image": "", diff --git a/src/package_io/sanity_check.star b/src/package_io/sanity_check.star index b3c21f22..5a57bff1 100644 --- a/src/package_io/sanity_check.star +++ b/src/package_io/sanity_check.star @@ -1,3 +1,14 @@ +INTEROP_PARAMS = [ + "enabled", + "supervisor_params", +] + +SUPERVISOR_PARAMS = [ + "image", + "dependency_set", + "extra_params", +] + PARTICIPANT_CATEGORIES = { "participants": [ "el_type", @@ -70,6 +81,7 @@ ADDITIONAL_SERVICES_PARAMS = [ ] ROOT_PARAMS = [ + "interop", "chains", "op_contract_deployer_params", "global_log_level", @@ -78,7 +90,6 @@ ROOT_PARAMS = [ "persistent", ] - EXTERNAL_L1_NETWORK_PARAMS = [ "network_id", "rpc_kind", @@ -120,6 +131,22 @@ def sanity_check(plan, optimism_config): if key not in ROOT_PARAMS: fail("Invalid parameter {0}, allowed fields: {1}".format(key, ROOT_PARAMS)) + if "interop" in optimism_config: + validate_params( + plan, + optimism_config, + "interop", + INTEROP_PARAMS, + ) + + if "supervisor_params" in optimism_config["interop"]: + validate_params( + plan, + optimism_config["interop"], + "supervisor_params", + SUPERVISOR_PARAMS, + ) + chains = optimism_config.get("chains", []) if type(chains) != "list": @@ -153,6 +180,7 @@ def sanity_check(plan, optimism_config): ) combined_root_params.append("additional_services") combined_root_params.append("op_contract_deployer_params") + combined_root_params.append("supervisor_params") if param not in combined_root_params: fail( diff --git a/src/participant_network.star b/src/participant_network.star index 1ba6922e..37b79733 100644 --- a/src/participant_network.star +++ b/src/participant_network.star @@ -27,6 +27,7 @@ def launch_participant_network( global_tolerations, persistent, additional_services, + interop_params, ): num_participants = len(participants) # First EL and sequencer CL @@ -45,6 +46,7 @@ def launch_participant_network( global_tolerations, persistent, additional_services, + interop_params, ) all_participants = [] diff --git a/src/util.star b/src/util.star index 3599f543..c1d1c494 100644 --- a/src/util.star +++ b/src/util.star @@ -18,6 +18,21 @@ def read_json_value(plan, json_file, json_path, mounts=None): return run.output +def write_to_file(plan, contents, directory, file_name): + file_path = "{0}/{1}".format(directory, file_name) + + run = plan.run_sh( + description="Write value to a file artifact", + image=DEPLOYMENT_UTILS_IMAGE, + store=[file_path], + run="mkdir -p '{0}' && echo '{2}' > '{1}'".format( + directory, file_path, contents + ), + ) + + return run.files_artifacts[0] + + def to_hex_chain_id(chain_id): out = "%x" % int(chain_id) pad = 64 - len(out)