From 6f92f49db97899510162a45fcc498e9d92483fbe Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Fri, 28 Nov 2025 12:04:45 +0100 Subject: [PATCH 1/7] feat: add skip_start --- .github/tests/skip.yaml | 17 +++++++ README.md | 7 +++ src/cl/grandine/grandine_launcher.star | 51 ++++++++++++-------- src/cl/lighthouse/lighthouse_launcher.star | 54 +++++++++++++-------- src/cl/lodestar/lodestar_launcher.star | 54 ++++++++++++--------- src/cl/nimbus/nimbus_launcher.star | 51 ++++++++++++-------- src/cl/prysm/prysm_launcher.star | 55 +++++++++++++--------- src/cl/teku/teku_launcher.star | 51 ++++++++++++-------- src/package_io/input_parser.star | 2 + src/package_io/sanity_check.star | 1 + src/participant_network.star | 11 +++++ src/shared_utils/shared_utils.star | 12 +++-- 12 files changed, 243 insertions(+), 123 deletions(-) create mode 100644 .github/tests/skip.yaml diff --git a/.github/tests/skip.yaml b/.github/tests/skip.yaml new file mode 100644 index 000000000..96248d8d3 --- /dev/null +++ b/.github/tests/skip.yaml @@ -0,0 +1,17 @@ +participants: + - el_type: geth + cl_type: lighthouse + cl_extra_params: ["--target-peers=0"] + + - el_type: geth + cl_type: prysm + checkpoint_sync_enabled: true + skip_start: true + validator_count: 1 +network_params: + preset: minimal + seconds_per_slot: 2 +additional_services: + - dora + +checkpoint_sync_url: "http://cl-1-lighthouse-geth:4000" diff --git a/README.md b/README.md index df7832853..52a034ee3 100644 --- a/README.md +++ b/README.md @@ -494,6 +494,13 @@ participants: # Defaults to null (uses global checkpoint_sync_enabled setting) checkpoint_sync_enabled: null + # If set to true, the beacon node will be created and then immediately stopped. + # No health checks are performed during creation (ready_conditions are disabled). + # The service can be started later using: kurtosis service start + # This is useful for testing or when you want to manually control when the beacon node starts. + # Defaults to false + skip_start: false + # Participants matrix creates a participant for each combination of EL, CL and VC clients # Each EL/CL/VC item can provide the same parameters as a standard participant participants_matrix: {} diff --git a/src/cl/grandine/grandine_launcher.star b/src/cl/grandine/grandine_launcher.star index ba5493060..736eaea32 100644 --- a/src/cl/grandine/grandine_launcher.star +++ b/src/cl/grandine/grandine_launcher.star @@ -190,7 +190,11 @@ def get_beacon_config( constants.HTTP_PORT_ID: BEACON_HTTP_PORT_NUM, constants.METRICS_PORT_ID: BEACON_METRICS_PORT_NUM, } - used_ports = shared_utils.get_port_specs(used_port_assignments) + # Disable port checks if skip_start is enabled + if participant.skip_start: + used_ports = shared_utils.get_port_specs(used_port_assignments, wait=None) + else: + used_ports = shared_utils.get_port_specs(used_port_assignments) cmd = [ GRANDINE_ENTRYPOINT_COMMAND, @@ -347,9 +351,6 @@ def get_beacon_config( "files": files, "env_vars": participant.cl_extra_env_vars, "private_ip_address_placeholder": constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - "ready_conditions": cl_node_ready_conditions.get_ready_conditions( - constants.HTTP_PORT_ID - ), "labels": shared_utils.label_maker( client=constants.CL_TYPE.grandine, client_type=constants.CLIENT_TYPES.cl, @@ -364,6 +365,12 @@ def get_beacon_config( "user": User(uid=0, gid=0), } + # Only add ready_conditions if not skipping start + if not participant.skip_start: + config_args["ready_conditions"] = cl_node_ready_conditions.get_ready_conditions( + constants.HTTP_PORT_ID + ) + if int(participant.cl_min_cpu) > 0: config_args["min_cpu"] = int(participant.cl_min_cpu) if int(participant.cl_max_cpu) > 0: @@ -390,21 +397,27 @@ def get_cl_context( beacon_metrics_port = service.ports[constants.METRICS_PORT_ID] beacon_metrics_url = "{0}:{1}".format(service.name, beacon_metrics_port.number) - beacon_node_identity_recipe = GetHttpRequestRecipe( - endpoint="/eth/v1/node/identity", - port_id=constants.HTTP_PORT_ID, - extract={ - "enr": ".data.enr", - "multiaddr": ".data.p2p_addresses[0]", - "peer_id": ".data.peer_id", - }, - ) - response = plan.request( - recipe=beacon_node_identity_recipe, service_name=service_name - ) - beacon_node_enr = response["extract.enr"] - beacon_multiaddr = response["extract.multiaddr"] - beacon_peer_id = response["extract.peer_id"] + # Skip HTTP requests if skip_start is enabled (service won't be running) + if participant.skip_start: + beacon_node_enr = "" + beacon_multiaddr = "" + beacon_peer_id = "" + else: + beacon_node_identity_recipe = GetHttpRequestRecipe( + endpoint="/eth/v1/node/identity", + port_id=constants.HTTP_PORT_ID, + extract={ + "enr": ".data.enr", + "multiaddr": ".data.p2p_addresses[0]", + "peer_id": ".data.peer_id", + }, + ) + response = plan.request( + recipe=beacon_node_identity_recipe, service_name=service_name + ) + beacon_node_enr = response["extract.enr"] + beacon_multiaddr = response["extract.multiaddr"] + beacon_peer_id = response["extract.peer_id"] beacon_node_metrics_info = node_metrics.new_node_metrics_info( service_name, BEACON_METRICS_PATH, beacon_metrics_url diff --git a/src/cl/lighthouse/lighthouse_launcher.star b/src/cl/lighthouse/lighthouse_launcher.star index 5ccf0f59a..4ba0c8ded 100644 --- a/src/cl/lighthouse/lighthouse_launcher.star +++ b/src/cl/lighthouse/lighthouse_launcher.star @@ -180,7 +180,11 @@ def get_beacon_config( constants.HTTP_PORT_ID: BEACON_HTTP_PORT_NUM, constants.METRICS_PORT_ID: BEACON_METRICS_PORT_NUM, } - used_ports = shared_utils.get_port_specs(used_port_assignments) + # Disable port checks if skip_start is enabled + if participant.skip_start: + used_ports = shared_utils.get_port_specs(used_port_assignments, wait=None) + else: + used_ports = shared_utils.get_port_specs(used_port_assignments) cmd = [ LIGHTHOUSE_ENTRYPOINT_COMMAND, "beacon_node", @@ -309,6 +313,7 @@ def get_beacon_config( env_vars = {RUST_BACKTRACE_ENVVAR_NAME: RUST_FULL_BACKTRACE_KEYWORD} env_vars.update(participant.cl_extra_env_vars) + config_args = { "image": participant.cl_image, "ports": used_ports, @@ -318,9 +323,6 @@ def get_beacon_config( "files": files, "env_vars": env_vars, "private_ip_address_placeholder": constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - "ready_conditions": cl_node_ready_conditions.get_ready_conditions( - constants.HTTP_PORT_ID - ), "labels": shared_utils.label_maker( client=constants.CL_TYPE.lighthouse, client_type=constants.CLIENT_TYPES.cl, @@ -334,6 +336,12 @@ def get_beacon_config( "node_selectors": node_selectors, } + # Only add ready_conditions if not skipping start + if not participant.skip_start: + config_args["ready_conditions"] = cl_node_ready_conditions.get_ready_conditions( + constants.HTTP_PORT_ID + ) + if int(participant.cl_min_cpu) > 0: config_args["min_cpu"] = int(participant.cl_min_cpu) if int(participant.cl_max_cpu) > 0: @@ -357,22 +365,28 @@ def get_cl_context( beacon_http_port = service.ports[constants.HTTP_PORT_ID] beacon_http_url = "http://{0}:{1}".format(service.name, beacon_http_port.number) - # TODO(old) add validator availability using the validator API: https://ethereum.github.io/beacon-APIs/?urls.primaryName=v1#/ValidatorRequiredApi | from eth2-merge-kurtosis-module - beacon_node_identity_recipe = GetHttpRequestRecipe( - endpoint="/eth/v1/node/identity", - port_id=constants.HTTP_PORT_ID, - extract={ - "enr": ".data.enr", - "multiaddr": ".data.p2p_addresses[0]", - "peer_id": ".data.peer_id", - }, - ) - response = plan.request( - recipe=beacon_node_identity_recipe, service_name=service_name - ) - beacon_node_enr = response["extract.enr"] - beacon_multiaddr = response["extract.multiaddr"] - beacon_peer_id = response["extract.peer_id"] + # Skip HTTP requests if skip_start is enabled (service won't be running) + if participant.skip_start: + beacon_node_enr = "" + beacon_multiaddr = "" + beacon_peer_id = "" + else: + # TODO(old) add validator availability using the validator API: https://ethereum.github.io/beacon-APIs/?urls.primaryName=v1#/ValidatorRequiredApi | from eth2-merge-kurtosis-module + beacon_node_identity_recipe = GetHttpRequestRecipe( + endpoint="/eth/v1/node/identity", + port_id=constants.HTTP_PORT_ID, + extract={ + "enr": ".data.enr", + "multiaddr": ".data.p2p_addresses[0]", + "peer_id": ".data.peer_id", + }, + ) + response = plan.request( + recipe=beacon_node_identity_recipe, service_name=service_name + ) + beacon_node_enr = response["extract.enr"] + beacon_multiaddr = response["extract.multiaddr"] + beacon_peer_id = response["extract.peer_id"] beacon_metrics_port = service.ports[constants.METRICS_PORT_ID] beacon_metrics_url = "{0}:{1}".format(service.name, beacon_metrics_port.number) diff --git a/src/cl/lodestar/lodestar_launcher.star b/src/cl/lodestar/lodestar_launcher.star index f2d421803..93852bd67 100644 --- a/src/cl/lodestar/lodestar_launcher.star +++ b/src/cl/lodestar/lodestar_launcher.star @@ -161,7 +161,11 @@ def get_beacon_config( constants.HTTP_PORT_ID: BEACON_HTTP_PORT_NUM, constants.METRICS_PORT_ID: BEACON_METRICS_PORT_NUM, } - used_ports = shared_utils.get_port_specs(used_port_assignments) + # Disable port checks if skip_start is enabled + if participant.skip_start: + used_ports = shared_utils.get_port_specs(used_port_assignments, wait=None) + else: + used_ports = shared_utils.get_port_specs(used_port_assignments) cmd = [ LODESTAR_ENTRYPOINT_COMMAND, @@ -298,9 +302,6 @@ def get_beacon_config( "files": files, "env_vars": env_vars, "private_ip_address_placeholder": constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - "ready_conditions": cl_node_ready_conditions.get_ready_conditions( - constants.HTTP_PORT_ID - ), "labels": shared_utils.label_maker( client=constants.CL_TYPE.lodestar, client_type=constants.CLIENT_TYPES.cl, @@ -314,6 +315,12 @@ def get_beacon_config( "node_selectors": node_selectors, } + # Only add ready_conditions if not skipping start + if not participant.skip_start: + config_args["ready_conditions"] = cl_node_ready_conditions.get_ready_conditions( + constants.HTTP_PORT_ID + ) + if int(participant.cl_min_cpu) > 0: config_args["min_cpu"] = int(participant.cl_min_cpu) if int(participant.cl_max_cpu) > 0: @@ -338,23 +345,28 @@ def get_cl_context( beacon_http_url = "http://{0}:{1}".format(service.name, beacon_http_port.number) - # TODO(old) add validator availability using the validator API: https://ethereum.github.io/beacon-APIs/?urls.primaryName=v1#/ValidatorRequiredApi | from eth2-merge-kurtosis-module - - beacon_node_identity_recipe = GetHttpRequestRecipe( - endpoint="/eth/v1/node/identity", - port_id=constants.HTTP_PORT_ID, - extract={ - "enr": ".data.enr", - "multiaddr": ".data.p2p_addresses[-1]", - "peer_id": ".data.peer_id", - }, - ) - response = plan.request( - recipe=beacon_node_identity_recipe, service_name=service_name - ) - beacon_node_enr = response["extract.enr"] - beacon_multiaddr = response["extract.multiaddr"] - beacon_peer_id = response["extract.peer_id"] + # Skip HTTP requests if skip_start is enabled (service won't be running) + if participant.skip_start: + beacon_node_enr = "" + beacon_multiaddr = "" + beacon_peer_id = "" + else: + # TODO(old) add validator availability using the validator API: https://ethereum.github.io/beacon-APIs/?urls.primaryName=v1#/ValidatorRequiredApi | from eth2-merge-kurtosis-module + beacon_node_identity_recipe = GetHttpRequestRecipe( + endpoint="/eth/v1/node/identity", + port_id=constants.HTTP_PORT_ID, + extract={ + "enr": ".data.enr", + "multiaddr": ".data.p2p_addresses[-1]", + "peer_id": ".data.peer_id", + }, + ) + response = plan.request( + recipe=beacon_node_identity_recipe, service_name=service_name + ) + beacon_node_enr = response["extract.enr"] + beacon_multiaddr = response["extract.multiaddr"] + beacon_peer_id = response["extract.peer_id"] beacon_metrics_port = service.ports[constants.METRICS_PORT_ID] beacon_metrics_url = "{0}:{1}".format(service.name, beacon_metrics_port.number) diff --git a/src/cl/nimbus/nimbus_launcher.star b/src/cl/nimbus/nimbus_launcher.star index 1547f16d7..5d2b00d55 100644 --- a/src/cl/nimbus/nimbus_launcher.star +++ b/src/cl/nimbus/nimbus_launcher.star @@ -189,7 +189,11 @@ def get_beacon_config( constants.HTTP_PORT_ID: BEACON_HTTP_PORT_NUM, constants.METRICS_PORT_ID: BEACON_METRICS_PORT_NUM, } - used_ports = shared_utils.get_port_specs(used_port_assignments) + # Disable port checks if skip_start is enabled + if participant.skip_start: + used_ports = shared_utils.get_port_specs(used_port_assignments, wait=None) + else: + used_ports = shared_utils.get_port_specs(used_port_assignments) nimbus_checkpoint_sync_subtask_str = "{0} trustedNodeSync --data-dir={1} --trusted-node-url={2} --network={3} --backfill=false".format( BEACON_NODE_ENTRYPOINT, @@ -348,9 +352,6 @@ def get_beacon_config( "files": files, "env_vars": participant.cl_extra_env_vars, "private_ip_address_placeholder": constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - "ready_conditions": cl_node_ready_conditions.get_ready_conditions( - constants.HTTP_PORT_ID - ), "labels": shared_utils.label_maker( client=constants.CL_TYPE.nimbus, client_type=constants.CLIENT_TYPES.cl, @@ -365,6 +366,12 @@ def get_beacon_config( "user": User(uid=0, gid=0), } + # Only add ready_conditions if not skipping start + if not participant.skip_start: + config_args["ready_conditions"] = cl_node_ready_conditions.get_ready_conditions( + constants.HTTP_PORT_ID + ) + if int(participant.cl_min_cpu) > 0: config_args["min_cpu"] = int(participant.cl_min_cpu) if int(participant.cl_max_cpu) > 0: @@ -390,21 +397,27 @@ def get_cl_context( beacon_http_url = "http://{0}:{1}".format(service.name, beacon_http_port.number) beacon_metrics_url = "{0}:{1}".format(service.name, beacon_metrics_port.number) - beacon_node_identity_recipe = GetHttpRequestRecipe( - endpoint="/eth/v1/node/identity", - port_id=constants.HTTP_PORT_ID, - extract={ - "enr": ".data.enr", - "multiaddr": ".data.p2p_addresses[0]", - "peer_id": ".data.peer_id", - }, - ) - response = plan.request( - recipe=beacon_node_identity_recipe, service_name=service_name - ) - beacon_node_enr = response["extract.enr"] - beacon_multiaddr = response["extract.multiaddr"] - beacon_peer_id = response["extract.peer_id"] + # Skip HTTP requests if skip_start is enabled (service won't be running) + if participant.skip_start: + beacon_node_enr = "" + beacon_multiaddr = "" + beacon_peer_id = "" + else: + beacon_node_identity_recipe = GetHttpRequestRecipe( + endpoint="/eth/v1/node/identity", + port_id=constants.HTTP_PORT_ID, + extract={ + "enr": ".data.enr", + "multiaddr": ".data.p2p_addresses[0]", + "peer_id": ".data.peer_id", + }, + ) + response = plan.request( + recipe=beacon_node_identity_recipe, service_name=service_name + ) + beacon_node_enr = response["extract.enr"] + beacon_multiaddr = response["extract.multiaddr"] + beacon_peer_id = response["extract.peer_id"] nimbus_node_metrics_info = node_metrics.new_node_metrics_info( service_name, BEACON_METRICS_PATH, beacon_metrics_url diff --git a/src/cl/prysm/prysm_launcher.star b/src/cl/prysm/prysm_launcher.star index c3f929e3c..3c9e999e6 100644 --- a/src/cl/prysm/prysm_launcher.star +++ b/src/cl/prysm/prysm_launcher.star @@ -188,7 +188,11 @@ def get_beacon_config( constants.RPC_PORT_ID: RPC_PORT_NUM, constants.PROFILING_PORT_ID: PROFILING_PORT_NUM, } - used_ports = shared_utils.get_port_specs(used_port_assignments) + # Disable port checks if skip_start is enabled + if participant.skip_start: + used_ports = shared_utils.get_port_specs(used_port_assignments, wait=None) + else: + used_ports = shared_utils.get_port_specs(used_port_assignments) cmd = [ PRYSM_ENTRYPOINT_COMMAND, @@ -324,9 +328,6 @@ def get_beacon_config( "files": files, "env_vars": participant.cl_extra_env_vars, "private_ip_address_placeholder": constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - "ready_conditions": cl_node_ready_conditions.get_ready_conditions( - constants.HTTP_PORT_ID - ), "labels": shared_utils.label_maker( client=constants.CL_TYPE.prysm, client_type=constants.CLIENT_TYPES.cl, @@ -341,6 +342,12 @@ def get_beacon_config( "tty_enabled": True, } + # Only add ready_conditions if not skipping start (port checks are already disabled via wait="disable") + if not participant.skip_start: + config_args["ready_conditions"] = cl_node_ready_conditions.get_ready_conditions( + constants.HTTP_PORT_ID + ) + if int(participant.cl_min_cpu) > 0: config_args["min_cpu"] = int(participant.cl_min_cpu) if int(participant.cl_max_cpu) > 0: @@ -366,23 +373,29 @@ def get_cl_context( beacon_http_url = "http://{0}:{1}".format(service.name, BEACON_HTTP_PORT_NUM) beacon_grpc_url = "{0}:{1}".format(service.name, RPC_PORT_NUM) - # TODO(old) add validator availability using the validator API: https://ethereum.github.io/beacon-APIs/?urls.primaryName=v1#/ValidatorRequiredApi | from eth2-merge-kurtosis-module - beacon_node_identity_recipe = GetHttpRequestRecipe( - endpoint="/eth/v1/node/identity", - port_id=constants.HTTP_PORT_ID, - extract={ - "enr": ".data.enr", - "multiaddr": ".data.p2p_addresses[0]", - "peer_id": ".data.peer_id", - }, - headers={"Accept-Encoding": "identity"}, - ) - response = plan.request( - recipe=beacon_node_identity_recipe, service_name=service_name - ) - beacon_node_enr = response["extract.enr"] - beacon_multiaddr = response["extract.multiaddr"] - beacon_peer_id = response["extract.peer_id"] + # Skip HTTP requests if skip_start is enabled (service won't be running) + if participant.skip_start: + beacon_node_enr = "" + beacon_multiaddr = "" + beacon_peer_id = "" + else: + # TODO(old) add validator availability using the validator API: https://ethereum.github.io/beacon-APIs/?urls.primaryName=v1#/ValidatorRequiredApi | from eth2-merge-kurtosis-module + beacon_node_identity_recipe = GetHttpRequestRecipe( + endpoint="/eth/v1/node/identity", + port_id=constants.HTTP_PORT_ID, + extract={ + "enr": ".data.enr", + "multiaddr": ".data.p2p_addresses[0]", + "peer_id": ".data.peer_id", + }, + headers={"Accept-Encoding": "identity"}, + ) + response = plan.request( + recipe=beacon_node_identity_recipe, service_name=service_name + ) + beacon_node_enr = response["extract.enr"] + beacon_multiaddr = response["extract.multiaddr"] + beacon_peer_id = response["extract.peer_id"] beacon_metrics_port = service.ports[constants.METRICS_PORT_ID] beacon_metrics_url = "{0}:{1}".format(service.name, beacon_metrics_port.number) diff --git a/src/cl/teku/teku_launcher.star b/src/cl/teku/teku_launcher.star index 874322382..7caff60ad 100644 --- a/src/cl/teku/teku_launcher.star +++ b/src/cl/teku/teku_launcher.star @@ -174,7 +174,11 @@ def get_beacon_config( constants.HTTP_PORT_ID: BEACON_HTTP_PORT_NUM, constants.METRICS_PORT_ID: BEACON_METRICS_PORT_NUM, } - used_ports = shared_utils.get_port_specs(used_port_assignments) + # Disable port checks if skip_start is enabled + if participant.skip_start: + used_ports = shared_utils.get_port_specs(used_port_assignments, wait=None) + else: + used_ports = shared_utils.get_port_specs(used_port_assignments) cmd = [ TEKU_ENTRYPOINT_COMMAND, @@ -358,9 +362,6 @@ def get_beacon_config( "files": files, "env_vars": participant.cl_extra_env_vars, "private_ip_address_placeholder": constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, - "ready_conditions": cl_node_ready_conditions.get_ready_conditions( - constants.HTTP_PORT_ID - ), "labels": shared_utils.label_maker( client=constants.CL_TYPE.teku, client_type=constants.CLIENT_TYPES.cl, @@ -375,6 +376,12 @@ def get_beacon_config( "user": User(uid=0, gid=0), } + # Only add ready_conditions if not skipping start + if not participant.skip_start: + config_args["ready_conditions"] = cl_node_ready_conditions.get_ready_conditions( + constants.HTTP_PORT_ID + ) + if int(participant.cl_min_cpu) > 0: config_args["min_cpu"] = int(participant.cl_min_cpu) if int(participant.cl_max_cpu) > 0: @@ -401,21 +408,27 @@ def get_cl_context( beacon_metrics_port = service.ports[constants.METRICS_PORT_ID] beacon_metrics_url = "{0}:{1}".format(service.name, beacon_metrics_port.number) - beacon_node_identity_recipe = GetHttpRequestRecipe( - endpoint="/eth/v1/node/identity", - port_id=constants.HTTP_PORT_ID, - extract={ - "enr": ".data.enr", - "multiaddr": ".data.p2p_addresses[0]", - "peer_id": ".data.peer_id", - }, - ) - response = plan.request( - recipe=beacon_node_identity_recipe, service_name=service_name - ) - beacon_node_enr = response["extract.enr"] - beacon_multiaddr = response["extract.multiaddr"] - beacon_peer_id = response["extract.peer_id"] + # Skip HTTP requests if skip_start is enabled (service won't be running) + if participant.skip_start: + beacon_node_enr = "" + beacon_multiaddr = "" + beacon_peer_id = "" + else: + beacon_node_identity_recipe = GetHttpRequestRecipe( + endpoint="/eth/v1/node/identity", + port_id=constants.HTTP_PORT_ID, + extract={ + "enr": ".data.enr", + "multiaddr": ".data.p2p_addresses[0]", + "peer_id": ".data.peer_id", + }, + ) + response = plan.request( + recipe=beacon_node_identity_recipe, service_name=service_name + ) + beacon_node_enr = response["extract.enr"] + beacon_multiaddr = response["extract.multiaddr"] + beacon_peer_id = response["extract.peer_id"] beacon_node_metrics_info = node_metrics.new_node_metrics_info( service_name, BEACON_METRICS_PATH, beacon_metrics_url diff --git a/src/package_io/input_parser.star b/src/package_io/input_parser.star index 50d936108..f8ccc9c8a 100644 --- a/src/package_io/input_parser.star +++ b/src/package_io/input_parser.star @@ -424,6 +424,7 @@ def input_parser(plan, input_args): keymanager_enabled=participant["keymanager_enabled"], vc_beacon_node_indices=participant["vc_beacon_node_indices"], checkpoint_sync_enabled=participant["checkpoint_sync_enabled"], + skip_start=participant["skip_start"], ) for participant in result["participants"] ], @@ -1404,6 +1405,7 @@ def default_participant(): "keymanager_enabled": None, "vc_beacon_node_indices": None, "checkpoint_sync_enabled": None, + "skip_start": False, } diff --git a/src/package_io/sanity_check.star b/src/package_io/sanity_check.star index eb7a2fae2..cc6b3ad9b 100644 --- a/src/package_io/sanity_check.star +++ b/src/package_io/sanity_check.star @@ -66,6 +66,7 @@ PARTICIPANT_CATEGORIES = { "keymanager_enabled", "vc_beacon_node_indices", "checkpoint_sync_enabled", + "skip_start", ], } diff --git a/src/participant_network.star b/src/participant_network.star index e59fa2263..1953a1236 100644 --- a/src/participant_network.star +++ b/src/participant_network.star @@ -199,6 +199,17 @@ def launch_participant_network( backend, ) + # Stop beacon nodes for participants with skip_start enabled + for index, participant in enumerate(args_with_right_defaults.participants): + if participant.skip_start: + cl_context = all_cl_contexts[index] + plan.print( + "Stopping beacon node {0} due to skip_start flag".format( + cl_context.beacon_service_name + ) + ) + plan.stop_service(cl_context.beacon_service_name) + # Launch all blobbers after all CLs are up cl_context_to_blobber_url = {} if len(blobber_configs_with_contexts) > 0: diff --git a/src/shared_utils/shared_utils.star b/src/shared_utils/shared_utils.star index 14fe1ad11..e3d8f431d 100644 --- a/src/shared_utils/shared_utils.star +++ b/src/shared_utils/shared_utils.star @@ -279,7 +279,7 @@ def __get_port_range(port_start, max_ports_per_component, participant_index): return (public_port_start, public_port_end) -def get_port_specs(port_assignments): +def get_port_specs(port_assignments, wait=NOT_PROVIDED_WAIT): ports = {} for port_id, port in port_assignments.items(): if port_id in [ @@ -292,13 +292,13 @@ def get_port_specs(port_assignments): constants.WS_PORT_ID, constants.PROFILING_PORT_ID, ]: - ports.update({port_id: new_port_spec(port, TCP_PROTOCOL)}) + ports.update({port_id: new_port_spec(port, TCP_PROTOCOL, wait=wait)}) elif port_id in [ constants.UDP_DISCOVERY_PORT_ID, constants.QUIC_DISCOVERY_PORT_ID, constants.TORRENT_PORT_ID, ]: - ports.update({port_id: new_port_spec(port, UDP_PROTOCOL)}) + ports.update({port_id: new_port_spec(port, UDP_PROTOCOL, wait=wait)}) elif port_id == constants.DEBUG_PORT_ID: ports.update( { @@ -317,7 +317,11 @@ def get_port_specs(port_assignments): constants.RBUILDER_METRICS_PORT_ID, ]: ports.update( - {port_id: new_port_spec(port, TCP_PROTOCOL, HTTP_APPLICATION_PROTOCOL)} + { + port_id: new_port_spec( + port, TCP_PROTOCOL, HTTP_APPLICATION_PROTOCOL, wait=wait + ) + } ) else: fail("Unknown port id: {}".format(port_id)) From 062e90ba6464e6b29b828ba0ee774a9f1e4fccb0 Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Fri, 28 Nov 2025 12:07:59 +0100 Subject: [PATCH 2/7] remove minimal preset with 2s slot --- .github/tests/skip.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/tests/skip.yaml b/.github/tests/skip.yaml index 96248d8d3..c8571d9ae 100644 --- a/.github/tests/skip.yaml +++ b/.github/tests/skip.yaml @@ -8,9 +8,7 @@ participants: checkpoint_sync_enabled: true skip_start: true validator_count: 1 -network_params: - preset: minimal - seconds_per_slot: 2 + additional_services: - dora From 4e25c68e1e39835e5ab8fbb1cd45936c9945ab02 Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Fri, 28 Nov 2025 12:08:28 +0100 Subject: [PATCH 3/7] use minimal --- .github/tests/skip.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/tests/skip.yaml b/.github/tests/skip.yaml index c8571d9ae..dec20b507 100644 --- a/.github/tests/skip.yaml +++ b/.github/tests/skip.yaml @@ -8,7 +8,8 @@ participants: checkpoint_sync_enabled: true skip_start: true validator_count: 1 - +network_params: + preset: minimal additional_services: - dora From 1df04c3644cc9e578ce69771778e0f839a9f48fc Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Fri, 28 Nov 2025 14:52:46 +0100 Subject: [PATCH 4/7] add checkpointz url --- .github/tests/skip.yaml | 31 ++++++++++++++----- src/cl/cl_launcher.star | 9 +++++- .../checkpointz-config/config.yaml.tmpl | 2 +- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/.github/tests/skip.yaml b/.github/tests/skip.yaml index dec20b507..ec46716c0 100644 --- a/.github/tests/skip.yaml +++ b/.github/tests/skip.yaml @@ -1,16 +1,31 @@ participants: - - el_type: geth - cl_type: lighthouse - cl_extra_params: ["--target-peers=0"] + - cl_type: prysm - - el_type: geth - cl_type: prysm + - cl_type: lighthouse checkpoint_sync_enabled: true skip_start: true validator_count: 1 + + - cl_type: teku + checkpoint_sync_enabled: true + skip_start: true + validator_count: 1 + + + + - cl_type: lodestar + checkpoint_sync_enabled: true + skip_start: true + validator_count: 1 + + - cl_type: grandine + checkpoint_sync_enabled: true + skip_start: true + validator_count: 1 + network_params: - preset: minimal + seconds_per_slot: 4 + additional_services: - dora - -checkpoint_sync_url: "http://cl-1-lighthouse-geth:4000" + - checkpointz diff --git a/src/cl/cl_launcher.star b/src/cl/cl_launcher.star index 7d884d570..020ce17cd 100644 --- a/src/cl/cl_launcher.star +++ b/src/cl/cl_launcher.star @@ -187,7 +187,14 @@ def launch( checkpoint_sync_enabled = participant.checkpoint_sync_enabled if checkpoint_sync_enabled: if args_with_right_defaults.checkpoint_sync_url == "": - if ( + if network_params.network == constants.NETWORK_NAME.kurtosis: + if "checkpointz" in args_with_right_defaults.additional_services: + checkpoint_sync_url = "http://checkpointz:5555" + else: + fail( + "Checkpoint sync URL is required if you enabled checkpoint_sync for kurtosis network. Please enable checkpointz additional service." + ) + elif ( network_params.network in constants.PUBLIC_NETWORKS or network_params.network == constants.NETWORK_NAME.ephemery ): diff --git a/static_files/checkpointz-config/config.yaml.tmpl b/static_files/checkpointz-config/config.yaml.tmpl index c2785fe76..11ec2b560 100644 --- a/static_files/checkpointz-config/config.yaml.tmpl +++ b/static_files/checkpointz-config/config.yaml.tmpl @@ -4,7 +4,7 @@ global: metricsAddr: ":9090" checkpointz: - mode: "light" + mode: "full" caches: blocks: max_items: 200 From 113dc7b1dce383999e7e7d375ff6deb7db9be214 Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Tue, 2 Dec 2025 17:08:56 +0100 Subject: [PATCH 5/7] fix checkpointz params --- .github/tests/skip.yaml | 8 +++++--- src/package_io/input_parser.star | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/tests/skip.yaml b/.github/tests/skip.yaml index ec46716c0..d94906a1b 100644 --- a/.github/tests/skip.yaml +++ b/.github/tests/skip.yaml @@ -11,8 +11,6 @@ participants: skip_start: true validator_count: 1 - - - cl_type: lodestar checkpoint_sync_enabled: true skip_start: true @@ -25,7 +23,11 @@ participants: network_params: seconds_per_slot: 4 - + preset: minimal + #fulu_fork_epoch: 0 additional_services: - dora - checkpointz + +checkpointz_params: + image: bbusa/checkpointz:latest diff --git a/src/package_io/input_parser.star b/src/package_io/input_parser.star index 51dd352ce..c60051123 100644 --- a/src/package_io/input_parser.star +++ b/src/package_io/input_parser.star @@ -195,6 +195,10 @@ def input_parser(plan, input_args): for sub_attr in input_args["ethereum_genesis_generator_params"]: sub_value = input_args["ethereum_genesis_generator_params"][sub_attr] result["ethereum_genesis_generator_params"][sub_attr] = sub_value + elif attr == "checkpointz_params": + for sub_attr in input_args["checkpointz_params"]: + sub_value = input_args["checkpointz_params"][sub_attr] + result["checkpointz_params"][sub_attr] = sub_value if result.get("disable_peer_scoring"): result = enrich_disable_peer_scoring(result) From 062bc2b9d3dbd570f0b46f2191653bc88f9bd072 Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Fri, 5 Dec 2025 10:32:04 +0100 Subject: [PATCH 6/7] fix checkpointz image --- .github/tests/skip.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/tests/skip.yaml b/.github/tests/skip.yaml index d94906a1b..558ae297c 100644 --- a/.github/tests/skip.yaml +++ b/.github/tests/skip.yaml @@ -30,4 +30,4 @@ additional_services: - checkpointz checkpointz_params: - image: bbusa/checkpointz:latest + image: ethpandaops/checkpointz:0.0.1-custom-preset From 6a73cc4de2b4e12492e99cdbfc529656073df8e4 Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Tue, 9 Dec 2025 11:39:10 +0100 Subject: [PATCH 7/7] Update skip.yaml to remove unused parameters Removed checkpointz parameters and commented out fulu fork epoch. Signed-off-by: Barnabas Busa --- .github/tests/skip.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/tests/skip.yaml b/.github/tests/skip.yaml index 558ae297c..f8c4344c7 100644 --- a/.github/tests/skip.yaml +++ b/.github/tests/skip.yaml @@ -24,10 +24,7 @@ participants: network_params: seconds_per_slot: 4 preset: minimal - #fulu_fork_epoch: 0 additional_services: - dora - checkpointz -checkpointz_params: - image: ethpandaops/checkpointz:0.0.1-custom-preset