From 05d0fe972f8096570432f8360902430e0490d619 Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Thu, 17 Oct 2024 08:42:28 +0200 Subject: [PATCH] feat: add additional configuration options for participants (#81) --- .github/tests/hildr.yaml | 4 + .github/tests/op-besu.yaml | 2 + .github/tests/op-erigon.yaml | 2 + .github/tests/op-geth.yaml | 2 + .github/tests/op-nethermind.yaml | 2 + .github/tests/op-node.yaml | 2 + .github/tests/op-reth.yaml | 2 + README.md | 129 ++++++++++++++ main.star | 20 ++- network_params.yaml | 26 +++ .../op-batcher/op_batcher_launcher.star | 12 +- src/blockscout/blockscout_launcher.star | 23 ++- src/cl/hildr/hildr_launcher.star | 132 +++++++++----- src/cl/op-node/op_node_launcher.star | 131 ++++++++++---- src/el/op-besu/op_besu_launcher.star | 163 ++++++++++++------ src/el/op-erigon/op_erigon_launcher.star | 163 ++++++++++++------ src/el/op-geth/op_geth_launcher.star | 162 +++++++++++------ .../op-nethermind/op_nethermind_launcher.star | 162 +++++++++++------ src/el/op-reth/op_reth_launcher.star | 154 ++++++++++++----- src/el_cl_launcher.star | 43 ++++- src/l2.star | 12 +- src/package_io/constants.star | 28 +++ src/package_io/input_parser.star | 60 ++++++- src/package_io/sanity_check.star | 27 ++- src/participant_network.star | 8 + .../op-proposer/op_proposer_launcher.star | 12 +- 26 files changed, 1101 insertions(+), 382 deletions(-) create mode 100644 src/package_io/constants.star diff --git a/.github/tests/hildr.yaml b/.github/tests/hildr.yaml index ad3be74..42238e9 100644 --- a/.github/tests/hildr.yaml +++ b/.github/tests/hildr.yaml @@ -9,3 +9,7 @@ optimism_package: cl_type: hildr - el_type: op-erigon cl_type: hildr + - el_type: op-nethermind + cl_type: hildr + - el_type: op-besu + cl_type: hildr diff --git a/.github/tests/op-besu.yaml b/.github/tests/op-besu.yaml index cb82369..c3e7d63 100644 --- a/.github/tests/op-besu.yaml +++ b/.github/tests/op-besu.yaml @@ -3,3 +3,5 @@ optimism_package: - participants: - el_type: op-besu cl_type: op-node + - el_type: op-besu + cl_type: hildr diff --git a/.github/tests/op-erigon.yaml b/.github/tests/op-erigon.yaml index 26bd7b6..5434317 100644 --- a/.github/tests/op-erigon.yaml +++ b/.github/tests/op-erigon.yaml @@ -3,3 +3,5 @@ optimism_package: - participants: - el_type: op-erigon cl_type: op-node + - el_type: op-erigon + cl_type: hildr diff --git a/.github/tests/op-geth.yaml b/.github/tests/op-geth.yaml index a11c25f..dd645ed 100644 --- a/.github/tests/op-geth.yaml +++ b/.github/tests/op-geth.yaml @@ -3,3 +3,5 @@ optimism_package: - participants: - el_type: op-geth cl_type: op-node + - el_type: op-geth + cl_type: hildr diff --git a/.github/tests/op-nethermind.yaml b/.github/tests/op-nethermind.yaml index 1093f32..17c6e64 100644 --- a/.github/tests/op-nethermind.yaml +++ b/.github/tests/op-nethermind.yaml @@ -4,3 +4,5 @@ optimism_package: - el_type: op-geth - el_type: op-nethermind cl_type: op-node + - el_type: op-nethermind + cl_type: hildr diff --git a/.github/tests/op-node.yaml b/.github/tests/op-node.yaml index e9c6d2f..bb3df25 100644 --- a/.github/tests/op-node.yaml +++ b/.github/tests/op-node.yaml @@ -9,3 +9,5 @@ optimism_package: cl_type: op-node - el_type: op-nethermind cl_type: op-node + - el_type: op-besu + cl_type: op-node diff --git a/.github/tests/op-reth.yaml b/.github/tests/op-reth.yaml index 5f959db..a216912 100644 --- a/.github/tests/op-reth.yaml +++ b/.github/tests/op-reth.yaml @@ -3,3 +3,5 @@ optimism_package: - participants: - el_type: op-reth cl_type: op-node + - el_type: op-reth + cl_type: hildr diff --git a/README.md b/README.md index ad1b642..82205c8 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,48 @@ optimism_package: # - op-besu: ghcr.io/optimism-java/op-besu:latest el_image: "" + # The log level string that this participant's EL client should log at + # If this is emptystring then the global `logLevel` parameter's value will be translated into a string appropriate for the client (e.g. if + # global `logLevel` = `info` then Geth would receive `3`, Besu would receive `INFO`, etc.) + # If this is not emptystring, then this value will override the global `logLevel` setting to allow for fine-grained control + # over a specific participant's logging + el_log_level: "" + + # A list of optional extra env_vars the el container should spin up with + el_extra_env_vars: {} + + # A list of optional extra labels the el container should spin up with + # Example; el_extra_labels: {"ethereum-package.partition": "1"} + el_extra_labels: {} + + # A list of optional extra params that will be passed to the EL client container for modifying its behaviour + el_extra_params: [] + + # A list of tolerations that will be passed to the EL client container + # Only works with Kubernetes + # Example: el_tolerations: + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + # toleration_seconds: 3600 + # Defaults to empty + el_tolerations: [] + + # Persistent storage size for the EL client container (in MB) + # Defaults to 0, which means that the default size for the client will be used + # Default values can be found in /src/package_io/constants.star VOLUME_SIZE + el_volume_size: 0 + + # Resource management for el containers + # CPU is milicores + # RAM is in MB + # Defaults to 0, which results in no resource limits + el_min_cpu: 0 + el_max_cpu: 0 + el_min_mem: 0 + el_max_mem: 0 + # CL(Consensus Layer) Specific flags # The type of CL client that should be started # Valid values are: @@ -86,6 +128,67 @@ optimism_package: # - hildr: ghcr.io/optimism-java/hildr:latest cl_image: "" + # The log level string that this participant's CL client should log at + # If this is emptystring then the global `logLevel` parameter's value will be translated into a string appropriate for the client (e.g. if + # If this is not emptystring, then this value will override the global `logLevel` setting to allow for fine-grained control + # over a specific participant's logging + cl_log_level: "" + + # A list of optional extra env_vars the cl container should spin up with + cl_extra_env_vars: {} + + # A list of optional extra labels that will be passed to the CL client Beacon container. + # Example; cl_extra_labels: {"ethereum-package.partition": "1"} + cl_extra_labels: {} + + # A list of optional extra params that will be passed to the CL client Beacon container for modifying its behaviour + # If the client combines the Beacon & validator nodes (e.g. Teku, Nimbus), then this list will be passed to the combined Beacon-validator node + cl_extra_params: [] + + # A list of tolerations that will be passed to the CL client container + # Only works with Kubernetes + # Example: el_tolerations: + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + # toleration_seconds: 3600 + # Defaults to empty + cl_tolerations: [] + + # Persistent storage size for the CL client container (in MB) + # Defaults to 0, which means that the default size for the client will be used + # Default values can be found in /src/package_io/constants.star VOLUME_SIZE + cl_volume_size: 0 + + # Resource management for cl containers + # CPU is milicores + # RAM is in MB + # Defaults to 0, which results in no resource limits + cl_min_cpu: 0 + cl_max_cpu: 0 + cl_min_mem: 0 + cl_max_mem: 0 + + # Participant specific flags + # Node selector + # Only works with Kubernetes + # Example: node_selectors: { "disktype": "ssd" } + # Defaults to empty + node_selectors: {} + + # A list of tolerations that will be passed to the EL/CL/validator containers + # This is to be used when you don't want to specify the tolerations for each container separately + # Only works with Kubernetes + # Example: tolerations: + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + # toleration_seconds: 3600 + # Defaults to empty + tolerations: [] + # Count of nodes to spin up for this participant # Default to 1 count: 1 @@ -142,6 +245,32 @@ optimism_package: op_contract_deployer_params: image: mslipper/op-deployer:latest artifacts_url: https://storage.googleapis.com/oplabs-contract-artifacts/artifacts-v1-4accd01f0c35c26f24d2aa71aba898dd7e5085a2ce5daadc8a84b10caf113409.tar.gz + + # The global log level that all clients should log at + # Valid values are "error", "warn", "info", "debug", and "trace" + # This value will be overridden by participant-specific values + global_log_level: "info" + + # Global node selector that will be passed to all containers (unless overridden by a more specific node selector) + # Only works with Kubernetes + # Example: global_node_selectors: { "disktype": "ssd" } + # Defaults to empty + global_node_selectors: {} + + # Global tolerations that will be passed to all containers (unless overridden by a more specific toleration) + # Only works with Kubernetes + # Example: tolerations: + # - key: "key" + # operator: "Equal" + # value: "value" + # effect: "NoSchedule" + # toleration_seconds: 3600 + # Defaults to empty + global_tolerations: [] + + # Whether the environment should be persistent; this is WIP and is slowly being rolled out accross services + # Defaults to false + persistent: false ``` ### Additional configuration recommendations diff --git a/main.star b/main.star index d66b297..69678d2 100644 --- a/main.star +++ b/main.star @@ -1,8 +1,5 @@ ethereum_package = import_module("github.com/ethpandaops/ethereum-package/main.star") contract_deployer = import_module("./src/contracts/contract_deployer.star") -static_files = import_module( - "github.com/ethpandaops/ethereum-package/src/static_files/static_files.star" -) l2_launcher = import_module("./src/l2.star") wait_for_sync = import_module("./src/wait/wait_for_sync.star") input_parser = import_module("./src/package_io/input_parser.star") @@ -26,6 +23,11 @@ def run(plan, args): # .get will return None if the key is in the config with a None value. optimism_args = args.get("optimism_package") or input_parser.default_optimism_args() optimism_args_with_right_defaults = input_parser.input_parser(plan, optimism_args) + global_tolerations = optimism_args_with_right_defaults.global_tolerations + global_node_selectors = optimism_args_with_right_defaults.global_node_selectors + global_log_level = optimism_args_with_right_defaults.global_log_level + persistent = optimism_args_with_right_defaults.persistent + # Deploy the L1 plan.print("Deploying a local L1") l1 = ethereum_package.run(plan, ethereum_args) @@ -64,6 +66,10 @@ def run(plan, args): l1_config_env_vars, l1_priv_key, all_l1_participants[0].el_context, + global_log_level, + global_node_selectors, + global_tolerations, + persistent, ) return @@ -78,6 +84,10 @@ def run(plan, args): l1_config_env_vars, l1_priv_key, all_l1_participants[0].el_context, + global_log_level, + global_node_selectors, + global_tolerations, + persistent, ) elif type(optimism_args) == "list": seen_names = {} @@ -108,6 +118,10 @@ def run(plan, args): l1_config_env_vars, l1_priv_key, all_l1_participants[0].el_context, + global_log_level, + global_node_selectors, + global_tolerations, + persistent, ) else: fail("invalid type provided for param: `optimism-package`") diff --git a/network_params.yaml b/network_params.yaml index 81b1e0f..6af39b2 100644 --- a/network_params.yaml +++ b/network_params.yaml @@ -3,8 +3,30 @@ optimism_package: - participants: - el_type: op-geth el_image: "" + el_log_level: "" + el_extra_env_vars: {} + el_extra_labels: {} + el_extra_params: [] + el_tolerations: [] + el_volume_size: 0 + el_min_cpu: 0 + el_max_cpu: 0 + el_min_mem: 0 + el_max_mem: 0 cl_type: op-node cl_image: "" + cl_log_level: "" + cl_extra_env_vars: {} + cl_extra_labels: {} + cl_extra_params: [] + cl_tolerations: [] + cl_volume_size: 0 + cl_min_cpu: 0 + cl_max_cpu: 0 + cl_min_mem: 0 + cl_max_mem: 0 + node_selectors: {} + tolerations: [] count: 1 network_params: network: "kurtosis" @@ -19,3 +41,7 @@ optimism_package: op_contract_deployer_params: image: mslipper/op-deployer:latest artifacts_url: https://storage.googleapis.com/oplabs-contract-artifacts/artifacts-v1-4accd01f0c35c26f24d2aa71aba898dd7e5085a2ce5daadc8a84b10caf113409.tar.gz + global_log_level: "info" + global_node_selectors: {} + global_tolerations: [] + persistent: false diff --git a/src/batcher/op-batcher/op_batcher_launcher.star b/src/batcher/op-batcher/op_batcher_launcher.star index 33a5d68..112205a 100644 --- a/src/batcher/op-batcher/op_batcher_launcher.star +++ b/src/batcher/op-batcher/op_batcher_launcher.star @@ -1,8 +1,8 @@ -shared_utils = import_module( +ethereum_package_shared_utils = import_module( "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" ) -constants = import_module( +ethereum_package_constants = import_module( "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" ) @@ -20,10 +20,10 @@ BATCHER_HTTP_PORT_NUM = 8548 def get_used_ports(): used_ports = { - BATCHER_HTTP_PORT_ID: shared_utils.new_port_spec( + BATCHER_HTTP_PORT_ID: ethereum_package_shared_utils.new_port_spec( BATCHER_HTTP_PORT_NUM, - shared_utils.TCP_PROTOCOL, - shared_utils.HTTP_APPLICATION_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, ), } return used_ports @@ -95,5 +95,5 @@ def get_batcher_config( image=image, ports=ports, cmd=cmd, - private_ip_address_placeholder=constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + private_ip_address_placeholder=ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, ) diff --git a/src/blockscout/blockscout_launcher.star b/src/blockscout/blockscout_launcher.star index dd891f2..8316d9f 100644 --- a/src/blockscout/blockscout_launcher.star +++ b/src/blockscout/blockscout_launcher.star @@ -1,16 +1,13 @@ -shared_utils = import_module( +ethereum_package_shared_utils = import_module( "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" ) -constants = import_module( - "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" -) postgres = import_module("github.com/kurtosis-tech/postgres-package/main.star") util = import_module("../util.star") -IMAGE_NAME_BLOCKSCOUT = "blockscout/blockscout-optimism:6.6.0" -IMAGE_NAME_BLOCKSCOUT_VERIF = "ghcr.io/blockscout/smart-contract-verifier:v1.7.0" +IMAGE_NAME_BLOCKSCOUT = "blockscout/blockscout-optimism:6.8.0" +IMAGE_NAME_BLOCKSCOUT_VERIF = "ghcr.io/blockscout/smart-contract-verifier:v1.9.0" SERVICE_NAME_BLOCKSCOUT = "op-blockscout" @@ -29,18 +26,18 @@ BLOCKSCOUT_VERIF_MIN_MEMORY = 10 BLOCKSCOUT_VERIF_MAX_MEMORY = 1024 USED_PORTS = { - HTTP_PORT_ID: shared_utils.new_port_spec( + HTTP_PORT_ID: ethereum_package_shared_utils.new_port_spec( HTTP_PORT_NUMBER, - shared_utils.TCP_PROTOCOL, - shared_utils.HTTP_APPLICATION_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, ) } VERIF_USED_PORTS = { - HTTP_PORT_ID: shared_utils.new_port_spec( + HTTP_PORT_ID: ethereum_package_shared_utils.new_port_spec( HTTP_PORT_NUMBER_VERIF, - shared_utils.TCP_PROTOCOL, - shared_utils.HTTP_APPLICATION_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, ) } @@ -76,7 +73,7 @@ def launch_blockscout( SERVICE_NAME_BLOCKSCOUT, l2_services_suffix ) verif_service = plan.add_service(verif_service_name, config_verif) - verif_url = "http://{}:{}/api".format( + verif_url = "http://{}:{}".format( verif_service.hostname, verif_service.ports["http"].number ) diff --git a/src/cl/hildr/hildr_launcher.star b/src/cl/hildr/hildr_launcher.star index 6b7a587..0cd2d9f 100644 --- a/src/cl/hildr/hildr_launcher.star +++ b/src/cl/hildr/hildr_launcher.star @@ -1,18 +1,21 @@ -shared_utils = import_module( +ethereum_package_shared_utils = import_module( "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" ) -cl_context = import_module( +ethereum_package_cl_context = import_module( "github.com/ethpandaops/ethereum-package/src/cl/cl_context.star" ) -cl_node_ready_conditions = import_module( - "github.com/ethpandaops/ethereum-package/src/cl/cl_node_ready_conditions.star" -) -constants = import_module( +ethereum_package_constants = import_module( "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" ) +ethereum_package_input_parser = import_module( + "github.com/ethpandaops/ethereum-package/src/package_io/input_parser.star" +) + +constants = import_module("../../package_io/constants.star") + util = import_module("../../util.star") # ---------------------------------- Beacon client ------------------------------------- @@ -31,16 +34,16 @@ BEACON_HTTP_PORT_NUM = 8547 def get_used_ports(discovery_port): used_ports = { - BEACON_TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.TCP_PROTOCOL, wait=None + BEACON_TCP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.TCP_PROTOCOL, wait=None ), - BEACON_UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.UDP_PROTOCOL, wait=None + BEACON_UDP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.UDP_PROTOCOL, wait=None ), - BEACON_HTTP_PORT_ID: shared_utils.new_port_spec( + BEACON_HTTP_PORT_ID: ethereum_package_shared_utils.new_port_spec( BEACON_HTTP_PORT_NUM, - shared_utils.TCP_PROTOCOL, - shared_utils.HTTP_APPLICATION_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, ), } return used_ports @@ -49,11 +52,11 @@ def get_used_ports(discovery_port): ENTRYPOINT_ARGS = ["sh", "-c"] VERBOSITY_LEVELS = { - constants.GLOBAL_LOG_LEVEL.error: "ERROR", - constants.GLOBAL_LOG_LEVEL.warn: "WARN", - constants.GLOBAL_LOG_LEVEL.info: "INFO", - constants.GLOBAL_LOG_LEVEL.debug: "DEBUG", - constants.GLOBAL_LOG_LEVEL.trace: "TRACE", + ethereum_package_constants.GLOBAL_LOG_LEVEL.error: "ERROR", + ethereum_package_constants.GLOBAL_LOG_LEVEL.warn: "WARN", + ethereum_package_constants.GLOBAL_LOG_LEVEL.info: "INFO", + ethereum_package_constants.GLOBAL_LOG_LEVEL.debug: "DEBUG", + ethereum_package_constants.GLOBAL_LOG_LEVEL.trace: "TRACE", } @@ -61,7 +64,11 @@ def launch( plan, launcher, service_name, - image, + participant, + global_log_level, + persistent, + tolerations, + node_selectors, el_context, existing_cl_clients, l1_config_env_vars, @@ -79,15 +86,22 @@ def launch( # }, # ) + log_level = ethereum_package_input_parser.get_client_log_level_or_default( + participant.cl_log_level, global_log_level, VERBOSITY_LEVELS + ) + config = get_beacon_config( plan, launcher, - image, service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, el_context, existing_cl_clients, l1_config_env_vars, - # beacon_node_identity_recipe, sequencer_enabled, ) @@ -106,7 +120,7 @@ def launch( # beacon_multiaddr = response["extract.multiaddr"] # beacon_peer_id = response["extract.peer_id"] - return cl_context.new_cl_context( + return ethereum_package_cl_context.new_cl_context( client_name="hildr", enr="", # beacon_node_enr, ip_addr=beacon_service.ip_address, @@ -119,12 +133,15 @@ def launch( def get_beacon_config( plan, launcher, - image, service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, el_context, existing_cl_clients, l1_config_env_vars, - # beacon_node_identity_recipe, sequencer_enabled, ): EXECUTION_ENGINE_ENDPOINT = "http://{0}:{1}".format( @@ -140,7 +157,7 @@ def get_beacon_config( cmd = [ "--devnet", - "--jwt-file=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, + "--jwt-file=" + ethereum_package_constants.JWT_MOUNT_PATH_ON_CONTAINER, "--l1-beacon-url={0}".format(l1_config_env_vars["CL_RPC_URL"]), "--l1-rpc-url={0}".format(l1_config_env_vars["L1_RPC_URL"]), "--l1-ws-rpc-url={0}".format(l1_config_env_vars["L1_WS_URL"]), @@ -150,7 +167,7 @@ def get_beacon_config( "--rpc-port={0}".format(BEACON_HTTP_PORT_NUM), "--sync-mode=full", "--network=" - + constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS + + ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS + "/rollup-{0}.json".format(launcher.network_params.network_id), ] @@ -170,31 +187,60 @@ def get_beacon_config( cmd.append( "--disc-boot-nodes=" + ",".join( - [ctx.enr for ctx in existing_cl_clients[: constants.MAX_ENR_ENTRIES]] + [ + ctx.enr + for ctx in existing_cl_clients[ + : ethereum_package_constants.MAX_ENR_ENTRIES + ] + ] ) ) files = { - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: launcher.deployment_output, - constants.JWT_MOUNTPOINT_ON_CLIENTS: launcher.jwt_file, + ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: launcher.deployment_output, + ethereum_package_constants.JWT_MOUNTPOINT_ON_CLIENTS: launcher.jwt_file, } + if persistent: + files[BEACON_DATA_DIRPATH_ON_SERVICE_CONTAINER] = Directory( + persistent_key="data-{0}".format(service_name), + size=int(participant.cl_volume_size) + if int(participant.cl_volume_size) > 0 + else constants.VOLUME_SIZE[launcher.network][ + constants.CL_TYPE.hildr + "_volume_size" + ], + ) + ports = {} ports.update(used_ports) - return ServiceConfig( - image=image, - ports=ports, - cmd=cmd, - files=files, - private_ip_address_placeholder=constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - # ready_conditions=ReadyCondition( - # recipe=beacon_node_identity_recipe, - # field="code", - # assertion="==", - # target_value=200, - # timeout="1m", - # ), - ) + env_vars = participant.cl_extra_env_vars + config_args = { + "image": participant.cl_image, + "ports": ports, + "cmd": cmd, + "files": files, + "private_ip_address_placeholder": ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "env_vars": env_vars, + "labels": ethereum_package_shared_utils.label_maker( + client=constants.CL_TYPE.op_node, + client_type=constants.CLIENT_TYPES.cl, + image=participant.cl_image, + connected_client=el_context.client_name, + extra_labels=participant.cl_extra_labels, + ), + "tolerations": tolerations, + "node_selectors": node_selectors, + } + + if participant.cl_min_cpu > 0: + config_args["min_cpu"] = participant.cl_min_cpu + if participant.cl_max_cpu > 0: + config_args["max_cpu"] = participant.cl_max_cpu + if participant.cl_min_mem > 0: + config_args["min_memory"] = participant.cl_min_mem + if participant.cl_max_mem > 0: + config_args["max_memory"] = participant.cl_max_mem + return ServiceConfig(**config_args) def new_hildr_launcher(deployment_output, jwt_file, network_params): diff --git a/src/cl/op-node/op_node_launcher.star b/src/cl/op-node/op_node_launcher.star index b5f6d84..9e1477b 100644 --- a/src/cl/op-node/op_node_launcher.star +++ b/src/cl/op-node/op_node_launcher.star @@ -1,18 +1,21 @@ -shared_utils = import_module( +ethereum_package_shared_utils = import_module( "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" ) -cl_context = import_module( +ethereum_package_cl_context = import_module( "github.com/ethpandaops/ethereum-package/src/cl/cl_context.star" ) -cl_node_ready_conditions = import_module( - "github.com/ethpandaops/ethereum-package/src/cl/cl_node_ready_conditions.star" -) -constants = import_module( +ethereum_package_constants = import_module( "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" ) +ethereum_package_input_parser = import_module( + "github.com/ethpandaops/ethereum-package/src/package_io/input_parser.star" +) + +constants = import_module("../../package_io/constants.star") + util = import_module("../../util.star") # ---------------------------------- Beacon client ------------------------------------- @@ -31,16 +34,16 @@ BEACON_HTTP_PORT_NUM = 8547 def get_used_ports(discovery_port): used_ports = { - BEACON_TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.TCP_PROTOCOL, wait=None + BEACON_TCP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.TCP_PROTOCOL, wait=None ), - BEACON_UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.UDP_PROTOCOL, wait=None + BEACON_UDP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.UDP_PROTOCOL, wait=None ), - BEACON_HTTP_PORT_ID: shared_utils.new_port_spec( + BEACON_HTTP_PORT_ID: ethereum_package_shared_utils.new_port_spec( BEACON_HTTP_PORT_NUM, - shared_utils.TCP_PROTOCOL, - shared_utils.HTTP_APPLICATION_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, ), } return used_ports @@ -49,11 +52,11 @@ def get_used_ports(discovery_port): ENTRYPOINT_ARGS = ["sh", "-c"] VERBOSITY_LEVELS = { - constants.GLOBAL_LOG_LEVEL.error: "ERROR", - constants.GLOBAL_LOG_LEVEL.warn: "WARN", - constants.GLOBAL_LOG_LEVEL.info: "INFO", - constants.GLOBAL_LOG_LEVEL.debug: "DEBUG", - constants.GLOBAL_LOG_LEVEL.trace: "TRACE", + ethereum_package_constants.GLOBAL_LOG_LEVEL.error: "ERROR", + ethereum_package_constants.GLOBAL_LOG_LEVEL.warn: "WARN", + ethereum_package_constants.GLOBAL_LOG_LEVEL.info: "INFO", + ethereum_package_constants.GLOBAL_LOG_LEVEL.debug: "DEBUG", + ethereum_package_constants.GLOBAL_LOG_LEVEL.trace: "TRACE", } @@ -61,7 +64,11 @@ def launch( plan, launcher, service_name, - image, + participant, + global_log_level, + persistent, + tolerations, + node_selectors, el_context, existing_cl_clients, l1_config_env_vars, @@ -79,10 +86,19 @@ def launch( }, ) + log_level = ethereum_package_input_parser.get_client_log_level_or_default( + participant.cl_log_level, global_log_level, VERBOSITY_LEVELS + ) + config = get_beacon_config( plan, launcher, - image, + service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, el_context, existing_cl_clients, l1_config_env_vars, @@ -105,7 +121,7 @@ def launch( beacon_multiaddr = response["extract.multiaddr"] beacon_peer_id = response["extract.peer_id"] - return cl_context.new_cl_context( + return ethereum_package_cl_context.new_cl_context( client_name="op-node", enr=beacon_node_enr, ip_addr=beacon_service.ip_address, @@ -121,7 +137,12 @@ def launch( def get_beacon_config( plan, launcher, - image, + service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, el_context, existing_cl_clients, l1_config_env_vars, @@ -138,10 +159,10 @@ def get_beacon_config( cmd = [ "op-node", "--l2={0}".format(EXECUTION_ENGINE_ENDPOINT), - "--l2.jwt-secret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, + "--l2.jwt-secret=" + ethereum_package_constants.JWT_MOUNT_PATH_ON_CONTAINER, "--verifier.l1-confs=4", "--rollup.config=" - + constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS + + ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS + "/rollup-{0}.json".format(launcher.network_params.network_id), "--rpc.addr=0.0.0.0", "--rpc.port={0}".format(BEACON_HTTP_PORT_NUM), @@ -150,7 +171,8 @@ def get_beacon_config( "--l1.rpckind={0}".format(l1_config_env_vars["L1_RPC_KIND"]), "--l1.beacon={0}".format(l1_config_env_vars["CL_RPC_URL"]), "--l1.trustrpc", - "--p2p.advertise.ip=" + constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "--p2p.advertise.ip=" + + ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, "--p2p.advertise.tcp={0}".format(BEACON_DISCOVERY_PORT_NUM), "--p2p.advertise.udp={0}".format(BEACON_DISCOVERY_PORT_NUM), "--p2p.listen.ip=0.0.0.0", @@ -174,31 +196,68 @@ def get_beacon_config( cmd.append( "--p2p.bootnodes=" + ",".join( - [ctx.enr for ctx in existing_cl_clients[: constants.MAX_ENR_ENTRIES]] + [ + ctx.enr + for ctx in existing_cl_clients[ + : ethereum_package_constants.MAX_ENR_ENTRIES + ] + ] ) ) files = { - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: launcher.deployment_output, - constants.JWT_MOUNTPOINT_ON_CLIENTS: launcher.jwt_file, + ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: launcher.deployment_output, + ethereum_package_constants.JWT_MOUNTPOINT_ON_CLIENTS: launcher.jwt_file, } + + if persistent: + files[BEACON_DATA_DIRPATH_ON_SERVICE_CONTAINER] = Directory( + persistent_key="data-{0}".format(service_name), + size=int(participant.cl_volume_size) + if int(participant.cl_volume_size) > 0 + else constants.VOLUME_SIZE[launcher.network][ + constants.CL_TYPE.hildr + "_volume_size" + ], + ) + ports = {} ports.update(used_ports) - return ServiceConfig( - image=image, - ports=ports, - cmd=cmd, - files=files, - private_ip_address_placeholder=constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - ready_conditions=ReadyCondition( + env_vars = participant.cl_extra_env_vars + config_args = { + "image": participant.cl_image, + "ports": ports, + "cmd": cmd, + "files": files, + "private_ip_address_placeholder": ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "env_vars": env_vars, + "labels": ethereum_package_shared_utils.label_maker( + client=constants.CL_TYPE.op_node, + client_type=constants.CLIENT_TYPES.cl, + image=participant.cl_image, + connected_client=el_context.client_name, + extra_labels=participant.cl_extra_labels, + ), + "ready_conditions": ReadyCondition( recipe=beacon_node_identity_recipe, field="code", assertion="==", target_value=200, timeout="1m", ), - ) + "tolerations": tolerations, + "node_selectors": node_selectors, + } + + if participant.cl_min_cpu > 0: + config_args["min_cpu"] = participant.cl_min_cpu + if participant.cl_max_cpu > 0: + config_args["max_cpu"] = participant.cl_max_cpu + if participant.cl_min_mem > 0: + config_args["min_memory"] = participant.cl_min_mem + if participant.cl_max_mem > 0: + config_args["max_memory"] = participant.cl_max_mem + return ServiceConfig(**config_args) def new_op_node_launcher(deployment_output, jwt_file, network_params): diff --git a/src/el/op-besu/op_besu_launcher.star b/src/el/op-besu/op_besu_launcher.star index 3026b28..bcd201a 100644 --- a/src/el/op-besu/op_besu_launcher.star +++ b/src/el/op-besu/op_besu_launcher.star @@ -1,21 +1,29 @@ -shared_utils = import_module( +ethereum_package_shared_utils = import_module( "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" ) -el_context = import_module( +ethereum_package_el_context = import_module( "github.com/ethpandaops/ethereum-package/src/el/el_context.star" ) -el_admin_node_info = import_module( + +ethereum_package_el_admin_node_info = import_module( "github.com/ethpandaops/ethereum-package/src/el/el_admin_node_info.star" ) -node_metrics = import_module( +ethereum_package_node_metrics = import_module( "github.com/ethpandaops/ethereum-package/src/node_metrics_info.star" ) -constants = import_module( + +ethereum_package_input_parser = import_module( + "github.com/ethpandaops/ethereum-package/src/package_io/input_parser.star" +) + +ethereum_package_constants = import_module( "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" ) +constants = import_module("../../package_io/constants.star") + RPC_PORT_NUM = 8545 WS_PORT_NUM = 8546 DISCOVERY_PORT_NUM = 30303 @@ -46,24 +54,26 @@ EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/data/besu/execution-data" def get_used_ports(discovery_port=DISCOVERY_PORT_NUM): used_ports = { - RPC_PORT_ID: shared_utils.new_port_spec( + RPC_PORT_ID: ethereum_package_shared_utils.new_port_spec( RPC_PORT_NUM, - shared_utils.TCP_PROTOCOL, - shared_utils.HTTP_APPLICATION_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, ), - WS_PORT_ID: shared_utils.new_port_spec(WS_PORT_NUM, shared_utils.TCP_PROTOCOL), - TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.TCP_PROTOCOL + WS_PORT_ID: ethereum_package_shared_utils.new_port_spec( + WS_PORT_NUM, ethereum_package_shared_utils.TCP_PROTOCOL ), - UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.UDP_PROTOCOL + TCP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.TCP_PROTOCOL ), - ENGINE_RPC_PORT_ID: shared_utils.new_port_spec( + UDP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.UDP_PROTOCOL + ), + ENGINE_RPC_PORT_ID: ethereum_package_shared_utils.new_port_spec( ENGINE_RPC_PORT_NUM, - shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, ), - METRICS_PORT_ID: shared_utils.new_port_spec( - METRICS_PORT_NUM, shared_utils.TCP_PROTOCOL + METRICS_PORT_ID: ethereum_package_shared_utils.new_port_spec( + METRICS_PORT_NUM, ethereum_package_shared_utils.TCP_PROTOCOL ), } return used_ports @@ -72,11 +82,11 @@ def get_used_ports(discovery_port=DISCOVERY_PORT_NUM): ENTRYPOINT_ARGS = ["sh", "-c"] VERBOSITY_LEVELS = { - constants.GLOBAL_LOG_LEVEL.error: "1", - constants.GLOBAL_LOG_LEVEL.warn: "2", - constants.GLOBAL_LOG_LEVEL.info: "3", - constants.GLOBAL_LOG_LEVEL.debug: "4", - constants.GLOBAL_LOG_LEVEL.trace: "5", + ethereum_package_constants.GLOBAL_LOG_LEVEL.error: "1", + ethereum_package_constants.GLOBAL_LOG_LEVEL.warn: "2", + ethereum_package_constants.GLOBAL_LOG_LEVEL.info: "3", + ethereum_package_constants.GLOBAL_LOG_LEVEL.debug: "4", + ethereum_package_constants.GLOBAL_LOG_LEVEL.trace: "5", } BUILDER_IMAGE_STR = "builder" @@ -87,38 +97,50 @@ def launch( plan, launcher, service_name, - image, + participant, + global_log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, sequencer_enabled, sequencer_context, ): - network_name = shared_utils.get_network_name(launcher.network) + log_level = ethereum_package_input_parser.get_client_log_level_or_default( + participant.el_log_level, global_log_level, VERBOSITY_LEVELS + ) + + cl_client_name = service_name.split("-")[4] config = get_config( plan, - launcher.deployment_output, - launcher.jwt_file, - launcher.network, - launcher.network_id, - image, + launcher, service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, + cl_client_name, sequencer_enabled, sequencer_context, ) service = plan.add_service(service_name, config) - enode = el_admin_node_info.get_enode_for_node(plan, service_name, RPC_PORT_ID) + enode = ethereum_package_el_admin_node_info.get_enode_for_node( + plan, service_name, RPC_PORT_ID + ) metrics_url = "{0}:{1}".format(service.ip_address, METRICS_PORT_NUM) - besu_metrics_info = node_metrics.new_node_metrics_info( + besu_metrics_info = ethereum_package_node_metrics.new_node_metrics_info( service_name, METRICS_PATH, metrics_url ) http_url = "http://{0}:{1}".format(service.ip_address, RPC_PORT_NUM) - return el_context.new_el_context( + return ethereum_package_el_context.new_el_context( client_name="op-besu", enode=enode, ip_addr=service.ip_address, @@ -133,13 +155,15 @@ def launch( def get_config( plan, - deployment_output, - jwt_file, - network, - network_id, - image, + launcher, service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, + cl_client_name, sequencer_enabled, sequencer_context, ): @@ -149,9 +173,9 @@ def get_config( cmd = [ "besu", "--genesis-file=" - + constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER - + "/genesis-{0}.json".format(network_id), - "--network-id={0}".format(network_id), + + ethereum_package_constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER + + "/genesis-{0}.json".format(launcher.network_id), + "--network-id={0}".format(launcher.network_id), # "--logging=" + log_level, "--data-path=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, "--host-allowlist=*", @@ -166,10 +190,10 @@ def get_config( "--rpc-ws-port={0}".format(WS_PORT_NUM), "--rpc-ws-api=ADMIN,CLIQUE,ETH,NET,DEBUG,TXPOOL,ENGINE,TRACE,WEB3", "--p2p-enabled=true", - "--p2p-host=" + constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "--p2p-host=" + ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, "--p2p-port={0}".format(discovery_port), "--engine-rpc-enabled=true", - "--engine-jwt-secret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, + "--engine-jwt-secret=" + ethereum_package_constants.JWT_MOUNT_PATH_ON_CONTAINER, "--engine-host-allowlist=*", "--engine-rpc-port={0}".format(ENGINE_RPC_PORT_NUM), "--sync-mode=FULL", @@ -191,7 +215,9 @@ def get_config( + ",".join( [ ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + for ctx in existing_el_clients[ + : ethereum_package_constants.MAX_ENODE_ENTRIES + ] ] ) ) @@ -199,19 +225,48 @@ def get_config( cmd_str = " ".join(cmd) files = { - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: deployment_output, - constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, + ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: launcher.deployment_output, + ethereum_package_constants.JWT_MOUNTPOINT_ON_CLIENTS: launcher.jwt_file, + } + if persistent: + files[EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER] = Directory( + persistent_key="data-{0}".format(service_name), + size=int(participant.el_volume_size) + if int(participant.el_volume_size) > 0 + else constants.VOLUME_SIZE[launcher.network][ + constants.EL_TYPE.op_besu + "_volume_size" + ], + ) + env_vars = participant.el_extra_env_vars + config_args = { + "image": participant.el_image, + "ports": used_ports, + "cmd": [cmd_str], + "files": files, + "entrypoint": ENTRYPOINT_ARGS, + "private_ip_address_placeholder": ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "env_vars": env_vars, + "labels": ethereum_package_shared_utils.label_maker( + client=constants.EL_TYPE.op_besu, + client_type=constants.CLIENT_TYPES.el, + image=participant.el_image, + connected_client=cl_client_name, + extra_labels=participant.el_extra_labels, + ), + "tolerations": tolerations, + "node_selectors": node_selectors, + "user": User(uid=0, gid=0), } - return ServiceConfig( - image=image, - ports=used_ports, - cmd=[cmd_str], - files=files, - entrypoint=ENTRYPOINT_ARGS, - private_ip_address_placeholder=constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - user=User(uid=0, gid=0), - ) + if participant.el_min_cpu > 0: + config_args["min_cpu"] = participant.el_min_cpu + if participant.el_max_cpu > 0: + config_args["max_cpu"] = participant.el_max_cpu + if participant.el_min_mem > 0: + config_args["min_memory"] = participant.el_min_mem + if participant.el_max_mem > 0: + config_args["max_memory"] = participant.el_max_mem + return ServiceConfig(**config_args) def new_op_besu_launcher( diff --git a/src/el/op-erigon/op_erigon_launcher.star b/src/el/op-erigon/op_erigon_launcher.star index ee40fdf..9837564 100644 --- a/src/el/op-erigon/op_erigon_launcher.star +++ b/src/el/op-erigon/op_erigon_launcher.star @@ -1,21 +1,27 @@ -shared_utils = import_module( +ethereum_package_shared_utils = import_module( "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" ) -# input_parser = import_module("../../package_io/input_parser.star") -el_context = import_module( + +ethereum_package_el_context = import_module( "github.com/ethpandaops/ethereum-package/src/el/el_context.star" ) -el_admin_node_info = import_module( +ethereum_package_el_admin_node_info = import_module( "github.com/ethpandaops/ethereum-package/src/el/el_admin_node_info.star" ) -node_metrics = import_module( +ethereum_package_node_metrics = import_module( "github.com/ethpandaops/ethereum-package/src/node_metrics_info.star" ) -constants = import_module( +ethereum_package_input_parser = import_module( + "github.com/ethpandaops/ethereum-package/src/package_io/input_parser.star" +) + +ethereum_package_constants = import_module( "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" ) +constants = import_module("../../package_io/constants.star") + RPC_PORT_NUM = 8545 WS_PORT_NUM = 8546 DISCOVERY_PORT_NUM = 30303 @@ -43,24 +49,26 @@ EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/data/op-erigon/execution-data" def get_used_ports(discovery_port=DISCOVERY_PORT_NUM): used_ports = { - RPC_PORT_ID: shared_utils.new_port_spec( + RPC_PORT_ID: ethereum_package_shared_utils.new_port_spec( RPC_PORT_NUM, - shared_utils.TCP_PROTOCOL, - shared_utils.HTTP_APPLICATION_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, ), - WS_PORT_ID: shared_utils.new_port_spec(WS_PORT_NUM, shared_utils.TCP_PROTOCOL), - TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.TCP_PROTOCOL + WS_PORT_ID: ethereum_package_shared_utils.new_port_spec( + WS_PORT_NUM, ethereum_package_shared_utils.TCP_PROTOCOL ), - UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.UDP_PROTOCOL + TCP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.TCP_PROTOCOL ), - ENGINE_RPC_PORT_ID: shared_utils.new_port_spec( + UDP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.UDP_PROTOCOL + ), + ENGINE_RPC_PORT_ID: ethereum_package_shared_utils.new_port_spec( ENGINE_RPC_PORT_NUM, - shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, ), - METRICS_PORT_ID: shared_utils.new_port_spec( - METRICS_PORT_NUM, shared_utils.TCP_PROTOCOL + METRICS_PORT_ID: ethereum_package_shared_utils.new_port_spec( + METRICS_PORT_NUM, ethereum_package_shared_utils.TCP_PROTOCOL ), } return used_ports @@ -69,11 +77,11 @@ def get_used_ports(discovery_port=DISCOVERY_PORT_NUM): ENTRYPOINT_ARGS = ["sh", "-c"] VERBOSITY_LEVELS = { - constants.GLOBAL_LOG_LEVEL.error: "1", - constants.GLOBAL_LOG_LEVEL.warn: "2", - constants.GLOBAL_LOG_LEVEL.info: "3", - constants.GLOBAL_LOG_LEVEL.debug: "4", - constants.GLOBAL_LOG_LEVEL.trace: "5", + ethereum_package_constants.GLOBAL_LOG_LEVEL.error: "1", + ethereum_package_constants.GLOBAL_LOG_LEVEL.warn: "2", + ethereum_package_constants.GLOBAL_LOG_LEVEL.info: "3", + ethereum_package_constants.GLOBAL_LOG_LEVEL.debug: "4", + ethereum_package_constants.GLOBAL_LOG_LEVEL.trace: "5", } @@ -81,40 +89,50 @@ def launch( plan, launcher, service_name, - image, + participant, + global_log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, sequencer_enabled, sequencer_context, ): - network_name = shared_utils.get_network_name(launcher.network) + log_level = ethereum_package_input_parser.get_client_log_level_or_default( + participant.el_log_level, global_log_level, VERBOSITY_LEVELS + ) + + cl_client_name = service_name.split("-")[4] config = get_config( plan, - launcher.deployment_output, - launcher.jwt_file, - launcher.network, - launcher.network_id, - image, + launcher, service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, + cl_client_name, sequencer_enabled, sequencer_context, ) service = plan.add_service(service_name, config) - enode, enr = el_admin_node_info.get_enode_enr_for_node( + enode, enr = ethereum_package_el_admin_node_info.get_enode_enr_for_node( plan, service_name, RPC_PORT_ID ) metrics_url = "{0}:{1}".format(service.ip_address, METRICS_PORT_NUM) - erigon_metrics_info = node_metrics.new_node_metrics_info( + erigon_metrics_info = ethereum_package_node_metrics.new_node_metrics_info( service_name, METRICS_PATH, metrics_url ) http_url = "http://{0}:{1}".format(service.ip_address, RPC_PORT_NUM) - return el_context.new_el_context( + return ethereum_package_el_context.new_el_context( client_name="op-erigon", enode=enode, ip_addr=service.ip_address, @@ -130,20 +148,22 @@ def launch( def get_config( plan, - deployment_output, - jwt_file, - network, - network_id, - image, + launcher, service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, + cl_client_name, sequencer_enabled, sequencer_context, ): init_datadir_cmd_str = "erigon init --datadir={0} {1}".format( EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, - constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER - + "/genesis-{0}.json".format(network_id), + ethereum_package_constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER + + "/genesis-{0}.json".format(launcher.network_id), ) discovery_port = DISCOVERY_PORT_NUM @@ -152,7 +172,7 @@ def get_config( cmd = [ "erigon", "--datadir=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, - "--networkid={0}".format(network_id), + "--networkid={0}".format(launcher.network_id), "--http", "--http.addr=0.0.0.0", "--http.vhosts=*", @@ -164,8 +184,8 @@ def get_config( "--authrpc.port={0}".format(ENGINE_RPC_PORT_NUM), "--authrpc.addr=0.0.0.0", "--authrpc.vhosts=*", - "--authrpc.jwtsecret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, - "--nat=extip:" + constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "--authrpc.jwtsecret=" + ethereum_package_constants.JWT_MOUNT_PATH_ON_CONTAINER, + "--nat=extip:" + ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, "--rpc.allow-unprotected-txs", "--metrics", "--metrics.addr=0.0.0.0", @@ -184,13 +204,15 @@ def get_config( + ",".join( [ ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + for ctx in existing_el_clients[ + : ethereum_package_constants.MAX_ENODE_ENTRIES + ] ] ) ) cmd_str = " ".join(cmd) - if network not in constants.PUBLIC_NETWORKS: + if launcher.network not in ethereum_package_constants.PUBLIC_NETWORKS: subcommand_strs = [ init_datadir_cmd_str, cmd_str, @@ -200,19 +222,48 @@ def get_config( command_str = cmd_str files = { - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: deployment_output, - constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, + ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: launcher.deployment_output, + ethereum_package_constants.JWT_MOUNTPOINT_ON_CLIENTS: launcher.jwt_file, + } + if persistent: + files[EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER] = Directory( + persistent_key="data-{0}".format(service_name), + size=int(participant.el_volume_size) + if int(participant.el_volume_size) > 0 + else constants.VOLUME_SIZE[launcher.network][ + constants.EL_TYPE.op_erigon + "_volume_size" + ], + ) + env_vars = participant.el_extra_env_vars + config_args = { + "image": participant.el_image, + "ports": used_ports, + "cmd": [command_str], + "files": files, + "entrypoint": ENTRYPOINT_ARGS, + "private_ip_address_placeholder": ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "env_vars": env_vars, + "labels": ethereum_package_shared_utils.label_maker( + client=constants.EL_TYPE.op_erigon, + client_type=constants.CLIENT_TYPES.el, + image=participant.el_image, + connected_client=cl_client_name, + extra_labels=participant.el_extra_labels, + ), + "tolerations": tolerations, + "node_selectors": node_selectors, + "user": User(uid=0, gid=0), } - return ServiceConfig( - image=image, - ports=used_ports, - cmd=[command_str], - files=files, - entrypoint=ENTRYPOINT_ARGS, - private_ip_address_placeholder=constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - user=User(uid=0, gid=0), - ) + if participant.el_min_cpu > 0: + config_args["min_cpu"] = participant.el_min_cpu + if participant.el_max_cpu > 0: + config_args["max_cpu"] = participant.el_max_cpu + if participant.el_min_mem > 0: + config_args["min_memory"] = participant.el_min_mem + if participant.el_max_mem > 0: + config_args["max_memory"] = participant.el_max_mem + return ServiceConfig(**config_args) def new_op_erigon_launcher( diff --git a/src/el/op-geth/op_geth_launcher.star b/src/el/op-geth/op_geth_launcher.star index 6f31e00..9341bc7 100644 --- a/src/el/op-geth/op_geth_launcher.star +++ b/src/el/op-geth/op_geth_launcher.star @@ -1,21 +1,28 @@ -shared_utils = import_module( +ethereum_package_shared_utils = import_module( "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" ) -el_context = import_module( +ethereum_package_el_context = import_module( "github.com/ethpandaops/ethereum-package/src/el/el_context.star" ) -el_admin_node_info = import_module( +ethereum_package_el_admin_node_info = import_module( "github.com/ethpandaops/ethereum-package/src/el/el_admin_node_info.star" ) -node_metrics = import_module( +ethereum_package_node_metrics = import_module( "github.com/ethpandaops/ethereum-package/src/node_metrics_info.star" ) -constants = import_module( + +ethereum_package_input_parser = import_module( + "github.com/ethpandaops/ethereum-package/src/package_io/input_parser.star" +) + +ethereum_package_constants = import_module( "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" ) +constants = import_module("../../package_io/constants.star") + RPC_PORT_NUM = 8545 WS_PORT_NUM = 8546 DISCOVERY_PORT_NUM = 30303 @@ -46,24 +53,26 @@ EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/data/geth/execution-data" def get_used_ports(discovery_port=DISCOVERY_PORT_NUM): used_ports = { - RPC_PORT_ID: shared_utils.new_port_spec( + RPC_PORT_ID: ethereum_package_shared_utils.new_port_spec( RPC_PORT_NUM, - shared_utils.TCP_PROTOCOL, - shared_utils.HTTP_APPLICATION_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, + ), + WS_PORT_ID: ethereum_package_shared_utils.new_port_spec( + WS_PORT_NUM, ethereum_package_shared_utils.TCP_PROTOCOL ), - WS_PORT_ID: shared_utils.new_port_spec(WS_PORT_NUM, shared_utils.TCP_PROTOCOL), - TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.TCP_PROTOCOL + TCP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.TCP_PROTOCOL ), - UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.UDP_PROTOCOL + UDP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.UDP_PROTOCOL ), - ENGINE_RPC_PORT_ID: shared_utils.new_port_spec( + ENGINE_RPC_PORT_ID: ethereum_package_shared_utils.new_port_spec( ENGINE_RPC_PORT_NUM, - shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, ), - METRICS_PORT_ID: shared_utils.new_port_spec( - METRICS_PORT_NUM, shared_utils.TCP_PROTOCOL + METRICS_PORT_ID: ethereum_package_shared_utils.new_port_spec( + METRICS_PORT_NUM, ethereum_package_shared_utils.TCP_PROTOCOL ), } return used_ports @@ -72,11 +81,11 @@ def get_used_ports(discovery_port=DISCOVERY_PORT_NUM): ENTRYPOINT_ARGS = ["sh", "-c"] VERBOSITY_LEVELS = { - constants.GLOBAL_LOG_LEVEL.error: "1", - constants.GLOBAL_LOG_LEVEL.warn: "2", - constants.GLOBAL_LOG_LEVEL.info: "3", - constants.GLOBAL_LOG_LEVEL.debug: "4", - constants.GLOBAL_LOG_LEVEL.trace: "5", + ethereum_package_constants.GLOBAL_LOG_LEVEL.error: "1", + ethereum_package_constants.GLOBAL_LOG_LEVEL.warn: "2", + ethereum_package_constants.GLOBAL_LOG_LEVEL.info: "3", + ethereum_package_constants.GLOBAL_LOG_LEVEL.debug: "4", + ethereum_package_constants.GLOBAL_LOG_LEVEL.trace: "5", } BUILDER_IMAGE_STR = "builder" @@ -87,37 +96,50 @@ def launch( plan, launcher, service_name, - image, + participant, + global_log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, sequencer_enabled, sequencer_context, ): + log_level = ethereum_package_input_parser.get_client_log_level_or_default( + participant.el_log_level, global_log_level, VERBOSITY_LEVELS + ) + + cl_client_name = service_name.split("-")[4] + config = get_config( plan, - launcher.deployment_output, - launcher.jwt_file, - launcher.network, - launcher.network_id, - image, + launcher, + service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, + cl_client_name, sequencer_enabled, sequencer_context, ) service = plan.add_service(service_name, config) - enode, enr = el_admin_node_info.get_enode_enr_for_node( + enode, enr = ethereum_package_el_admin_node_info.get_enode_enr_for_node( plan, service_name, RPC_PORT_ID ) metrics_url = "{0}:{1}".format(service.ip_address, METRICS_PORT_NUM) - geth_metrics_info = node_metrics.new_node_metrics_info( + geth_metrics_info = ethereum_package_node_metrics.new_node_metrics_info( service_name, METRICS_PATH, metrics_url ) http_url = "http://{0}:{1}".format(service.ip_address, RPC_PORT_NUM) - return el_context.new_el_context( + return ethereum_package_el_context.new_el_context( client_name="op-geth", enode=enode, ip_addr=service.ip_address, @@ -133,19 +155,22 @@ def launch( def get_config( plan, - deployment_output, - jwt_file, - network, - network_id, - image, + launcher, + service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, + cl_client_name, sequencer_enabled, sequencer_context, ): init_datadir_cmd_str = "geth init --datadir={0} --state.scheme=hash {1}".format( EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS - + "/genesis-{0}.json".format(network_id), + ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS + + "/genesis-{0}.json".format(launcher.network_id), ) discovery_port = DISCOVERY_PORT_NUM @@ -153,7 +178,7 @@ def get_config( cmd = [ "geth", - "--networkid={0}".format(network_id), + "--networkid={0}".format(launcher.network_id), # "--verbosity=" + verbosity_level, "--datadir=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, "--gcmode=archive", @@ -172,9 +197,9 @@ def get_config( "--authrpc.port={0}".format(ENGINE_RPC_PORT_NUM), "--authrpc.addr=0.0.0.0", "--authrpc.vhosts=*", - "--authrpc.jwtsecret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, + "--authrpc.jwtsecret=" + ethereum_package_constants.JWT_MOUNT_PATH_ON_CONTAINER, "--syncmode=full", - "--nat=extip:" + constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "--nat=extip:" + ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, "--rpc.allow-unprotected-txs", "--metrics", "--metrics.addr=0.0.0.0", @@ -194,13 +219,15 @@ def get_config( + ",".join( [ ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + for ctx in existing_el_clients[ + : ethereum_package_constants.MAX_ENODE_ENTRIES + ] ] ) ) cmd_str = " ".join(cmd) - if network not in constants.PUBLIC_NETWORKS: + if launcher.network not in ethereum_package_constants.PUBLIC_NETWORKS: subcommand_strs = [ init_datadir_cmd_str, cmd_str, @@ -210,18 +237,47 @@ def get_config( command_str = cmd_str files = { - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: deployment_output, - constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, + ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: launcher.deployment_output, + ethereum_package_constants.JWT_MOUNTPOINT_ON_CLIENTS: launcher.jwt_file, + } + if persistent: + files[EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER] = Directory( + persistent_key="data-{0}".format(service_name), + size=int(participant.el_volume_size) + if int(participant.el_volume_size) > 0 + else constants.VOLUME_SIZE[launcher.network][ + constants.EL_TYPE.op_geth + "_volume_size" + ], + ) + env_vars = participant.el_extra_env_vars + config_args = { + "image": participant.el_image, + "ports": used_ports, + "cmd": [command_str], + "files": files, + "entrypoint": ENTRYPOINT_ARGS, + "private_ip_address_placeholder": ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "env_vars": env_vars, + "labels": ethereum_package_shared_utils.label_maker( + client=constants.EL_TYPE.op_geth, + client_type=constants.CLIENT_TYPES.el, + image=participant.el_image, + connected_client=cl_client_name, + extra_labels=participant.el_extra_labels, + ), + "tolerations": tolerations, + "node_selectors": node_selectors, } - return ServiceConfig( - image=image, - ports=used_ports, - cmd=[command_str], - files=files, - entrypoint=ENTRYPOINT_ARGS, - private_ip_address_placeholder=constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - ) + if participant.el_min_cpu > 0: + config_args["min_cpu"] = participant.el_min_cpu + if participant.el_max_cpu > 0: + config_args["max_cpu"] = participant.el_max_cpu + if participant.el_min_mem > 0: + config_args["min_memory"] = participant.el_min_mem + if participant.el_max_mem > 0: + config_args["max_memory"] = participant.el_max_mem + return ServiceConfig(**config_args) def new_op_geth_launcher( diff --git a/src/el/op-nethermind/op_nethermind_launcher.star b/src/el/op-nethermind/op_nethermind_launcher.star index 5c12777..a063ca6 100644 --- a/src/el/op-nethermind/op_nethermind_launcher.star +++ b/src/el/op-nethermind/op_nethermind_launcher.star @@ -1,21 +1,28 @@ -shared_utils = import_module( +ethereum_package_shared_utils = import_module( "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" ) -el_context = import_module( +ethereum_package_el_context = import_module( "github.com/ethpandaops/ethereum-package/src/el/el_context.star" ) -el_admin_node_info = import_module( +ethereum_package_el_admin_node_info = import_module( "github.com/ethpandaops/ethereum-package/src/el/el_admin_node_info.star" ) -node_metrics = import_module( +ethereum_package_el_node_metrics = import_module( "github.com/ethpandaops/ethereum-package/src/node_metrics_info.star" ) -constants = import_module( + +ethereum_package_input_parser = import_module( + "github.com/ethpandaops/ethereum-package/src/package_io/input_parser.star" +) + +ethereum_package_constants = import_module( "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" ) +constants = import_module("../../package_io/constants.star") + RPC_PORT_NUM = 8545 WS_PORT_NUM = 8546 DISCOVERY_PORT_NUM = 30303 @@ -46,35 +53,37 @@ EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/data/nethermind/execution-data" def get_used_ports(discovery_port=DISCOVERY_PORT_NUM): used_ports = { - RPC_PORT_ID: shared_utils.new_port_spec( + RPC_PORT_ID: ethereum_package_shared_utils.new_port_spec( RPC_PORT_NUM, - shared_utils.TCP_PROTOCOL, - shared_utils.HTTP_APPLICATION_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, ), - WS_PORT_ID: shared_utils.new_port_spec(WS_PORT_NUM, shared_utils.TCP_PROTOCOL), - TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.TCP_PROTOCOL + WS_PORT_ID: ethereum_package_shared_utils.new_port_spec( + WS_PORT_NUM, ethereum_package_shared_utils.TCP_PROTOCOL ), - UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.UDP_PROTOCOL + TCP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.TCP_PROTOCOL ), - ENGINE_RPC_PORT_ID: shared_utils.new_port_spec( + UDP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.UDP_PROTOCOL + ), + ENGINE_RPC_PORT_ID: ethereum_package_shared_utils.new_port_spec( ENGINE_RPC_PORT_NUM, - shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, ), - METRICS_PORT_ID: shared_utils.new_port_spec( - METRICS_PORT_NUM, shared_utils.TCP_PROTOCOL + METRICS_PORT_ID: ethereum_package_shared_utils.new_port_spec( + METRICS_PORT_NUM, ethereum_package_shared_utils.TCP_PROTOCOL ), } return used_ports VERBOSITY_LEVELS = { - constants.GLOBAL_LOG_LEVEL.error: "1", - constants.GLOBAL_LOG_LEVEL.warn: "2", - constants.GLOBAL_LOG_LEVEL.info: "3", - constants.GLOBAL_LOG_LEVEL.debug: "4", - constants.GLOBAL_LOG_LEVEL.trace: "5", + ethereum_package_constants.GLOBAL_LOG_LEVEL.error: "1", + ethereum_package_constants.GLOBAL_LOG_LEVEL.warn: "2", + ethereum_package_constants.GLOBAL_LOG_LEVEL.info: "3", + ethereum_package_constants.GLOBAL_LOG_LEVEL.debug: "4", + ethereum_package_constants.GLOBAL_LOG_LEVEL.trace: "5", } @@ -82,39 +91,51 @@ def launch( plan, launcher, service_name, - image, + participant, + global_log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, sequencer_enabled, sequencer_context, ): - network_name = shared_utils.get_network_name(launcher.network) + log_level = ethereum_package_input_parser.get_client_log_level_or_default( + participant.el_log_level, global_log_level, VERBOSITY_LEVELS + ) + + cl_client_name = service_name.split("-")[4] config = get_config( plan, - launcher.el_cl_genesis_data, - launcher.jwt_file, - launcher.network, - launcher.network_id, - image, + launcher, service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, + cl_client_name, sequencer_enabled, sequencer_context, ) service = plan.add_service(service_name, config) - enode = el_admin_node_info.get_enode_for_node(plan, service_name, RPC_PORT_ID) + enode = ethereum_package_el_admin_node_info.get_enode_for_node( + plan, service_name, RPC_PORT_ID + ) metrics_url = "{0}:{1}".format(service.ip_address, METRICS_PORT_NUM) - nethermind_metrics_info = node_metrics.new_node_metrics_info( + nethermind_metrics_info = ethereum_package_el_node_metrics.new_node_metrics_info( service_name, METRICS_PATH, metrics_url ) http_url = "http://{0}:{1}".format(service.ip_address, RPC_PORT_NUM) ws_url = "ws://{0}:{1}".format(service.ip_address, WS_PORT_NUM) - return el_context.new_el_context( + return ethereum_package_el_context.new_el_context( client_name="op-nethermind", enode=enode, ip_addr=service.ip_address, @@ -130,13 +151,15 @@ def launch( def get_config( plan, - el_cl_genesis_data, - jwt_file, - network, - network_id, - image, + launcher, service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, + cl_client_name, sequencer_enabled, sequencer_context, ): @@ -153,10 +176,12 @@ def get_config( "--JsonRpc.WebSocketsPort={0}".format(WS_PORT_NUM), "--JsonRpc.EngineHost=0.0.0.0", "--JsonRpc.EnginePort={0}".format(ENGINE_RPC_PORT_NUM), - "--Network.ExternalIp=" + constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "--Network.ExternalIp=" + + ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, "--Network.DiscoveryPort={0}".format(discovery_port), "--Network.P2PPort={0}".format(discovery_port), - "--JsonRpc.JwtSecretFile=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, + "--JsonRpc.JwtSecretFile=" + + ethereum_package_constants.JWT_MOUNT_PATH_ON_CONTAINER, "--Metrics.Enabled=true", "--Metrics.ExposePort={0}".format(METRICS_PORT_NUM), "--Metrics.ExposeHost=0.0.0.0", @@ -172,7 +197,9 @@ def get_config( + ",".join( [ ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + for ctx in existing_el_clients[ + : ethereum_package_constants.MAX_ENODE_ENTRIES + ] ] ) ) @@ -181,32 +208,61 @@ def get_config( cmd.append("--config=none.cfg") cmd.append( "--Init.ChainSpecPath=" - + constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER - + "/chainspec-{0}.json".format(network_id) + + ethereum_package_constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER + + "/chainspec-{0}.json".format(launcher.network_id) ) files = { - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data, - constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, + ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: launcher.deployment_output, + ethereum_package_constants.JWT_MOUNTPOINT_ON_CLIENTS: launcher.jwt_file, + } + if persistent: + files[EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER] = Directory( + persistent_key="data-{0}".format(service_name), + size=int(participant.el_volume_size) + if int(participant.el_volume_size) > 0 + else constants.VOLUME_SIZE[launcher.network][ + constants.EL_TYPE.op_nethermind + "_volume_size" + ], + ) + env_vars = participant.el_extra_env_vars + config_args = { + "image": participant.el_image, + "ports": used_ports, + "cmd": cmd, + "files": files, + "private_ip_address_placeholder": ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "env_vars": env_vars, + "labels": ethereum_package_shared_utils.label_maker( + client=constants.EL_TYPE.op_nethermind, + client_type=constants.CLIENT_TYPES.el, + image=participant.el_image, + connected_client=cl_client_name, + extra_labels=participant.el_extra_labels, + ), + "tolerations": tolerations, + "node_selectors": node_selectors, } - return ServiceConfig( - image=image, - ports=used_ports, - cmd=cmd, - files=files, - private_ip_address_placeholder=constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - ) + if participant.el_min_cpu > 0: + config_args["min_cpu"] = participant.el_min_cpu + if participant.el_max_cpu > 0: + config_args["max_cpu"] = participant.el_max_cpu + if participant.el_min_mem > 0: + config_args["min_memory"] = participant.el_min_mem + if participant.el_max_mem > 0: + config_args["max_memory"] = participant.el_max_mem + return ServiceConfig(**config_args) def new_nethermind_launcher( - el_cl_genesis_data, + deployment_output, jwt_file, network, network_id, ): return struct( - el_cl_genesis_data=el_cl_genesis_data, + deployment_output=deployment_output, jwt_file=jwt_file, network=network, network_id=network_id, diff --git a/src/el/op-reth/op_reth_launcher.star b/src/el/op-reth/op_reth_launcher.star index 08af39e..548c9dc 100644 --- a/src/el/op-reth/op_reth_launcher.star +++ b/src/el/op-reth/op_reth_launcher.star @@ -1,21 +1,27 @@ -shared_utils = import_module( +ethereum_package_shared_utils = import_module( "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" ) -el_context = import_module( +ethereum_package_el_context = import_module( "github.com/ethpandaops/ethereum-package/src/el/el_context.star" ) -el_admin_node_info = import_module( +ethereum_package_el_admin_node_info = import_module( "github.com/ethpandaops/ethereum-package/src/el/el_admin_node_info.star" ) -node_metrics = import_module( +ethereum_package_node_metrics = import_module( "github.com/ethpandaops/ethereum-package/src/node_metrics_info.star" ) -constants = import_module( +ethereum_package_constants = import_module( "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" ) +ethereum_package_input_parser = import_module( + "github.com/ethpandaops/ethereum-package/src/package_io/input_parser.star" +) + +constants = import_module("../../package_io/constants.star") + RPC_PORT_NUM = 8545 WS_PORT_NUM = 8546 DISCOVERY_PORT_NUM = 30303 @@ -43,34 +49,36 @@ EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/data/op-reth/execution-data" def get_used_ports(discovery_port=DISCOVERY_PORT_NUM): used_ports = { - RPC_PORT_ID: shared_utils.new_port_spec( + RPC_PORT_ID: ethereum_package_shared_utils.new_port_spec( RPC_PORT_NUM, - shared_utils.TCP_PROTOCOL, - shared_utils.HTTP_APPLICATION_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, + ), + WS_PORT_ID: ethereum_package_shared_utils.new_port_spec( + WS_PORT_NUM, ethereum_package_shared_utils.TCP_PROTOCOL ), - WS_PORT_ID: shared_utils.new_port_spec(WS_PORT_NUM, shared_utils.TCP_PROTOCOL), - TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.TCP_PROTOCOL + TCP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.TCP_PROTOCOL ), - UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec( - discovery_port, shared_utils.UDP_PROTOCOL + UDP_DISCOVERY_PORT_ID: ethereum_package_shared_utils.new_port_spec( + discovery_port, ethereum_package_shared_utils.UDP_PROTOCOL ), - ENGINE_RPC_PORT_ID: shared_utils.new_port_spec( - ENGINE_RPC_PORT_NUM, shared_utils.TCP_PROTOCOL + ENGINE_RPC_PORT_ID: ethereum_package_shared_utils.new_port_spec( + ENGINE_RPC_PORT_NUM, ethereum_package_shared_utils.TCP_PROTOCOL ), - METRICS_PORT_ID: shared_utils.new_port_spec( - METRICS_PORT_NUM, shared_utils.TCP_PROTOCOL + METRICS_PORT_ID: ethereum_package_shared_utils.new_port_spec( + METRICS_PORT_NUM, ethereum_package_shared_utils.TCP_PROTOCOL ), } return used_ports VERBOSITY_LEVELS = { - constants.GLOBAL_LOG_LEVEL.error: "v", - constants.GLOBAL_LOG_LEVEL.warn: "vv", - constants.GLOBAL_LOG_LEVEL.info: "vvv", - constants.GLOBAL_LOG_LEVEL.debug: "vvvv", - constants.GLOBAL_LOG_LEVEL.trace: "vvvvv", + ethereum_package_constants.GLOBAL_LOG_LEVEL.error: "v", + ethereum_package_constants.GLOBAL_LOG_LEVEL.warn: "vv", + ethereum_package_constants.GLOBAL_LOG_LEVEL.info: "vvv", + ethereum_package_constants.GLOBAL_LOG_LEVEL.debug: "vvvv", + ethereum_package_constants.GLOBAL_LOG_LEVEL.trace: "vvvvv", } @@ -78,32 +86,50 @@ def launch( plan, launcher, service_name, - image, + participant, + global_log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, sequencer_enabled, sequencer_context, ): + log_level = ethereum_package_input_parser.get_client_log_level_or_default( + participant.el_log_level, global_log_level, VERBOSITY_LEVELS + ) + + cl_client_name = service_name.split("-")[4] + config = get_config( plan, launcher, - image, + service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, + cl_client_name, sequencer_enabled, sequencer_context, ) service = plan.add_service(service_name, config) - enode = el_admin_node_info.get_enode_for_node(plan, service_name, RPC_PORT_ID) + enode = ethereum_package_el_admin_node_info.get_enode_for_node( + plan, service_name, RPC_PORT_ID + ) metric_url = "{0}:{1}".format(service.ip_address, METRICS_PORT_NUM) - op_reth_metrics_info = node_metrics.new_node_metrics_info( + op_reth_metrics_info = ethereum_package_node_metrics.new_node_metrics_info( service_name, METRICS_PATH, metric_url ) http_url = "http://{0}:{1}".format(service.ip_address, RPC_PORT_NUM) - return el_context.new_el_context( + return ethereum_package_el_context.new_el_context( client_name="reth", enode=enode, ip_addr=service.ip_address, @@ -119,14 +145,17 @@ def launch( def get_config( plan, launcher, - image, + service_name, + participant, + log_level, + persistent, + tolerations, + node_selectors, existing_el_clients, + cl_client_name, sequencer_enabled, sequencer_context, ): - deployment_output = launcher.deployment_output - jwt_file = launcher.jwt_file - network = launcher.network public_ports = {} discovery_port = DISCOVERY_PORT_NUM used_ports = get_used_ports(discovery_port) @@ -135,9 +164,9 @@ def get_config( "node", "--datadir=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, "--chain={0}".format( - network - if network in constants.PUBLIC_NETWORKS - else constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER + launcher.network + if launcher.network in ethereum_package_constants.PUBLIC_NETWORKS + else ethereum_package_constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER + "/genesis-{0}.json".format(launcher.network_id) ), "--http", @@ -152,9 +181,9 @@ def get_config( "--ws.port={0}".format(WS_PORT_NUM), "--ws.api=net,eth", "--ws.origins=*", - "--nat=extip:" + constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "--nat=extip:" + ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, "--authrpc.port={0}".format(ENGINE_RPC_PORT_NUM), - "--authrpc.jwtsecret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, + "--authrpc.jwtsecret=" + ethereum_package_constants.JWT_MOUNT_PATH_ON_CONTAINER, "--authrpc.addr=0.0.0.0", "--metrics=0.0.0.0:{0}".format(METRICS_PORT_NUM), "--discovery.port={0}".format(discovery_port), @@ -173,24 +202,55 @@ def get_config( + ",".join( [ ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + for ctx in existing_el_clients[ + : ethereum_package_constants.MAX_ENODE_ENTRIES + ] ] ) ) files = { - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: deployment_output, - constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, + ethereum_package_constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: launcher.deployment_output, + ethereum_package_constants.JWT_MOUNTPOINT_ON_CLIENTS: launcher.jwt_file, } + if persistent: + files[EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER] = Directory( + persistent_key="data-{0}".format(service_name), + size=int(participant.el_volume_size) + if int(participant.el_volume_size) > 0 + else constants.VOLUME_SIZE[launcher.network][ + constants.EL_TYPE.op_reth + "_volume_size" + ], + ) - return ServiceConfig( - image=image, - ports=used_ports, - public_ports=public_ports, - cmd=cmd, - files=files, - private_ip_address_placeholder=constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - ) + env_vars = participant.el_extra_env_vars + config_args = { + "image": participant.el_image, + "ports": used_ports, + "cmd": cmd, + "files": files, + "private_ip_address_placeholder": ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + "env_vars": env_vars, + "labels": ethereum_package_shared_utils.label_maker( + client=constants.EL_TYPE.op_reth, + client_type=constants.CLIENT_TYPES.el, + image=participant.el_image, + connected_client=cl_client_name, + extra_labels=participant.el_extra_labels, + ), + "tolerations": tolerations, + "node_selectors": node_selectors, + } + + if participant.el_min_cpu > 0: + config_args["min_cpu"] = participant.el_min_cpu + if participant.el_max_cpu > 0: + config_args["max_cpu"] = participant.el_max_cpu + if participant.el_min_mem > 0: + config_args["min_memory"] = participant.el_min_mem + if participant.el_max_mem > 0: + config_args["max_memory"] = participant.el_max_mem + return ServiceConfig(**config_args) def new_op_reth_launcher( diff --git a/src/el_cl_launcher.star b/src/el_cl_launcher.star index 36ca1a3..92c245d 100644 --- a/src/el_cl_launcher.star +++ b/src/el_cl_launcher.star @@ -1,9 +1,11 @@ -constants = import_module( - "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" -) -shared_utils = import_module( +ethereum_package_shared_utils = import_module( "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" ) + +ethereum_package_input_parser = import_module( + "github.com/ethpandaops/ethereum-package/src/package_io/input_parser.star" +) + # EL op_geth = import_module("./el/op-geth/op_geth_launcher.star") op_reth = import_module("./el/op-reth/op_reth_launcher.star") @@ -24,6 +26,10 @@ def launch( num_participants, l1_config_env_vars, l2_services_suffix, + global_log_level, + global_node_selectors, + global_tolerations, + persistent, ): el_launchers = { "op-geth": { @@ -95,6 +101,19 @@ def launch( cl_type = participant.cl_type el_type = participant.el_type + node_selectors = ethereum_package_input_parser.get_client_node_selectors( + participant.node_selectors, + global_node_selectors, + ) + + el_tolerations = ethereum_package_input_parser.get_client_tolerations( + participant.el_tolerations, participant.tolerations, global_tolerations + ) + + cl_tolerations = ethereum_package_input_parser.get_client_tolerations( + participant.cl_tolerations, participant.tolerations, global_tolerations + ) + if el_type not in el_launchers: fail( "Unsupported launcher '{0}', need one of '{1}'".format( @@ -119,7 +138,9 @@ def launch( ) # Zero-pad the index using the calculated zfill value - index_str = shared_utils.zfill_custom(index + 1, len(str(len(participants)))) + index_str = ethereum_package_shared_utils.zfill_custom( + index + 1, len(str(len(participants))) + ) el_service_name = "op-el-{0}-{1}-{2}-{3}".format( index_str, el_type, cl_type, l2_services_suffix @@ -133,7 +154,11 @@ def launch( plan, el_launcher, el_service_name, - participant.el_image, + participant, + global_log_level, + persistent, + el_tolerations, + node_selectors, all_el_contexts, sequencer_enabled, sequencer_context, @@ -143,7 +168,11 @@ def launch( plan, cl_launcher, cl_service_name, - participant.cl_image, + participant, + global_log_level, + persistent, + cl_tolerations, + node_selectors, el_context, all_cl_contexts, l1_config_env_vars, diff --git a/src/l2.star b/src/l2.star index 4678a74..f12c6b1 100644 --- a/src/l2.star +++ b/src/l2.star @@ -2,7 +2,7 @@ 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") -static_files = import_module( +ethereum_package_static_files = import_module( "github.com/ethpandaops/ethereum-package/src/static_files/static_files.star" ) util = import_module("./util.star") @@ -16,6 +16,10 @@ def launch_l2( l1_config, l1_priv_key, l1_bootnode_context, + global_log_level, + global_node_selectors, + global_tolerations, + persistent, ): network_params = l2_args.network_params @@ -25,7 +29,7 @@ def launch_l2( plan.print("Deploying L2 with name {0}".format(network_params.name)) jwt_file = plan.upload_files( - src=static_files.JWT_PATH_FILEPATH, + src=ethereum_package_static_files.JWT_PATH_FILEPATH, name="op_jwt_file{0}".format(l2_services_suffix), ) @@ -37,6 +41,10 @@ def launch_l2( deployment_output, l1_config, l2_services_suffix, + global_log_level, + global_node_selectors, + global_tolerations, + persistent, ) all_el_contexts = [] diff --git a/src/package_io/constants.star b/src/package_io/constants.star new file mode 100644 index 0000000..08fe50a --- /dev/null +++ b/src/package_io/constants.star @@ -0,0 +1,28 @@ +EL_TYPE = struct( + op_geth="op-geth", + op_erigon="op-erigon", + op_nethermind="op-nethermind", + op_besu="op-besu", + op_reth="op-reth", +) + +CL_TYPE = struct( + op_node="op-node", + hildr="hildr", +) + +CLIENT_TYPES = struct( + el="execution", + cl="beacon", +) +VOLUME_SIZE = { + "kurtosis": { + "op_geth_volume_size": 5000, # 5GB + "op_erigon_volume_size": 3000, # 3GB + "op_nethermind_volume_size": 3000, # 3GB + "op_besu_volume_size": 3000, # 3GB + "op_reth_volume_size": 3000, # 3GB + "op_node_volume_size": 1000, # 1GB + "hildr_volume_size": 1000, # 1GB + }, +} diff --git a/src/package_io/input_parser.star b/src/package_io/input_parser.star index 12f5e5b..24d681d 100644 --- a/src/package_io/input_parser.star +++ b/src/package_io/input_parser.star @@ -36,7 +36,10 @@ DEFAULT_ADDITIONAL_SERVICES = [] 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( chains=[ struct( @@ -44,8 +47,30 @@ def input_parser(plan, input_args): struct( el_type=participant["el_type"], el_image=participant["el_image"], + el_log_level=participant["el_log_level"], + el_extra_env_vars=participant["el_extra_env_vars"], + el_extra_labels=participant["el_extra_labels"], + el_extra_params=participant["el_extra_params"], + el_tolerations=participant["el_tolerations"], + el_volume_size=participant["el_volume_size"], + el_min_cpu=participant["el_min_cpu"], + el_max_cpu=participant["el_max_cpu"], + el_min_mem=participant["el_min_mem"], + el_max_mem=participant["el_max_mem"], cl_type=participant["cl_type"], cl_image=participant["cl_image"], + cl_log_level=participant["cl_log_level"], + cl_extra_env_vars=participant["cl_extra_env_vars"], + cl_extra_labels=participant["cl_extra_labels"], + cl_extra_params=participant["cl_extra_params"], + cl_tolerations=participant["cl_tolerations"], + cl_volume_size=participant["cl_volume_size"], + cl_min_cpu=participant["cl_min_cpu"], + cl_max_cpu=participant["cl_max_cpu"], + cl_min_mem=participant["cl_min_mem"], + cl_max_mem=participant["cl_max_mem"], + node_selectors=participant["node_selectors"], + tolerations=participant["tolerations"], count=participant["count"], ) for participant in result["participants"] @@ -70,6 +95,10 @@ def input_parser(plan, input_args): image=results["op_contract_deployer_params"]["image"], artifacts_url=results["op_contract_deployer_params"]["artifacts_url"], ), + global_log_level=results["global_log_level"], + global_node_selectors=results["global_node_selectors"], + global_tolerations=results["global_tolerations"], + persistent=results["persistent"], ) @@ -137,6 +166,8 @@ def parse_network_params(plan, input_args): 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 @@ -144,6 +175,10 @@ def default_optimism_args(): return { "chains": default_chains(), "op_contract_deployer_params": default_op_contract_deployer_params(), + "global_log_level": "info", + "global_node_selectors": {}, + "global_tolerations": [], + "persistent": False, } @@ -174,10 +209,31 @@ def default_participant(): return { "el_type": "op-geth", "el_image": "", + "el_log_level": "", + "el_extra_env_vars": {}, + "el_extra_labels": {}, + "el_extra_params": [], + "el_tolerations": [], + "el_volume_size": 0, + "el_min_cpu": 0, + "el_max_cpu": 0, + "el_min_mem": 0, + "el_max_mem": 0, "cl_type": "op-node", "cl_image": "", + "cl_log_level": "", + "cl_extra_env_vars": {}, + "cl_extra_labels": {}, + "cl_extra_params": [], + "cl_tolerations": [], + "cl_volume_size": 0, + "cl_min_cpu": 0, + "cl_max_cpu": 0, + "cl_min_mem": 0, + "cl_max_mem": 0, + "node_selectors": {}, + "tolerations": [], "count": 1, - "sequencer": False, } diff --git a/src/package_io/sanity_check.star b/src/package_io/sanity_check.star index fc42ea3..c0e6784 100644 --- a/src/package_io/sanity_check.star +++ b/src/package_io/sanity_check.star @@ -2,10 +2,31 @@ PARTICIPANT_CATEGORIES = { "participants": [ "el_type", "el_image", + "el_log_level", + "el_extra_env_vars", + "el_extra_labels", + "el_extra_params", + "el_tolerations", + "el_volume_size", + "el_min_cpu", + "el_max_cpu", + "el_min_mem", + "el_max_mem", "cl_type", "cl_image", + "cl_log_level", + "cl_extra_env_vars", + "cl_extra_labels", + "cl_extra_params", + "cl_tolerations", + "cl_volume_size", + "cl_min_cpu", + "cl_max_cpu", + "cl_min_mem", + "cl_max_mem", + "node_selectors", + "tolerations", "count", - "sequencer", ], } @@ -34,6 +55,10 @@ ADDITIONAL_SERVICES_PARAMS = [ ROOT_PARAMS = [ "chains", "op_contract_deployer_params", + "global_log_level", + "global_node_selectors", + "global_tolerations", + "persistent", ] diff --git a/src/participant_network.star b/src/participant_network.star index 03ac102..9673562 100644 --- a/src/participant_network.star +++ b/src/participant_network.star @@ -14,6 +14,10 @@ def launch_participant_network( deployment_output, l1_config_env_vars, l2_services_suffix, + global_log_level, + global_node_selectors, + global_tolerations, + persistent, ): num_participants = len(participants) # First EL and sequencer CL @@ -26,6 +30,10 @@ def launch_participant_network( num_participants, l1_config_env_vars, l2_services_suffix, + global_log_level, + global_node_selectors, + global_tolerations, + persistent, ) all_participants = [] diff --git a/src/proposer/op-proposer/op_proposer_launcher.star b/src/proposer/op-proposer/op_proposer_launcher.star index 6b049f1..6b3078d 100644 --- a/src/proposer/op-proposer/op_proposer_launcher.star +++ b/src/proposer/op-proposer/op_proposer_launcher.star @@ -1,8 +1,8 @@ -shared_utils = import_module( +ethereum_package_shared_utils = import_module( "github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" ) -constants = import_module( +ethereum_package_constants = import_module( "github.com/ethpandaops/ethereum-package/src/package_io/constants.star" ) @@ -20,10 +20,10 @@ PROPOSER_HTTP_PORT_NUM = 8560 def get_used_ports(): used_ports = { - PROPOSER_HTTP_PORT_ID: shared_utils.new_port_spec( + PROPOSER_HTTP_PORT_ID: ethereum_package_shared_utils.new_port_spec( PROPOSER_HTTP_PORT_NUM, - shared_utils.TCP_PROTOCOL, - shared_utils.HTTP_APPLICATION_PROTOCOL, + ethereum_package_shared_utils.TCP_PROTOCOL, + ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, ), } return used_ports @@ -87,5 +87,5 @@ def get_proposer_config( image=image, ports=ports, cmd=cmd, - private_ip_address_placeholder=constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, + private_ip_address_placeholder=ethereum_package_constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, )