From 706915f5d312ee7b6b9350c0e4f71aa4025462ca Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Tue, 12 Dec 2023 11:41:17 +0100 Subject: [PATCH] feat: add blobber --- .github/tests/blobber.yaml | 19 ++++++ README.md | 8 +++ network_params.yaml | 2 + src/blobber/blobber_context.star | 5 ++ src/blobber/blobber_launcher.star | 67 +++++++++++++++++++ src/cl/lighthouse/lighthouse_launcher.star | 21 ++++++ src/cl/lodestar/lodestar_launcher.star | 19 ++++++ src/cl/nimbus/nimbus_launcher.star | 2 + src/cl/prysm/prysm_launcher.star | 19 ++++++ src/cl/teku/teku_launcher.star | 2 + src/package_io/input_parser.star | 11 +++ src/participant_network.star | 5 +- .../validator_keystores/keystore_files.star | 2 + .../validator_keystore_generator.star | 2 + 14 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 .github/tests/blobber.yaml create mode 100644 src/blobber/blobber_context.star create mode 100644 src/blobber/blobber_launcher.star diff --git a/.github/tests/blobber.yaml b/.github/tests/blobber.yaml new file mode 100644 index 000000000..231d3239a --- /dev/null +++ b/.github/tests/blobber.yaml @@ -0,0 +1,19 @@ +participants: + - el_client_type: geth + cl_client_type: teku + blobber_enabled: true + - el_client_type: nethermind + cl_client_type: prysm + blobber_enabled: true + - el_client_type: erigon + cl_client_type: nimbus + blobber_enabled: true + - el_client_type: besu + cl_client_type: lighthouse + blobber_enabled: true + - el_client_type: reth + cl_client_type: lodestar + blobber_enabled: true + - el_client_type: ethereumjs + cl_client_type: teku + blobber_enabled: true diff --git a/README.md b/README.md index a120356eb..c74315eea 100644 --- a/README.md +++ b/README.md @@ -218,6 +218,14 @@ participants: # Additional labels to be added. Default to empty labels: {} + # Blobber can be enabled with the `blobber_enabled` flag per client or globally + # Defaults to false + blobber_enabled: false + + # Blobber extra params can be passed in to the blobber container + # Defaults to empty + blobber_extra_params: [] + # Default configuration parameters for the Eth network network_params: # The network ID of the network. diff --git a/network_params.yaml b/network_params.yaml index 34f8f98a3..8601241c6 100644 --- a/network_params.yaml +++ b/network_params.yaml @@ -31,6 +31,8 @@ participants: prometheus_config: scrape_interval: 15s labels: {} + blobber_enabled: false + blobber_extra_params: [] network_params: network_id: "3151908" deposit_contract_address: "0x4242424242424242424242424242424242424242" diff --git a/src/blobber/blobber_context.star b/src/blobber/blobber_context.star new file mode 100644 index 000000000..1d778f74a --- /dev/null +++ b/src/blobber/blobber_context.star @@ -0,0 +1,5 @@ +def new_blobber_context(ip_addr, port_num): + return struct( + ip_addr=ip_addr, + port_num=port_num, + ) diff --git a/src/blobber/blobber_launcher.star b/src/blobber/blobber_launcher.star new file mode 100644 index 000000000..686694b48 --- /dev/null +++ b/src/blobber/blobber_launcher.star @@ -0,0 +1,67 @@ +shared_utils = import_module("../shared_utils/shared_utils.star") +input_parser = import_module("../package_io/input_parser.star") +cl_client_context = import_module("../cl/cl_client_context.star") + +blobber_context = import_module("../blobber/blobber_context.star") + +BLOBBER_BEACON_PORT_NUM = 9000 +BLOBBER_BEACON_PORT_ID = "discovery" +BLOBBER_VALIDATOR_PROXY_PORT_NUM = 4000 +BLOBBER_VALIDATOR_PROXY_PORT_ID = "http" + +PRIVATE_IP_ADDRESS_PLACEHOLDER = "KURTOSIS_IP_ADDR_PLACEHOLDER" + +DEFAULT_BLOBBER_IMAGE = "ethpandaops/blobber:1.0.5" + +VALIDATOR_KEYS_MOUNTPOINT_ON_CLIENTS = "/validator-keys" + +BLOBBER_USED_PORTS = { + BLOBBER_VALIDATOR_PROXY_PORT_ID: shared_utils.new_port_spec( + BLOBBER_VALIDATOR_PROXY_PORT_NUM, shared_utils.TCP_PROTOCOL, wait="5s" + ), + BLOBBER_BEACON_PORT_ID: shared_utils.new_port_spec( + BLOBBER_BEACON_PORT_NUM, shared_utils.TCP_PROTOCOL, wait=None + ), +} + + +def launch(plan, service_name, node_keystore_files, beacon_http_url, extra_params): + blobber_service_name = "{0}".format(service_name) + + blobber_config = get_config( + service_name, node_keystore_files, beacon_http_url, extra_params + ) + + blobber_service = plan.add_service(blobber_service_name, blobber_config) + return blobber_context.new_blobber_context( + blobber_service.ip_address, BLOBBER_VALIDATOR_PROXY_PORT_NUM + ) + + +def get_config(service_name, node_keystore_files, beacon_http_url, extra_params): + + validator_root_dirpath = shared_utils.path_join( + VALIDATOR_KEYS_MOUNTPOINT_ON_CLIENTS, + node_keystore_files.raw_root_dirpath, + ) + cmd = [ + "--beacon-port-start={0}".format(BLOBBER_BEACON_PORT_NUM), + "--cl={0}".format(beacon_http_url), + "--validator-key-folder={0}".format(validator_root_dirpath), + "--enable-unsafe-mode", + "--external-ip={0}".format(PRIVATE_IP_ADDRESS_PLACEHOLDER), + "--validator-proxy-port-start={0}".format(BLOBBER_VALIDATOR_PROXY_PORT_NUM), # use the same port as the beacon http port + ] + + if len(extra_params) > 0: + cmd.extend([param for param in extra_params]) + + return ServiceConfig( + image=DEFAULT_BLOBBER_IMAGE, + ports=BLOBBER_USED_PORTS, + files={ + VALIDATOR_KEYS_MOUNTPOINT_ON_CLIENTS: node_keystore_files.files_artifact_uuid + }, + cmd=cmd, + private_ip_address_placeholder=PRIVATE_IP_ADDRESS_PLACEHOLDER, + ) diff --git a/src/cl/lighthouse/lighthouse_launcher.star b/src/cl/lighthouse/lighthouse_launcher.star index c06b1ba8e..a86411257 100644 --- a/src/cl/lighthouse/lighthouse_launcher.star +++ b/src/cl/lighthouse/lighthouse_launcher.star @@ -6,6 +6,8 @@ cl_node_ready_conditions = import_module("../../cl/cl_node_ready_conditions.star constants = import_module("../../package_io/constants.star") +blobber_launcher = import_module("../../blobber/blobber_launcher.star") + LIGHTHOUSE_BINARY_COMMAND = "lighthouse" VALIDATOR_KEYS_MOUNTPOINT_ON_CLIENTS = "/validator-keys" @@ -113,6 +115,8 @@ def launch( v_max_mem, snooper_enabled, snooper_engine_context, + blobber_enabled, + blobber_extra_params, extra_beacon_params, extra_validator_params, extra_beacon_labels, @@ -155,6 +159,23 @@ def launch( beacon_service.ip_address, beacon_http_port.number ) + # Blobber config + if blobber_enabled: + blobber_service_name = "{0}-{1}".format("blobber", beacon_node_service_name) + blobber_config = blobber_launcher.get_config( + blobber_service_name, + node_keystore_files, + beacon_http_url, + blobber_extra_params, + ) + + blobber_service = plan.add_service(blobber_service_name, blobber_config) + blobber_http_port = blobber_service.ports[BEACON_HTTP_PORT_ID] + blobber_http_url = "http://{0}:{1}".format( + blobber_service.ip_address, beacon_http_port.number + ) + beacon_http_url = blobber_http_url + # Launch validator node if we have a keystore validator_service = None if node_keystore_files != None: diff --git a/src/cl/lodestar/lodestar_launcher.star b/src/cl/lodestar/lodestar_launcher.star index 970bd1627..94a6b9db1 100644 --- a/src/cl/lodestar/lodestar_launcher.star +++ b/src/cl/lodestar/lodestar_launcher.star @@ -89,6 +89,8 @@ def launch( v_max_mem, snooper_enabled, snooper_engine_context, + blobber_enabled, + blobber_extra_params, extra_beacon_params, extra_validator_params, extra_beacon_labels, @@ -132,6 +134,23 @@ def launch( beacon_service.ip_address, beacon_http_port.number ) + # Blobber config + if blobber_enabled: + blobber_service_name = "{0}-{1}".format("blobber", beacon_node_service_name) + blobber_config = blobber_launcher.get_config( + blobber_service_name, + node_keystore_files, + beacon_http_url, + blobber_extra_params, + ) + + blobber_service = plan.add_service(blobber_service_name, blobber_config) + blobber_http_port = blobber_service.ports[BEACON_HTTP_PORT_ID] + blobber_http_url = "http://{0}:{1}".format( + blobber_service.ip_address, beacon_http_port.number + ) + beacon_http_url = blobber_http_url + # Launch validator node if we have a keystore if node_keystore_files != None: v_min_cpu = int(v_min_cpu) if int(v_min_cpu) > 0 else VALIDATOR_MIN_CPU diff --git a/src/cl/nimbus/nimbus_launcher.star b/src/cl/nimbus/nimbus_launcher.star index 3f51c5818..0a110ff88 100644 --- a/src/cl/nimbus/nimbus_launcher.star +++ b/src/cl/nimbus/nimbus_launcher.star @@ -91,6 +91,8 @@ def launch( v_max_mem, snooper_enabled, snooper_engine_context, + blobber_enabled, + blobber_extra_params, extra_beacon_params, extra_validator_params, extra_beacon_labels, diff --git a/src/cl/prysm/prysm_launcher.star b/src/cl/prysm/prysm_launcher.star index 3626e120e..28792261b 100644 --- a/src/cl/prysm/prysm_launcher.star +++ b/src/cl/prysm/prysm_launcher.star @@ -102,6 +102,8 @@ def launch( v_max_mem, snooper_enabled, snooper_engine_context, + blobber_enabled, + blobber_extra_params, extra_beacon_params, extra_validator_params, extra_beacon_labels, @@ -158,6 +160,23 @@ def launch( beacon_http_endpoint = "{0}:{1}".format(beacon_service.ip_address, HTTP_PORT_NUM) beacon_rpc_endpoint = "{0}:{1}".format(beacon_service.ip_address, RPC_PORT_NUM) + # Blobber config + if blobber_enabled: + blobber_service_name = "{0}-{1}".format("blobber", beacon_node_service_name) + blobber_config = blobber_launcher.get_config( + blobber_service_name, + node_keystore_files, + beacon_http_url, + blobber_extra_params, + ) + + blobber_service = plan.add_service(blobber_service_name, blobber_config) + blobber_http_port = blobber_service.ports[BEACON_HTTP_PORT_ID] + blobber_http_url = "http://{0}:{1}".format( + blobber_service.ip_address, beacon_http_port.number + ) + beacon_http_url = blobber_http_url + # Launch validator node if we have a keystore file validator_service = None if node_keystore_files != None: diff --git a/src/cl/teku/teku_launcher.star b/src/cl/teku/teku_launcher.star index a116f11b5..e33088f27 100644 --- a/src/cl/teku/teku_launcher.star +++ b/src/cl/teku/teku_launcher.star @@ -93,6 +93,8 @@ def launch( v_max_mem, snooper_enabled, snooper_engine_context, + blobber_enabled, + blobber_extra_params, extra_beacon_params, extra_validator_params, extra_beacon_labels, diff --git a/src/package_io/input_parser.star b/src/package_io/input_parser.star index 5b09f51bf..cc8da51de 100644 --- a/src/package_io/input_parser.star +++ b/src/package_io/input_parser.star @@ -152,6 +152,8 @@ def input_parser(plan, input_args): scrape_interval=participant["prometheus_config"]["scrape_interval"], labels=participant["prometheus_config"]["labels"], ), + blobber_enabled=participant["blobber_enabled"], + blobber_extra_params=participant["blobber_params"], ) for participant in result["participants"] ], @@ -281,6 +283,13 @@ def parse_network_params(input_args): ethereum_metrics_exporter_enabled = participant[ "ethereum_metrics_exporter_enabled" ] + + blobber_enabled = participant["blobber_enabled"] + if blobber_enabled: + if participant["cl_client_type"] == ("teku" or "nimbus"): + # TODO: remove this once teku and nimbus support blobber + participant["blobber_enabled"] = False + if ethereum_metrics_exporter_enabled == False: default_ethereum_metrics_exporter_enabled = result[ "ethereum_metrics_exporter_enabled" @@ -433,6 +442,8 @@ def default_participant(): "scrape_interval": "15s", "labels": None, }, + "blobber_enabled": False, + "blobber_params": [], } diff --git a/src/participant_network.star b/src/participant_network.star index efa82ff45..0905c4308 100644 --- a/src/participant_network.star +++ b/src/participant_network.star @@ -311,7 +311,6 @@ def launch_participant_network( snooper_engine_context ) ) - all_snooper_engine_contexts.append(snooper_engine_context) if index == 0: @@ -335,6 +334,8 @@ def launch_participant_network( participant.v_max_mem, participant.snooper_enabled, snooper_engine_context, + participant.blobber_enabled, + participant.blobber_extra_params, participant.beacon_extra_params, participant.validator_extra_params, participant.beacon_extra_labels, @@ -362,6 +363,8 @@ def launch_participant_network( participant.v_max_mem, participant.snooper_enabled, snooper_engine_context, + participant.blobber_enabled, + participant.blobber_extra_params, participant.beacon_extra_params, participant.validator_extra_params, participant.beacon_extra_labels, diff --git a/src/prelaunch_data_generator/validator_keystores/keystore_files.star b/src/prelaunch_data_generator/validator_keystores/keystore_files.star index 2d2383f17..d10f359b4 100644 --- a/src/prelaunch_data_generator/validator_keystores/keystore_files.star +++ b/src/prelaunch_data_generator/validator_keystores/keystore_files.star @@ -1,6 +1,7 @@ # One of these will be created per node we're trying to start def new_keystore_files( files_artifact_uuid, + raw_root_dirpath, raw_keys_relative_dirpath, raw_secrets_relative_dirpath, nimbus_keys_relative_dirpath, @@ -11,6 +12,7 @@ def new_keystore_files( return struct( files_artifact_uuid=files_artifact_uuid, # ------------ All directories below are relative to the root of the files artifact ---------------- + raw_root_dirpath=raw_root_dirpath, raw_keys_relative_dirpath=raw_keys_relative_dirpath, raw_secrets_relative_dirpath=raw_secrets_relative_dirpath, nimbus_keys_relative_dirpath=nimbus_keys_relative_dirpath, diff --git a/src/prelaunch_data_generator/validator_keystores/validator_keystore_generator.star b/src/prelaunch_data_generator/validator_keystores/validator_keystore_generator.star index de459ce43..a4e50a2cd 100644 --- a/src/prelaunch_data_generator/validator_keystores/validator_keystore_generator.star +++ b/src/prelaunch_data_generator/validator_keystores/validator_keystore_generator.star @@ -140,6 +140,7 @@ def generate_validator_keystores(plan, mnemonic, participants): base_dirname_in_artifact = shared_utils.path_base(output_dirpath) to_add = keystore_files_module.new_keystore_files( artifact_name, + shared_utils.path_join(base_dirname_in_artifact), shared_utils.path_join(base_dirname_in_artifact, RAW_KEYS_DIRNAME), shared_utils.path_join(base_dirname_in_artifact, RAW_SECRETS_DIRNAME), shared_utils.path_join(base_dirname_in_artifact, NIMBUS_KEYS_DIRNAME), @@ -283,6 +284,7 @@ def generate_valdiator_keystores_in_parallel(plan, mnemonic, participants): base_dirname_in_artifact = shared_utils.path_base(output_dirpath) to_add = keystore_files_module.new_keystore_files( artifact_name, + shared_utils.path_join(base_dirname_in_artifact), shared_utils.path_join(base_dirname_in_artifact, RAW_KEYS_DIRNAME), shared_utils.path_join(base_dirname_in_artifact, RAW_SECRETS_DIRNAME), shared_utils.path_join(base_dirname_in_artifact, NIMBUS_KEYS_DIRNAME),