diff --git a/.github/tests/besu-persistence.yaml b/.github/tests/besu-persistence.yaml deleted file mode 100644 index b84df9add..000000000 --- a/.github/tests/besu-persistence.yaml +++ /dev/null @@ -1,5 +0,0 @@ -participants: - - el_client_type: besu - cl_client_type: lighthouse -additional_services: [] -persistent: true diff --git a/.github/tests/erigon-persistence.yaml b/.github/tests/broken-docker-persistence.yaml similarity index 52% rename from .github/tests/erigon-persistence.yaml rename to .github/tests/broken-docker-persistence.yaml index 45dd0ba77..96195aad7 100644 --- a/.github/tests/erigon-persistence.yaml +++ b/.github/tests/broken-docker-persistence.yaml @@ -1,5 +1,7 @@ participants: + - el_client_type: besu + cl_client_type: teku - el_client_type: erigon - cl_client_type: lighthouse + cl_client_type: teku additional_services: [] persistent: true diff --git a/.github/tests/devnet-test.yaml b/.github/tests/devnet-test.yaml new file mode 100644 index 000000000..72502f846 --- /dev/null +++ b/.github/tests/devnet-test.yaml @@ -0,0 +1,28 @@ +participants: + - el_client_type: geth + el_client_image: ethpandaops/geth:master + cl_client_type: teku + cl_client_image: ethpandaops/teku:master + - el_client_type: nethermind + el_client_image: ethpandaops/nethermind:master + cl_client_type: prysm + cl_client_image: ethpandaops/prysm:develop,ethpandaops/prysm-validator:develop + - el_client_type: erigon + el_client_image: ethpandaops/erigon:devel + cl_client_type: nimbus + cl_client_image: ethpandaops/nimbus:unstable + - el_client_type: besu + el_client_image: ethpandaops/besu:main + cl_client_type: lighthouse + cl_client_image: ethpandaops/lighthouse:unstable + - el_client_type: reth + el_client_image: ethpandaops/reth:main + cl_client_type: lodestar + cl_client_image: ethpandaops/lodestar:unstable + - el_client_type: ethereumjs + el_client_image: ethpandaops/ethereumjs:master + cl_client_type: teku + cl_client_image: ethpandaops/teku:master +network_params: + network: "dencun-devnet-12" +additional_services: [] diff --git a/.github/tests/teku-persistence.yaml b/.github/tests/teku-persistence.yaml deleted file mode 100644 index dad2f9b4e..000000000 --- a/.github/tests/teku-persistence.yaml +++ /dev/null @@ -1,5 +0,0 @@ -participants: - - el_client_type: geth - cl_client_type: teku -additional_services: [] -persistent: true diff --git a/main.star b/main.star index de75ccaf2..07ce1cb72 100644 --- a/main.star +++ b/main.star @@ -69,6 +69,11 @@ def run(plan, args={}): ) prometheus_additional_metrics_jobs = [] + raw_jwt_secret = read_file(static_files.JWT_PATH_FILEPATH) + jwt_file = plan.upload_files( + src=static_files.JWT_PATH_FILEPATH, + name="jwt_file", + ) plan.print("Read the prometheus, grafana templates") plan.print( @@ -86,6 +91,7 @@ def run(plan, args={}): args_with_right_defaults.participants, network_params, args_with_right_defaults.global_client_log_level, + jwt_file, persistent, parallel_keystore_generation, ) @@ -117,17 +123,18 @@ def run(plan, args={}): all_cl_client_contexts, args_with_right_defaults.participants, ) - - if network_params.deneb_fork_epoch != 0: - plan.print("Launching 4788 contract deployer") - el_uri = "http://{0}:{1}".format( - all_el_client_contexts[0].ip_addr, all_el_client_contexts[0].rpc_port_num - ) - eip4788_deployment.deploy_eip4788_contract_in_background( - plan, - genesis_constants.PRE_FUNDED_ACCOUNTS[5].private_key, - el_uri, - ) + if network_params.network == "kurtosis": + if network_params.deneb_fork_epoch != 0: + plan.print("Launching 4788 contract deployer") + el_uri = "http://{0}:{1}".format( + all_el_client_contexts[0].ip_addr, + all_el_client_contexts[0].rpc_port_num, + ) + eip4788_deployment.deploy_eip4788_contract_in_background( + plan, + genesis_constants.PRE_FUNDED_ACCOUNTS[5].private_key, + el_uri, + ) fuzz_target = "http://{0}:{1}".format( all_el_client_contexts[0].ip_addr, @@ -165,17 +172,11 @@ def run(plan, args={}): beacon_uri = "{0}:{1}".format( all_cl_client_contexts[0].ip_addr, all_cl_client_contexts[0].http_port_num ) - jwt_secret = plan.run_sh( - run="cat " + constants.JWT_AUTH_PATH + " | tr -d '\n'", - image="busybox", - files={"/data": el_cl_data_files_artifact_uuid}, - wait=None, - ) endpoint = mock_mev.launch_mock_mev( plan, el_uri, beacon_uri, - jwt_secret.output, + raw_jwt_secret, args_with_right_defaults.global_client_log_level, ) mev_endpoints.append(endpoint) diff --git a/src/cl/lighthouse/lighthouse_launcher.star b/src/cl/lighthouse/lighthouse_launcher.star index a5f71167a..5878343d2 100644 --- a/src/cl/lighthouse/lighthouse_launcher.star +++ b/src/cl/lighthouse/lighthouse_launcher.star @@ -3,7 +3,6 @@ input_parser = import_module("../../package_io/input_parser.star") cl_client_context = import_module("../../cl/cl_client_context.star") node_metrics = import_module("../../node_metrics_info.star") 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") @@ -139,7 +138,10 @@ def launch( # Launch Beacon node beacon_config = get_beacon_config( + plan, launcher.el_cl_genesis_data, + launcher.jwt_file, + launcher.network, image, beacon_service_name, bootnode_contexts, @@ -263,7 +265,10 @@ def launch( def get_beacon_config( + plan, el_cl_genesis_data, + jwt_file, + network, image, service_name, boot_cl_client_ctxs, @@ -325,7 +330,7 @@ def get_beacon_config( # and the option says it's "useful for testing in smaller networks" (unclear what happens in larger networks) "--disable-packet-filter", "--execution-endpoints=" + EXECUTION_ENGINE_ENDPOINT, - "--jwt-secrets=" + constants.JWT_AUTH_PATH, + "--jwt-secrets=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, "--suggested-fee-recipient=" + constants.VALIDATING_REWARDS_ACCOUNT, # Set per Paris' recommendation to reduce noise in the logs "--subscribe-all-subnets", @@ -337,20 +342,31 @@ def get_beacon_config( # ^^^^^^^^^^^^^^^^^^^ METRICS CONFIG ^^^^^^^^^^^^^^^^^^^^^ ] - if boot_cl_client_ctxs != None: - cmd.append( - "--boot-nodes=" - + ",".join( - [ctx.enr for ctx in boot_cl_client_ctxs[: constants.MAX_ENR_ENTRIES]] + if network == "kurtosis": + if boot_cl_client_ctxs != None: + cmd.append( + "--boot-nodes=" + + ",".join( + [ + ctx.enr + for ctx in boot_cl_client_ctxs[: constants.MAX_ENR_ENTRIES] + ] + ) ) - ) + cmd.append( + "--trusted-peers=" + + ",".join( + [ + ctx.peer_id + for ctx in boot_cl_client_ctxs[: constants.MAX_ENR_ENTRIES] + ] + ) + ) + elif network not in constants.PUBLIC_NETWORKS: cmd.append( - "--trusted-peers=" - + ",".join( - [ - ctx.peer_id - for ctx in boot_cl_client_ctxs[: constants.MAX_ENR_ENTRIES] - ] + "--boot-nodes=" + + shared_utils.get_devnet_enrs_list( + plan, el_cl_genesis_data.files_artifact_uuid ) ) @@ -362,7 +378,8 @@ def get_beacon_config( endpoint="/eth/v1/node/identity", port_id=BEACON_HTTP_PORT_ID ) files = { - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid + constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, + constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, } if persistent: @@ -476,7 +493,9 @@ def get_validator_config( ) -def new_lighthouse_launcher(el_cl_genesis_data): +def new_lighthouse_launcher(el_cl_genesis_data, jwt_file, network): return struct( el_cl_genesis_data=el_cl_genesis_data, + jwt_file=jwt_file, + network=network, ) diff --git a/src/cl/lodestar/lodestar_launcher.star b/src/cl/lodestar/lodestar_launcher.star index b9484bf7b..7d81713d0 100644 --- a/src/cl/lodestar/lodestar_launcher.star +++ b/src/cl/lodestar/lodestar_launcher.star @@ -116,7 +116,10 @@ def launch( # Launch Beacon node beacon_config = get_beacon_config( + plan, launcher.el_cl_genesis_data, + launcher.jwt_file, + launcher.network, image, beacon_service_name, bootnode_contexts, @@ -232,7 +235,10 @@ def launch( def get_beacon_config( + plan, el_cl_genesis_data, + jwt_file, + network, image, service_name, bootnode_contexts, @@ -293,19 +299,26 @@ def get_beacon_config( "--enr.udp={0}".format(DISCOVERY_PORT_NUM), # Set per Pari's recommendation to reduce noise in the logs "--subscribeAllSubnets=true", - "--jwt-secret=" + constants.JWT_AUTH_PATH, + "--jwt-secret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, # vvvvvvvvvvvvvvvvvvv METRICS CONFIG vvvvvvvvvvvvvvvvvvvvv "--metrics", "--metrics.address=0.0.0.0", "--metrics.port={0}".format(METRICS_PORT_NUM), # ^^^^^^^^^^^^^^^^^^^ METRICS CONFIG ^^^^^^^^^^^^^^^^^^^^^ ] - - if bootnode_contexts != None: + if network == "kurtosis": + if bootnode_contexts != None: + cmd.append( + "--bootnodes=" + + ",".join( + [ctx.enr for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]] + ) + ) + elif network not in constants.PUBLIC_NETWORKS: cmd.append( "--bootnodes=" - + ",".join( - [ctx.enr for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]] + + shared_utils.get_devnet_enrs_list( + plan, el_cl_genesis_data.files_artifact_uuid ) ) @@ -313,7 +326,8 @@ def get_beacon_config( # this is a repeated, we convert it into Starlark cmd.extend([param for param in extra_params]) files = { - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid + constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, + constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, } if persistent: @@ -424,7 +438,9 @@ def get_validator_config( ) -def new_lodestar_launcher(el_cl_genesis_data): +def new_lodestar_launcher(el_cl_genesis_data, jwt_file, network): return struct( el_cl_genesis_data=el_cl_genesis_data, + jwt_file=jwt_file, + network=network, ) diff --git a/src/cl/nimbus/nimbus_launcher.star b/src/cl/nimbus/nimbus_launcher.star index 91672d9cb..5bf613adf 100644 --- a/src/cl/nimbus/nimbus_launcher.star +++ b/src/cl/nimbus/nimbus_launcher.star @@ -155,7 +155,10 @@ def launch( bn_max_mem = int(bn_max_mem) if int(bn_max_mem) > 0 else BEACON_MAX_MEMORY beacon_config = get_beacon_config( + plan, launcher.el_cl_genesis_data, + launcher.jwt_file, + launcher.network, image, beacon_service_name, bootnode_contexts, @@ -261,7 +264,10 @@ def launch( def get_beacon_config( + plan, el_cl_genesis_data, + jwt_file, + network, image, service_name, bootnode_contexts, @@ -325,7 +331,7 @@ def get_beacon_config( "--subscribe-all-subnets=true", # Nimbus can handle a max of 256 threads, if the host has more then nimbus crashes. Setting it to 4 so it doesn't crash on build servers "--num-threads=4", - "--jwt-secret=" + constants.JWT_AUTH_PATH, + "--jwt-secret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, # vvvvvvvvvvvvvvvvvvv METRICS CONFIG vvvvvvvvvvvvvvvvvvvvv "--metrics", "--metrics-address=0.0.0.0", @@ -346,20 +352,27 @@ def get_beacon_config( if node_keystore_files != None and not split_mode_enabled: cmd.extend(validator_flags) - if bootnode_contexts == None: - # Copied from https://github.com/status-im/nimbus-eth2/blob/67ab477a27e358d605e99bffeb67f98d18218eca/scripts/launch_local_testnet.sh#L417 - # See explanation there - cmd.append("--subscribe-all-subnets") - else: - for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]: - cmd.append("--bootstrap-node=" + ctx.enr) - cmd.append("--direct-peer=" + ctx.multiaddr) + if network == "kurtosis": + if bootnode_contexts == None: + # Copied from https://github.com/status-im/nimbus-eth2/blob/67ab477a27e358d605e99bffeb67f98d18218eca/scripts/launch_local_testnet.sh#L417 + # See explanation there + cmd.append("--subscribe-all-subnets") + else: + for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]: + cmd.append("--bootstrap-node=" + ctx.enr) + cmd.append("--direct-peer=" + ctx.multiaddr) + elif network not in constants.PUBLIC_NETWORKS: + cmd.append( + "--bootstrap-node=" + + shared_utils.get_devnet_enr(plan, el_cl_genesis_data.files_artifact_uuid) + ) if len(extra_params) > 0: cmd.extend([param for param in extra_params]) files = { constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, + constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, } if node_keystore_files != None and not split_mode_enabled: files[ @@ -465,7 +478,9 @@ def get_validator_config( ) -def new_nimbus_launcher(el_cl_genesis_data): +def new_nimbus_launcher(el_cl_genesis_data, jwt_file, network): return struct( el_cl_genesis_data=el_cl_genesis_data, + jwt_file=jwt_file, + network=network, ) diff --git a/src/cl/prysm/prysm_launcher.star b/src/cl/prysm/prysm_launcher.star index e9b0266e0..2a6ecc2a9 100644 --- a/src/cl/prysm/prysm_launcher.star +++ b/src/cl/prysm/prysm_launcher.star @@ -142,7 +142,10 @@ def launch( bn_max_mem = int(bn_max_mem) if int(bn_max_mem) > 0 else BEACON_MAX_MEMORY beacon_config = get_beacon_config( + plan, launcher.el_cl_genesis_data, + launcher.jwt_file, + launcher.network, beacon_image, beacon_service_name, bootnode_contexts, @@ -250,7 +253,10 @@ def launch( def get_beacon_config( + plan, el_cl_genesis_data, + jwt_file, + network, beacon_image, service_name, bootnode_contexts, @@ -302,7 +308,7 @@ def get_beacon_config( "--suggested-fee-recipient=" + constants.VALIDATING_REWARDS_ACCOUNT, # Set per Pari's recommendation to reduce noise "--subscribe-all-subnets=true", - "--jwt-secret=" + constants.JWT_AUTH_PATH, + "--jwt-secret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, "--enable-debug-rpc-endpoints=true", # vvvvvvvvv METRICS CONFIG vvvvvvvvvvvvvvvvvvvvv "--disable-monitoring=false", @@ -310,11 +316,17 @@ def get_beacon_config( "--monitoring-port={0}".format(BEACON_MONITORING_PORT_NUM) # ^^^^^^^^^^^^^^^^^^^ METRICS CONFIG ^^^^^^^^^^^^^^^^^^^^^ ] - - if bootnode_contexts != None: - for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]: - cmd.append("--peer=" + ctx.multiaddr) - cmd.append("--bootstrap-node=" + ctx.enr) + if network == "kurtosis": + if bootnode_contexts != None: + for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]: + cmd.append("--peer=" + ctx.multiaddr) + cmd.append("--bootstrap-node=" + ctx.enr) + cmd.append("--p2p-static-id=true") + elif network not in constants.PUBLIC_NETWORKS: + cmd.append( + "--bootstrap-node=" + + shared_utils.get_devnet_enr(plan, el_cl_genesis_data.files_artifact_uuid) + ) cmd.append("--p2p-static-id=true") if len(extra_params) > 0: @@ -322,7 +334,8 @@ def get_beacon_config( cmd.extend([param for param in extra_params]) files = { - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid + constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, + constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, } if persistent: @@ -394,7 +407,6 @@ def get_validator_config( "--monitoring-port={0}".format(VALIDATOR_MONITORING_PORT_NUM), "--verbosity=" + log_level, "--suggested-fee-recipient=" + constants.VALIDATING_REWARDS_ACCOUNT, - # TODO(old) SOMETHING ABOUT JWT # vvvvvvvvvvvvvvvvvvv METRICS CONFIG vvvvvvvvvvvvvvvvvvvvv "--disable-monitoring=false", "--monitoring-host=0.0.0.0", @@ -440,10 +452,16 @@ def get_validator_config( def new_prysm_launcher( - el_cl_genesis_data, prysm_password_relative_filepath, prysm_password_artifact_uuid + el_cl_genesis_data, + jwt_file, + network, + prysm_password_relative_filepath, + prysm_password_artifact_uuid, ): return struct( el_cl_genesis_data=el_cl_genesis_data, + jwt_file=jwt_file, + network=network, prysm_password_artifact_uuid=prysm_password_artifact_uuid, prysm_password_relative_filepath=prysm_password_relative_filepath, ) diff --git a/src/cl/teku/teku_launcher.star b/src/cl/teku/teku_launcher.star index 6b2b42a26..75d7940cb 100644 --- a/src/cl/teku/teku_launcher.star +++ b/src/cl/teku/teku_launcher.star @@ -3,7 +3,6 @@ input_parser = import_module("../../package_io/input_parser.star") cl_client_context = import_module("../../cl/cl_client_context.star") node_metrics = import_module("../../node_metrics_info.star") cl_node_ready_conditions = import_module("../../cl/cl_node_ready_conditions.star") - constants = import_module("../../package_io/constants.star") TEKU_BINARY_FILEPATH_IN_IMAGE = "/opt/teku/bin/teku" @@ -145,7 +144,10 @@ def launch( bn_max_mem = int(bn_max_mem) if int(bn_max_mem) > 0 else BEACON_MAX_MEMORY config = get_beacon_config( + plan, launcher.el_cl_genesis_data, + launcher.jwt_file, + launcher.network, image, beacon_service_name, bootnode_context, @@ -254,7 +256,10 @@ def launch( def get_beacon_config( + plan, el_cl_genesis_data, + jwt_file, + network, image, service_name, bootnode_contexts, @@ -319,7 +324,7 @@ def get_beacon_config( "--rest-api-port={0}".format(BEACON_HTTP_PORT_NUM), "--rest-api-host-allowlist=*", "--data-storage-non-canonical-blocks-enabled=true", - "--ee-jwt-secret-file=" + constants.JWT_AUTH_PATH, + "--ee-jwt-secret-file=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, "--ee-endpoint=" + EXECUTION_ENGINE_ENDPOINT, # vvvvvvvvvvvvvvvvvvv METRICS CONFIG vvvvvvvvvvvvvvvvvvvvv "--metrics-enabled", @@ -328,6 +333,8 @@ def get_beacon_config( "--metrics-categories=BEACON,PROCESS,LIBP2P,JVM,NETWORK,PROCESS", "--metrics-port={0}".format(BEACON_METRICS_PORT_NUM), # ^^^^^^^^^^^^^^^^^^^ METRICS CONFIG ^^^^^^^^^^^^^^^^^^^^^ + # To enable syncing other networks too without checkpoint syncing + "--ignore-weak-subjectivity-period-enabled=true", ] validator_flags = [ "--validator-keys={0}:{1}".format( @@ -344,21 +351,28 @@ def get_beacon_config( if node_keystore_files != None and not split_mode_enabled: cmd.extend(validator_flags) - - if bootnode_contexts != None: - cmd.append( - "--p2p-discovery-bootnodes=" - + ",".join( - [ctx.enr for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]] + if network == "kurtosis": + if bootnode_contexts != None: + cmd.append( + "--p2p-discovery-bootnodes=" + + ",".join( + [ctx.enr for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES]] + ) ) - ) + cmd.append( + "--p2p-static-peers=" + + ",".join( + [ + ctx.multiaddr + for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES] + ] + ) + ) + elif network not in constants.PUBLIC_NETWORKS: cmd.append( - "--p2p-static-peers=" - + ",".join( - [ - ctx.multiaddr - for ctx in bootnode_contexts[: constants.MAX_ENR_ENTRIES] - ] + "--p2p-discovery-bootnodes=" + + shared_utils.get_devnet_enrs_list( + plan, el_cl_genesis_data.files_artifact_uuid ) ) @@ -368,6 +382,7 @@ def get_beacon_config( files = { constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, + constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, } if node_keystore_files != None and not split_mode_enabled: files[ @@ -485,5 +500,7 @@ def get_validator_config( ) -def new_teku_launcher(el_cl_genesis_data): - return struct(el_cl_genesis_data=el_cl_genesis_data) +def new_teku_launcher(el_cl_genesis_data, jwt_file, network): + return struct( + el_cl_genesis_data=el_cl_genesis_data, jwt_file=jwt_file, network=network + ) diff --git a/src/el/besu/besu_launcher.star b/src/el/besu/besu_launcher.star index 2e8d9c515..6a8fce143 100644 --- a/src/el/besu/besu_launcher.star +++ b/src/el/besu/besu_launcher.star @@ -4,7 +4,6 @@ el_client_context = import_module("../../el/el_client_context.star") el_admin_node_info = import_module("../../el/el_admin_node_info.star") node_metrics = import_module("../../node_metrics_info.star") constants = import_module("../../package_io/constants.star") - # The dirpath of the execution data directory on the client container EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/opt/besu/execution-data" @@ -89,8 +88,10 @@ def launch( cl_client_name = service_name.split("-")[3] config = get_config( - launcher.network_id, + plan, launcher.el_cl_genesis_data, + launcher.jwt_file, + launcher.network, image, service_name, existing_el_clients, @@ -129,8 +130,10 @@ def launch( def get_config( - network_id, + plan, el_cl_genesis_data, + jwt_file, + network, image, service_name, existing_el_clients, @@ -152,7 +155,6 @@ def get_config( "--genesis-file=" + constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER + "/besu.json", - "--network-id=" + network_id, "--host-allowlist=*", "--rpc-http-enabled=true", "--rpc-http-host=0.0.0.0", @@ -167,7 +169,7 @@ def get_config( "--p2p-host=" + PRIVATE_IP_ADDRESS_PLACEHOLDER, "--p2p-port={0}".format(DISCOVERY_PORT_NUM), "--engine-rpc-enabled=true", - "--engine-jwt-secret=" + constants.JWT_AUTH_PATH, + "--engine-jwt-secret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, "--engine-host-allowlist=*", "--engine-rpc-port={0}".format(ENGINE_HTTP_RPC_PORT_NUM), "--sync-mode=FULL", @@ -176,15 +178,22 @@ def get_config( "--metrics-host=0.0.0.0", "--metrics-port={0}".format(METRICS_PORT_NUM), ] - - if len(existing_el_clients) > 0: + if network == "kurtosis": + if len(existing_el_clients) > 0: + cmd.append( + "--bootnodes=" + + ",".join( + [ + ctx.enode + for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + ] + ) + ) + elif network not in constants.PUBLIC_NETWORKS: cmd.append( "--bootnodes=" - + ",".join( - [ - ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] - ] + + shared_utils.get_devnet_enodes( + plan, el_cl_genesis_data.files_artifact_uuid ) ) @@ -198,6 +207,7 @@ def get_config( files = { constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, + constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, } if persistent: @@ -226,5 +236,9 @@ def get_config( ) -def new_besu_launcher(network_id, el_cl_genesis_data): - return struct(network_id=network_id, el_cl_genesis_data=el_cl_genesis_data) +def new_besu_launcher(el_cl_genesis_data, jwt_file, network): + return struct( + el_cl_genesis_data=el_cl_genesis_data, + jwt_file=jwt_file, + network=network, + ) diff --git a/src/el/erigon/erigon_launcher.star b/src/el/erigon/erigon_launcher.star index 1892be186..25489d33b 100644 --- a/src/el/erigon/erigon_launcher.star +++ b/src/el/erigon/erigon_launcher.star @@ -90,8 +90,10 @@ def launch( cl_client_name = service_name.split("-")[3] config = get_config( - launcher.network_id, + plan, launcher.el_cl_genesis_data, + launcher.jwt_file, + launcher.network, image, service_name, existing_el_clients, @@ -132,8 +134,10 @@ def launch( def get_config( - network_id, + plan, el_cl_genesis_data, + jwt_file, + network, image, service_name, existing_el_clients, @@ -148,8 +152,6 @@ def get_config( extra_labels, persistent, ): - network_id = network_id - init_datadir_cmd_str = "erigon init --datadir={0} {1}".format( EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER + "/genesis.json", @@ -160,7 +162,6 @@ def get_config( "--log.console.verbosity=" + verbosity_level, "--datadir=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, "--port={0}".format(DISCOVERY_PORT_NUM), - "--networkid=" + network_id, "--http.api=eth,erigon,engine,web3,net,debug,trace,txpool,admin", "--http.vhosts=*", "--ws", @@ -170,32 +171,47 @@ def get_config( "--http.addr=0.0.0.0", "--http.corsdomain=*", "--http.port={0}".format(WS_RPC_PORT_NUM), - "--authrpc.jwtsecret=" + constants.JWT_AUTH_PATH, + "--authrpc.jwtsecret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, "--authrpc.addr=0.0.0.0", "--authrpc.port={0}".format(ENGINE_RPC_PORT_NUM), "--authrpc.vhosts=*", "--metrics", "--metrics.addr=0.0.0.0", "--metrics.port={0}".format(METRICS_PORT_NUM), + "--db.size.limit=100GB", ] - if len(existing_el_clients) > 0: + if network == "kurtosis": + if len(existing_el_clients) > 0: + cmd.append( + "--bootnodes=" + + ",".join( + [ + ctx.enode + for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + ] + ) + ) + cmd.append( + "--staticpeers=" + + ",".join( + [ + ctx.enode + for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + ] + ) + ) + elif network not in constants.PUBLIC_NETWORKS: cmd.append( "--bootnodes=" - + ",".join( - [ - ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] - ] + + shared_utils.get_devnet_enodes( + plan, el_cl_genesis_data.files_artifact_uuid ) ) cmd.append( "--staticpeers=" - + ",".join( - [ - ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] - ] + + shared_utils.get_devnet_enodes( + plan, el_cl_genesis_data.files_artifact_uuid ) ) @@ -208,6 +224,7 @@ def get_config( command_arg_str = " && ".join(command_arg) files = { constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, + constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, } if persistent: @@ -236,8 +253,9 @@ def get_config( ) -def new_erigon_launcher(network_id, el_cl_genesis_data): +def new_erigon_launcher(el_cl_genesis_data, jwt_file, network): return struct( - network_id=network_id, el_cl_genesis_data=el_cl_genesis_data, + jwt_file=jwt_file, + network=network, ) diff --git a/src/el/ethereumjs/ethereumjs_launcher.star b/src/el/ethereumjs/ethereumjs_launcher.star index f61a05b0d..55fad2be3 100644 --- a/src/el/ethereumjs/ethereumjs_launcher.star +++ b/src/el/ethereumjs/ethereumjs_launcher.star @@ -6,7 +6,6 @@ el_admin_node_info = import_module("../../el/el_admin_node_info.star") node_metrics = import_module("../../node_metrics_info.star") constants = import_module("../../package_io/constants.star") - RPC_PORT_NUM = 8545 WS_PORT_NUM = 8546 WS_PORT_ENGINE_NUM = 8547 @@ -94,7 +93,10 @@ def launch( cl_client_name = service_name.split("-")[3] config = get_config( + plan, launcher.el_cl_genesis_data, + launcher.jwt_file, + launcher.network, image, service_name, existing_el_clients, @@ -132,7 +134,10 @@ def launch( def get_config( + plan, el_cl_genesis_data, + jwt_file, + network, image, service_name, existing_el_clients, @@ -165,21 +170,28 @@ def get_config( "--wsPort={0}".format(WS_PORT_NUM), "--wsEnginePort={0}".format(WS_PORT_ENGINE_NUM), "--wsEngineAddr=0.0.0.0", - "--jwt-secret=" + constants.JWT_AUTH_PATH, + "--jwt-secret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, "--extIP={0}".format(PRIVATE_IP_ADDRESS_PLACEHOLDER), "--sync=full", "--isSingleNode=true", "--logLevel={0}".format(verbosity_level), ] - - if len(existing_el_clients) > 0: + if network == "kurtosis": + if len(existing_el_clients) > 0: + cmd.append( + "--bootnodes=" + + ",".join( + [ + ctx.enode + for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + ] + ) + ) + elif network not in constants.PUBLIC_NETWORKS: cmd.append( "--bootnodes=" - + ",".join( - [ - ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] - ] + + shared_utils.get_devnet_enodes( + plan, el_cl_genesis_data.files_artifact_uuid ) ) @@ -189,6 +201,7 @@ def get_config( files = { constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, + constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, } if persistent: @@ -217,7 +230,9 @@ def get_config( ) -def new_ethereumjs_launcher(el_cl_genesis_data): +def new_ethereumjs_launcher(el_cl_genesis_data, jwt_file, network): return struct( el_cl_genesis_data=el_cl_genesis_data, + jwt_file=jwt_file, + network=network, ) diff --git a/src/el/geth/geth_launcher.star b/src/el/geth/geth_launcher.star index 56a63762e..f0d9f3c68 100644 --- a/src/el/geth/geth_launcher.star +++ b/src/el/geth/geth_launcher.star @@ -99,8 +99,10 @@ def launch( cl_client_name = service_name.split("-")[3] config = get_config( - launcher.network_id, + plan, launcher.el_cl_genesis_data, + launcher.jwt_file, + launcher.network, image, service_name, existing_el_clients, @@ -144,8 +146,10 @@ def launch( def get_config( - network_id, + plan, el_cl_genesis_data, + jwt_file, + network, image, service_name, existing_el_clients, @@ -211,7 +215,6 @@ def get_config( ), "--verbosity=" + verbosity_level, "--datadir=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, - "--networkid=" + network_id, "--http", "--http.addr=0.0.0.0", "--http.vhosts=*", @@ -230,7 +233,7 @@ def get_config( "--authrpc.port={0}".format(ENGINE_RPC_PORT_NUM), "--authrpc.addr=0.0.0.0", "--authrpc.vhosts=*", - "--authrpc.jwtsecret=" + constants.JWT_AUTH_PATH, + "--authrpc.jwtsecret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, "--syncmode=full", "--rpc.allow-unprotected-txs", "--metrics", @@ -245,14 +248,22 @@ def get_config( if "--ws.api" in arg: cmd[index] = "--ws.api=admin,engine,net,eth,web3,debug,mev,flashbots" - if len(existing_el_clients) > 0: + if network == "kurtosis": + if len(existing_el_clients) > 0: + cmd.append( + "--bootnodes=" + + ",".join( + [ + ctx.enode + for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + ] + ) + ) + elif network not in constants.PUBLIC_NETWORKS: cmd.append( "--bootnodes=" - + ",".join( - [ - ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] - ] + + shared_utils.get_devnet_enodes( + plan, el_cl_genesis_data.files_artifact_uuid ) ) @@ -269,7 +280,8 @@ def get_config( command_str = " && ".join(subcommand_strs) files = { - constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid + constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, + constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, } if persistent: files[EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER] = Directory( @@ -298,15 +310,17 @@ def get_config( def new_geth_launcher( - network_id, el_cl_genesis_data, + jwt_file, + network, final_genesis_timestamp, capella_fork_epoch, electra_fork_epoch=None, ): return struct( - network_id=network_id, el_cl_genesis_data=el_cl_genesis_data, + jwt_file=jwt_file, + network=network, final_genesis_timestamp=final_genesis_timestamp, capella_fork_epoch=capella_fork_epoch, electra_fork_epoch=electra_fork_epoch, diff --git a/src/el/nethermind/nethermind_launcher.star b/src/el/nethermind/nethermind_launcher.star index 993812a1b..3a5d4e09f 100644 --- a/src/el/nethermind/nethermind_launcher.star +++ b/src/el/nethermind/nethermind_launcher.star @@ -88,7 +88,10 @@ def launch( cl_client_name = service_name.split("-")[3] config = get_config( + plan, launcher.el_cl_genesis_data, + launcher.jwt_file, + launcher.network, image, service_name, existing_el_clients, @@ -128,7 +131,10 @@ def launch( def get_config( + plan, el_cl_genesis_data, + jwt_file, + network, image, service_name, existing_el_clients, @@ -161,20 +167,27 @@ def get_config( "--Network.ExternalIp={0}".format(PRIVATE_IP_ADDRESS_PLACEHOLDER), "--Network.DiscoveryPort={0}".format(DISCOVERY_PORT_NUM), "--Network.P2PPort={0}".format(DISCOVERY_PORT_NUM), - "--JsonRpc.JwtSecretFile=" + constants.JWT_AUTH_PATH, + "--JsonRpc.JwtSecretFile=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, "--Network.OnlyStaticPeers=true", "--Metrics.Enabled=true", "--Metrics.ExposePort={0}".format(METRICS_PORT_NUM), ] - - if len(existing_el_clients) > 0: + if network == "kurtosis": + if len(existing_el_clients) > 0: + cmd.append( + "--Network.StaticPeers=" + + ",".join( + [ + ctx.enode + for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + ] + ) + ) + elif network not in constants.PUBLIC_NETWORKS: cmd.append( "--Network.StaticPeers=" - + ",".join( - [ - ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] - ] + + shared_utils.get_devnet_enodes( + plan, el_cl_genesis_data.files_artifact_uuid ) ) @@ -184,6 +197,7 @@ def get_config( files = { constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, + constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, } if persistent: @@ -212,5 +226,7 @@ def get_config( ) -def new_nethermind_launcher(el_cl_genesis_data): - return struct(el_cl_genesis_data=el_cl_genesis_data) +def new_nethermind_launcher(el_cl_genesis_data, jwt_file, network): + return struct( + el_cl_genesis_data=el_cl_genesis_data, jwt_file=jwt_file, network=network + ) diff --git a/src/el/reth/reth_launcher.star b/src/el/reth/reth_launcher.star index 01986c56e..ef969c2a8 100644 --- a/src/el/reth/reth_launcher.star +++ b/src/el/reth/reth_launcher.star @@ -5,7 +5,6 @@ el_admin_node_info = import_module("../../el/el_admin_node_info.star") node_metrics = import_module("../../node_metrics_info.star") constants = import_module("../../package_io/constants.star") - RPC_PORT_NUM = 8545 WS_PORT_NUM = 8546 DISCOVERY_PORT_NUM = 30303 @@ -92,7 +91,10 @@ def launch( cl_client_name = service_name.split("-")[3] config = get_config( + plan, launcher.el_cl_genesis_data, + launcher.jwt_file, + launcher.network, image, service_name, existing_el_clients, @@ -131,7 +133,10 @@ def launch( def get_config( + plan, el_cl_genesis_data, + jwt_file, + network, image, service_name, existing_el_clients, @@ -171,19 +176,26 @@ def get_config( "--ws.origins=*", "--nat=extip:" + PRIVATE_IP_ADDRESS_PLACEHOLDER, "--authrpc.port={0}".format(ENGINE_RPC_PORT_NUM), - "--authrpc.jwtsecret=" + constants.JWT_AUTH_PATH, + "--authrpc.jwtsecret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER, "--authrpc.addr=0.0.0.0", "--metrics=0.0.0.0:{0}".format(METRICS_PORT_NUM), ] - - if len(existing_el_clients) > 0: + if network == "kurtosis": + if len(existing_el_clients) > 0: + cmd.append( + "--bootnodes=" + + ",".join( + [ + ctx.enode + for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] + ] + ) + ) + elif network not in constants.PUBLIC_NETWORKS: cmd.append( "--bootnodes=" - + ",".join( - [ - ctx.enode - for ctx in existing_el_clients[: constants.MAX_ENODE_ENTRIES] - ] + + shared_utils.get_devnet_enodes( + plan, el_cl_genesis_data.files_artifact_uuid ) ) @@ -201,6 +213,7 @@ def get_config( files = { constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, + constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file, } if persistent: @@ -229,7 +242,9 @@ def get_config( ) -def new_reth_launcher(el_cl_genesis_data): +def new_reth_launcher(el_cl_genesis_data, jwt_file, network): return struct( el_cl_genesis_data=el_cl_genesis_data, + jwt_file=jwt_file, + network=network, ) diff --git a/src/package_io/constants.star b/src/package_io/constants.star index ccecc8f3a..9d59af240 100644 --- a/src/package_io/constants.star +++ b/src/package_io/constants.star @@ -38,15 +38,24 @@ GENESIS_VALIDATORS_ROOT_PLACEHOLDER = "GENESIS_VALIDATORS_ROOT_PLACEHOLDER" ARCHIVE_MODE = True -GENESIS_DATA_MOUNTPOINT_ON_CLIENTS = "/data" +GENESIS_DATA_MOUNTPOINT_ON_CLIENTS = "/network-configs" GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER = ( - GENESIS_DATA_MOUNTPOINT_ON_CLIENTS + "/data/custom_config_data" + GENESIS_DATA_MOUNTPOINT_ON_CLIENTS + "/network-configs" ) -JWT_AUTH_PATH = GENESIS_DATA_MOUNTPOINT_ON_CLIENTS + "/data/jwt/jwtsecret" +JWT_MOUNTPOINT_ON_CLIENTS = "/jwt" +JWT_MOUNT_PATH_ON_CONTAINER = JWT_MOUNTPOINT_ON_CLIENTS + "/jwtsecret" + GENESIS_FORK_VERSION = "0x10000038" BELLATRIX_FORK_VERSION = "0x30000038" CAPELLA_FORK_VERSION = "0x40000038" DENEB_FORK_VERSION = "0x50000038" ELECTRA_FORK_VERSION = "0x60000038" + +PUBLIC_NETWORKS = ( + "mainnet", + "goerli", + "sepolia", + "holesky", +) diff --git a/src/package_io/input_parser.star b/src/package_io/input_parser.star index a2101332f..0d397a40a 100644 --- a/src/package_io/input_parser.star +++ b/src/package_io/input_parser.star @@ -64,7 +64,10 @@ def input_parser(plan, input_args): # add default eth2 input params result["mev_type"] = None result["mev_params"] = get_default_mev_params() - result["additional_services"] = DEFAULT_ADDITIONAL_SERVICES + if result["network_params"]["network"] == "kurtosis": + result["additional_services"] = DEFAULT_ADDITIONAL_SERVICES + else: + result["additional_services"] = [] result["grafana_additional_dashboards"] = [] result["tx_spammer_params"] = get_default_tx_spammer_params() result["custom_flood_params"] = get_default_custom_flood_params() @@ -181,6 +184,7 @@ def input_parser(plan, input_args): capella_fork_epoch=result["network_params"]["capella_fork_epoch"], deneb_fork_epoch=result["network_params"]["deneb_fork_epoch"], electra_fork_epoch=result["network_params"]["electra_fork_epoch"], + network=result["network_params"]["network"], ), mev_params=struct( mev_relay_image=result["mev_params"]["mev_relay_image"], @@ -346,10 +350,14 @@ def parse_network_params(input_args): "deposit_contract_address is empty or spaces it needs to be of non zero length" ) - if result["network_params"]["preregistered_validator_keys_mnemonic"].strip() == "": - fail( - "preregistered_validator_keys_mnemonic is empty or spaces it needs to be of non zero length" - ) + if result["network_params"]["network"] == "kurtosis": + if ( + result["network_params"]["preregistered_validator_keys_mnemonic"].strip() + == "" + ): + fail( + "preregistered_validator_keys_mnemonic is empty or spaces it needs to be of non zero length" + ) if result["network_params"]["seconds_per_slot"] == 0: fail("seconds_per_slot is 0 needs to be > 0 ") @@ -367,12 +375,17 @@ def parse_network_params(input_args): ): fail("electra can only happen with capella genesis not bellatrix") - if MIN_VALIDATORS > actual_num_validators: - fail( - "We require at least {0} validators but got {1}".format( - MIN_VALIDATORS, actual_num_validators + if result["network_params"]["network"] == "kurtosis": + if MIN_VALIDATORS > actual_num_validators: + fail( + "We require at least {0} validators but got {1}".format( + MIN_VALIDATORS, actual_num_validators + ) ) - ) + else: + # Don't allow validators on non-kurtosis networks + for participant in result["participants"]: + participant["validator_count"] = 0 return result @@ -423,6 +436,7 @@ def default_network_params(): "capella_fork_epoch": 0, "deneb_fork_epoch": 500, "electra_fork_epoch": None, + "network": "kurtosis", } diff --git a/src/participant_network.star b/src/participant_network.star index 2f318aec1..61d3335e7 100644 --- a/src/participant_network.star +++ b/src/participant_network.star @@ -5,6 +5,9 @@ validator_keystores = import_module( el_cl_genesis_data_generator = import_module( "./prelaunch_data_generator/el_cl_genesis/el_cl_genesis_generator.star" ) +el_cl_genesis_data = import_module( + "./prelaunch_data_generator/el_cl_genesis/el_cl_genesis_data.star" +) shared_utils = import_module("./shared_utils/shared_utils.star") static_files = import_module("./static_files/static_files.star") @@ -56,96 +59,124 @@ def launch_participant_network( participants, network_params, global_log_level, + jwt_file, persistent, parallel_keystore_generation=False, ): num_participants = len(participants) + if network_params.network == "kurtosis": + plan.print("Generating cl validator key stores") + validator_data = None + if not parallel_keystore_generation: + validator_data = validator_keystores.generate_validator_keystores( + plan, network_params.preregistered_validator_keys_mnemonic, participants + ) + else: + validator_data = ( + validator_keystores.generate_valdiator_keystores_in_parallel( + plan, + network_params.preregistered_validator_keys_mnemonic, + participants, + ) + ) - plan.print("Generating cl validator key stores") - validator_data = None - if not parallel_keystore_generation: - validator_data = validator_keystores.generate_validator_keystores( - plan, network_params.preregistered_validator_keys_mnemonic, participants - ) - else: - validator_data = validator_keystores.generate_valdiator_keystores_in_parallel( - plan, network_params.preregistered_validator_keys_mnemonic, participants + plan.print(json.indent(json.encode(validator_data))) + + # We need to send the same genesis time to both the EL and the CL to ensure that timestamp based forking works as expected + final_genesis_timestamp = get_final_genesis_timestamp( + plan, + CL_GENESIS_DATA_GENERATION_TIME + num_participants * CL_NODE_STARTUP_TIME, ) - plan.print(json.indent(json.encode(validator_data))) + # if preregistered validator count is 0 (default) then calculate the total number of validators from the participants + total_number_of_validator_keys = network_params.preregistered_validator_count - # We need to send the same genesis time to both the EL and the CL to ensure that timestamp based forking works as expected - final_genesis_timestamp = get_final_genesis_timestamp( - plan, CL_GENESIS_DATA_GENERATION_TIME + num_participants * CL_NODE_STARTUP_TIME - ) + if network_params.preregistered_validator_count == 0: + for participant in participants: + total_number_of_validator_keys += participant.validator_count - # if preregistered validator count is 0 (default) then calculate the total number of validators from the participants - total_number_of_validator_keys = network_params.preregistered_validator_count - - if network_params.preregistered_validator_count == 0: - for participant in participants: - total_number_of_validator_keys += participant.validator_count - - plan.print("Generating EL CL data") - # we are running bellatrix genesis (deprecated) - will be removed in the future - if ( - network_params.capella_fork_epoch > 0 - and network_params.electra_fork_epoch == None - ): - ethereum_genesis_generator_image = ( - "ethpandaops/ethereum-genesis-generator:1.3.15" - ) - # we are running capella genesis - default behavior - elif ( - network_params.capella_fork_epoch == 0 - and network_params.electra_fork_epoch == None - ): - ethereum_genesis_generator_image = ( - "ethpandaops/ethereum-genesis-generator:2.0.8" - ) - # we are running electra - experimental - elif network_params.electra_fork_epoch != None: - if network_params.electra_fork_epoch == 0: + plan.print("Generating EL CL data") + # we are running bellatrix genesis (deprecated) - will be removed in the future + if ( + network_params.capella_fork_epoch > 0 + and network_params.electra_fork_epoch == None + ): ethereum_genesis_generator_image = ( - "ethpandaops/ethereum-genesis-generator:4.0.0-rc.4" + "ethpandaops/ethereum-genesis-generator:1.3.15" ) - else: + # we are running capella genesis - default behavior + elif ( + network_params.capella_fork_epoch == 0 + and network_params.electra_fork_epoch == None + ): ethereum_genesis_generator_image = ( - "ethpandaops/ethereum-genesis-generator:3.0.0-rc.18" + "ethpandaops/ethereum-genesis-generator:2.0.8" + ) + # we are running electra - experimental + elif network_params.electra_fork_epoch != None: + if network_params.electra_fork_epoch == 0: + ethereum_genesis_generator_image = ( + "ethpandaops/ethereum-genesis-generator:4.0.0-rc.3" + ) + else: + ethereum_genesis_generator_image = ( + "ethpandaops/ethereum-genesis-generator:3.0.0-rc.18" + ) + else: + fail( + "Unsupported fork epoch configuration, need to define either capella_fork_epoch, deneb_fork_epoch or electra_fork_epoch" ) - else: - fail( - "Unsupported fork epoch configuration, need to define either capella_fork_epoch, deneb_fork_epoch or electra_fork_epoch" - ) - el_cl_genesis_config_template = read_file( - static_files.EL_CL_GENESIS_GENERATION_CONFIG_TEMPLATE_FILEPATH - ) + el_cl_genesis_config_template = read_file( + static_files.EL_CL_GENESIS_GENERATION_CONFIG_TEMPLATE_FILEPATH + ) - el_cl_data = el_cl_genesis_data_generator.generate_el_cl_genesis_data( - plan, - ethereum_genesis_generator_image, - el_cl_genesis_config_template, - final_genesis_timestamp, - network_params.network_id, - network_params.deposit_contract_address, - network_params.seconds_per_slot, - network_params.preregistered_validator_keys_mnemonic, - total_number_of_validator_keys, - network_params.genesis_delay, - network_params.max_churn, - network_params.ejection_balance, - network_params.eth1_follow_distance, - network_params.capella_fork_epoch, - network_params.deneb_fork_epoch, - network_params.electra_fork_epoch, - ) + el_cl_data = el_cl_genesis_data_generator.generate_el_cl_genesis_data( + plan, + ethereum_genesis_generator_image, + el_cl_genesis_config_template, + final_genesis_timestamp, + network_params.network_id, + network_params.deposit_contract_address, + network_params.seconds_per_slot, + network_params.preregistered_validator_keys_mnemonic, + total_number_of_validator_keys, + network_params.genesis_delay, + network_params.max_churn, + network_params.ejection_balance, + network_params.eth1_follow_distance, + network_params.capella_fork_epoch, + network_params.deneb_fork_epoch, + network_params.electra_fork_epoch, + ) + else: + # split up the name from dencun-devnet-12 to dencun and devnet-12 + devnet_name = network_params.network.split("-")[0] + devnet_number = network_params.network.split("-")[-1] + el_cl_genesis_uuid = plan.upload_files( + src="github.com/ethpandaops/{0}-devnets/network-configs/devnet-{1}".format( + devnet_name, devnet_number + ), + name="el_cl_genesis", + ) + el_cl_genesis_data_uuid = plan.run_sh( + run="mkdir -p /network-configs/ && mv /opt/* /network-configs/", + store=[StoreSpec(src="/network-configs/", name="el_cl_genesis_data")], + files={"/opt": el_cl_genesis_uuid}, + ) + el_cl_data = el_cl_genesis_data.new_el_cl_genesis_data( + el_cl_genesis_data_uuid.files_artifacts[0], + "0", + ) + final_genesis_timestamp = 0 + validator_data = None el_launchers = { constants.EL_CLIENT_TYPE.geth: { "launcher": geth.new_geth_launcher( - network_params.network_id, el_cl_data, + jwt_file, + network_params.network, final_genesis_timestamp, network_params.capella_fork_epoch, network_params.electra_fork_epoch, @@ -154,8 +185,9 @@ def launch_participant_network( }, constants.EL_CLIENT_TYPE.gethbuilder: { "launcher": geth.new_geth_launcher( - network_params.network_id, el_cl_data, + jwt_file, + network_params.network, final_genesis_timestamp, network_params.capella_fork_epoch, network_params.electra_fork_epoch, @@ -163,25 +195,43 @@ def launch_participant_network( "launch_method": geth.launch, }, constants.EL_CLIENT_TYPE.besu: { - "launcher": besu.new_besu_launcher(network_params.network_id, el_cl_data), + "launcher": besu.new_besu_launcher( + el_cl_data, + jwt_file, + network_params.network, + ), "launch_method": besu.launch, }, constants.EL_CLIENT_TYPE.erigon: { "launcher": erigon.new_erigon_launcher( - network_params.network_id, el_cl_data + el_cl_data, + jwt_file, + network_params.network, ), "launch_method": erigon.launch, }, constants.EL_CLIENT_TYPE.nethermind: { - "launcher": nethermind.new_nethermind_launcher(el_cl_data), + "launcher": nethermind.new_nethermind_launcher( + el_cl_data, + jwt_file, + network_params.network, + ), "launch_method": nethermind.launch, }, constants.EL_CLIENT_TYPE.reth: { - "launcher": reth.new_reth_launcher(el_cl_data), + "launcher": reth.new_reth_launcher( + el_cl_data, + jwt_file, + network_params.network, + ), "launch_method": reth.launch, }, constants.EL_CLIENT_TYPE.ethereumjs: { - "launcher": ethereumjs.new_ethereumjs_launcher(el_cl_data), + "launcher": ethereumjs.new_ethereumjs_launcher( + el_cl_data, + jwt_file, + network_params.network, + ), "launch_method": ethereumjs.launch, }, } @@ -239,30 +289,51 @@ def launch_participant_network( plan.print("Successfully added {0} EL participants".format(num_participants)) plan.print("Launching CL network") - + prysm_password_relative_filepath = ( + validator_data.prysm_password_relative_filepath + if network_params.network == "kurtosis" + else None + ) + prysm_password_artifact_uuid = ( + validator_data.prysm_password_artifact_uuid + if network_params.network == "kurtosis" + else None + ) cl_launchers = { constants.CL_CLIENT_TYPE.lighthouse: { - "launcher": lighthouse.new_lighthouse_launcher(el_cl_data), + "launcher": lighthouse.new_lighthouse_launcher( + el_cl_data, jwt_file, network_params.network + ), "launch_method": lighthouse.launch, }, constants.CL_CLIENT_TYPE.lodestar: { - "launcher": lodestar.new_lodestar_launcher(el_cl_data), + "launcher": lodestar.new_lodestar_launcher( + el_cl_data, jwt_file, network_params.network + ), "launch_method": lodestar.launch, }, constants.CL_CLIENT_TYPE.nimbus: { - "launcher": nimbus.new_nimbus_launcher(el_cl_data), + "launcher": nimbus.new_nimbus_launcher( + el_cl_data, jwt_file, network_params.network + ), "launch_method": nimbus.launch, }, constants.CL_CLIENT_TYPE.prysm: { "launcher": prysm.new_prysm_launcher( el_cl_data, - validator_data.prysm_password_relative_filepath, - validator_data.prysm_password_artifact_uuid, + jwt_file, + network_params.network, + prysm_password_relative_filepath, + prysm_password_artifact_uuid, ), "launch_method": prysm.launch, }, constants.CL_CLIENT_TYPE.teku: { - "launcher": teku.new_teku_launcher(el_cl_data), + "launcher": teku.new_teku_launcher( + el_cl_data, + jwt_file, + network_params.network, + ), "launch_method": teku.launch, }, } @@ -270,7 +341,11 @@ def launch_participant_network( all_snooper_engine_contexts = [] all_cl_client_contexts = [] all_ethereum_metrics_exporter_contexts = [] - preregistered_validator_keys_for_nodes = validator_data.per_node_keystores + preregistered_validator_keys_for_nodes = ( + validator_data.per_node_keystores + if network_params.network == "kurtosis" + else None + ) for index, participant in enumerate(participants): cl_client_type = participant.cl_client_type diff --git a/src/prelaunch_data_generator/el_cl_genesis/el_cl_genesis_generator.star b/src/prelaunch_data_generator/el_cl_genesis/el_cl_genesis_generator.star index ac839be0d..d4093c146 100644 --- a/src/prelaunch_data_generator/el_cl_genesis/el_cl_genesis_generator.star +++ b/src/prelaunch_data_generator/el_cl_genesis/el_cl_genesis_generator.star @@ -56,16 +56,22 @@ def generate_el_cl_genesis_data( ) genesis = plan.run_sh( - run="cp /opt/values.env /config/values.env && ./entrypoint.sh all", + run="cp /opt/values.env /config/values.env && ./entrypoint.sh all && mkdir /network-configs && mv /data/custom_config_data/* /network-configs/", image=image, files={GENESIS_VALUES_PATH: genesis_generation_config_artifact_name}, - store=[StoreSpec(src="/data", name="el-cl-genesis-data")], + store=[ + StoreSpec(src="/network-configs/", name="el_cl_genesis_data"), + StoreSpec( + src="/network-configs/genesis_validators_root.txt", + name="genesis_validators_root", + ), + ], wait=None, ) genesis_validators_root = plan.run_sh( - run="cat /data/data/custom_config_data/genesis_validators_root.txt", - files={"/data": genesis.files_artifacts[0]}, + run="cat /data/genesis_validators_root.txt", + files={"/data": genesis.files_artifacts[1]}, wait=None, ) diff --git a/src/shared_utils/shared_utils.star b/src/shared_utils/shared_utils.star index e49339872..656bea513 100644 --- a/src/shared_utils/shared_utils.star +++ b/src/shared_utils/shared_utils.star @@ -1,3 +1,5 @@ +constants = import_module("../package_io/constants.star") + TCP_PROTOCOL = "TCP" UDP_PROTOCOL = "UDP" HTTP_APPLICATION_PROTOCOL = "http" @@ -71,3 +73,51 @@ def label_maker(client, client_type, image, connected_client, extra_labels): } labels.update(extra_labels) # Add extra_labels to the labels dictionary return labels + + +def get_devnet_enodes(plan, filename): + enode_list = plan.run_python( + files={constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: filename}, + wait=None, + run=""" +with open("/network-configs/network-configs/bootnode.txt") as bootnode_file: + bootnodes = [] + for line in bootnode_file: + line = line.strip() + bootnodes.append(line) +print(",".join(bootnodes), end="") + """, + ) + return enode_list.output + + +def get_devnet_enrs_list(plan, filename): + enr_list = plan.run_python( + files={constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: filename}, + wait=None, + run=""" +with open("/network-configs/network-configs/bootstrap_nodes.txt") as bootnode_file: + bootnodes = [] + for line in bootnode_file: + line = line.strip() + bootnodes.append(line) +print(",".join(bootnodes), end="") + """, + ) + return enr_list.output + + +# Prysm and Nimbus needs to have the enrs in a list format +# Can't figure out how to pass each item as a list, as I can't return an array from the starlark function +# So for now I'm just returning the last item in the list +def get_devnet_enr(plan, filename): + enr_items = plan.run_python( + files={constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: filename}, + wait=None, + run=""" +with open("/network-configs/network-configs/bootstrap_nodes.txt") as bootnode_file: + last_enr = bootnode_file.read().splitlines()[-1] + print(last_enr, end="") + """, + ) + return enr_items.output diff --git a/src/static_files/static_files.star b/src/static_files/static_files.star index 1050edf55..0c0a4ca28 100644 --- a/src/static_files/static_files.star +++ b/src/static_files/static_files.star @@ -51,3 +51,5 @@ CL_GENESIS_GENERATION_CONFIG_TEMPLATE_FILEPATH = ( CL_GENESIS_GENERATION_MNEMONICS_TEMPLATE_FILEPATH = ( CL_GENESIS_GENERATION_CONFIG_DIRPATH + "/mnemonics.yaml.tmpl" ) + +JWT_PATH_FILEPATH = STATIC_FILES_DIRPATH + "/jwt/jwtsecret" diff --git a/static_files/dora-config/config.yaml.tmpl b/static_files/dora-config/config.yaml.tmpl index 60e605bb8..d272102fd 100644 --- a/static_files/dora-config/config.yaml.tmpl +++ b/static_files/dora-config/config.yaml.tmpl @@ -5,7 +5,7 @@ logging: # Chain network configuration chain: name: "kurtosis-testnet" - configPath: "/data/data/custom_config_data/config.yaml" + configPath: "/network-configs/network-configs/config.yaml" displayName: "Kurtosis Testnet" # HTTP Server configuration diff --git a/static_files/jwt/jwtsecret b/static_files/jwt/jwtsecret new file mode 100644 index 000000000..8b60cacec --- /dev/null +++ b/static_files/jwt/jwtsecret @@ -0,0 +1 @@ +0xdc49981516e8e72b401a63e6405495a32dafc3939b5d6d83cc319ac0388bca1b \ No newline at end of file