Skip to content

Commit 4272ff3

Browse files
authored
feat: add vc_count to increase the number of validators per participant (ethereum#633)
1 parent ad46dbd commit 4272ff3

File tree

6 files changed

+273
-177
lines changed

6 files changed

+273
-177
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,10 @@ participants:
344344
# - teku: consensys/teku:latest
345345
vc_image: ""
346346

347+
# The number of validator clients to run for this participant
348+
# Defaults to 1
349+
vc_count: 1
350+
347351
# The log level string that this participant's CL client should log at
348352
# If this is emptystring then the global `logLevel` parameter's value will be translated into a string appropriate for the client (e.g. if
349353
# global `logLevel` = `info` then Teku would receive `INFO`, Prysm would receive `info`, etc.)

network_params.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ participants:
3030
vc_type: lighthouse
3131
vc_image: sigp/lighthouse:latest
3232
vc_log_level: ""
33+
vc_count: 1
3334
vc_extra_env_vars: {}
3435
vc_extra_labels: {}
3536
vc_extra_params: []

src/cl/cl_launcher.star

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def launch(
119119

120120
cl_service_name = "cl-{0}-{1}-{2}".format(index_str, cl_type, el_type)
121121
new_cl_node_validator_keystores = None
122-
if participant.validator_count != 0:
122+
if participant.validator_count != 0 and participant.vc_count != 0:
123123
new_cl_node_validator_keystores = preregistered_validator_keys_for_nodes[
124124
index
125125
]

src/package_io/input_parser.star

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ def input_parser(plan, input_args):
214214
vc_type=participant["vc_type"],
215215
vc_image=participant["vc_image"],
216216
vc_log_level=participant["vc_log_level"],
217+
vc_count=participant["vc_count"],
217218
vc_tolerations=participant["vc_tolerations"],
218219
cl_extra_params=participant["cl_extra_params"],
219220
cl_extra_labels=participant["cl_extra_labels"],
@@ -537,6 +538,30 @@ def parse_network_params(plan, input_args):
537538
)
538539
participant["vc_image"] = default_image
539540

541+
if result["parallel_keystore_generation"] and participant["vc_count"] != 1:
542+
fail(
543+
"parallel_keystore_generation is only supported for 1 validator client per participant (for now)"
544+
)
545+
546+
# If the num validator keys per node is not divisible by vc_count of a participant, fail
547+
if (
548+
participant["vc_count"] > 0
549+
and result["network_params"]["num_validator_keys_per_node"]
550+
% participant["vc_count"]
551+
!= 0
552+
):
553+
fail(
554+
"num_validator_keys_per_node: {0} is not divisible by vc_count: {1} for participant: {2}".format(
555+
result["network_params"]["num_validator_keys_per_node"],
556+
participant["vc_count"],
557+
str(index + 1)
558+
+ "-"
559+
+ participant["el_type"]
560+
+ "-"
561+
+ participant["cl_type"],
562+
)
563+
)
564+
540565
snooper_enabled = participant["snooper_enabled"]
541566
if snooper_enabled == None:
542567
participant["snooper_enabled"] = result["snooper_enabled"]
@@ -826,6 +851,7 @@ def default_participant():
826851
"vc_type": "",
827852
"vc_image": "",
828853
"vc_log_level": "",
854+
"vc_count": 1,
829855
"vc_extra_env_vars": {},
830856
"vc_extra_labels": {},
831857
"vc_extra_params": [],

src/participant_network.star

Lines changed: 154 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -210,150 +210,177 @@ def launch_participant_network(
210210
cl_type = participant.cl_type
211211
vc_type = participant.vc_type
212212
index_str = shared_utils.zfill_custom(index + 1, len(str(len(participants))))
213-
el_context = all_el_contexts[index]
214-
cl_context = all_cl_contexts[index]
215-
216-
node_selectors = input_parser.get_client_node_selectors(
217-
participant.node_selectors,
218-
global_node_selectors,
219-
)
220-
if participant.ethereum_metrics_exporter_enabled:
221-
pair_name = "{0}-{1}-{2}".format(index_str, cl_type, el_type)
213+
for sub_index in range(participant.vc_count):
214+
el_context = all_el_contexts[index]
215+
cl_context = all_cl_contexts[index]
222216

223-
ethereum_metrics_exporter_service_name = (
224-
"ethereum-metrics-exporter-{0}".format(pair_name)
217+
node_selectors = input_parser.get_client_node_selectors(
218+
participant.node_selectors,
219+
global_node_selectors,
225220
)
221+
if participant.ethereum_metrics_exporter_enabled:
222+
pair_name = "{0}-{1}-{2}".format(index_str, cl_type, el_type)
226223

227-
ethereum_metrics_exporter_context = ethereum_metrics_exporter.launch(
228-
plan,
229-
pair_name,
230-
ethereum_metrics_exporter_service_name,
231-
el_context,
232-
cl_context,
233-
node_selectors,
234-
)
235-
plan.print(
236-
"Successfully added {0} ethereum metrics exporter participants".format(
237-
ethereum_metrics_exporter_context
224+
ethereum_metrics_exporter_service_name = (
225+
"ethereum-metrics-exporter-{0}".format(pair_name)
238226
)
239-
)
240-
241-
all_ethereum_metrics_exporter_contexts.append(ethereum_metrics_exporter_context)
242227

243-
xatu_sentry_context = None
244-
245-
if participant.xatu_sentry_enabled:
246-
pair_name = "{0}-{1}-{2}".format(index_str, cl_type, el_type)
247-
248-
xatu_sentry_service_name = "xatu-sentry-{0}".format(pair_name)
249-
250-
xatu_sentry_context = xatu_sentry.launch(
251-
plan,
252-
xatu_sentry_service_name,
253-
cl_context,
254-
xatu_sentry_params,
255-
network_params,
256-
pair_name,
257-
node_selectors,
258-
)
259-
plan.print(
260-
"Successfully added {0} xatu sentry participants".format(
261-
xatu_sentry_context
228+
ethereum_metrics_exporter_context = ethereum_metrics_exporter.launch(
229+
plan,
230+
pair_name,
231+
ethereum_metrics_exporter_service_name,
232+
el_context,
233+
cl_context,
234+
node_selectors,
235+
)
236+
plan.print(
237+
"Successfully added {0} ethereum metrics exporter participants".format(
238+
ethereum_metrics_exporter_context
239+
)
262240
)
263-
)
264241

265-
all_xatu_sentry_contexts.append(xatu_sentry_context)
242+
all_ethereum_metrics_exporter_contexts.append(
243+
ethereum_metrics_exporter_context
244+
)
266245

267-
plan.print("Successfully added {0} CL participants".format(num_participants))
246+
xatu_sentry_context = None
268247

269-
plan.print("Start adding validators for participant #{0}".format(index_str))
270-
if participant.use_separate_vc == None:
271-
# This should only be the case for the MEV participant,
272-
# the regular participants default to False/True
273-
all_vc_contexts.append(None)
274-
all_snooper_beacon_contexts.append(None)
275-
continue
248+
if participant.xatu_sentry_enabled:
249+
pair_name = "{0}-{1}-{2}".format(index_str, cl_type, el_type)
276250

277-
if cl_type in _cls_that_need_separate_vc and not participant.use_separate_vc:
278-
fail("{0} needs a separate validator client!".format(cl_type))
251+
xatu_sentry_service_name = "xatu-sentry-{0}".format(pair_name)
279252

280-
if not participant.use_separate_vc:
281-
all_vc_contexts.append(None)
282-
all_snooper_beacon_contexts.append(None)
283-
continue
253+
xatu_sentry_context = xatu_sentry.launch(
254+
plan,
255+
xatu_sentry_service_name,
256+
cl_context,
257+
xatu_sentry_params,
258+
network_params,
259+
pair_name,
260+
node_selectors,
261+
)
262+
plan.print(
263+
"Successfully added {0} xatu sentry participants".format(
264+
xatu_sentry_context
265+
)
266+
)
284267

285-
plan.print(
286-
"Using separate validator client for participant #{0}".format(index_str)
287-
)
268+
all_xatu_sentry_contexts.append(xatu_sentry_context)
288269

289-
vc_keystores = None
290-
if participant.validator_count != 0:
291-
vc_keystores = preregistered_validator_keys_for_nodes[index]
270+
plan.print(
271+
"Successfully added {0} CL participants".format(num_participants)
272+
)
292273

293-
vc_context = None
294-
snooper_beacon_context = None
274+
plan.print("Start adding validators for participant #{0}".format(index_str))
275+
if participant.use_separate_vc == None:
276+
# This should only be the case for the MEV participant,
277+
# the regular participants default to False/True
278+
all_vc_contexts.append(None)
279+
all_snooper_beacon_contexts.append(None)
280+
continue
281+
282+
if (
283+
cl_type in _cls_that_need_separate_vc
284+
and not participant.use_separate_vc
285+
):
286+
fail("{0} needs a separate validator client!".format(cl_type))
287+
288+
if not participant.use_separate_vc:
289+
all_vc_contexts.append(None)
290+
all_snooper_beacon_contexts.append(None)
291+
continue
295292

296-
if participant.snooper_enabled:
297-
snooper_service_name = "snooper-beacon-{0}-{1}-{2}".format(
298-
index_str, cl_type, vc_type
299-
)
300-
snooper_beacon_context = beacon_snooper.launch(
301-
plan,
302-
snooper_service_name,
303-
cl_context,
304-
node_selectors,
305-
)
306293
plan.print(
307-
"Successfully added {0} snooper participants".format(
308-
snooper_beacon_context
294+
"Using separate validator client for participant #{0}".format(index_str)
295+
)
296+
297+
vc_keystores = None
298+
if participant.validator_count != 0:
299+
if participant.vc_count == 1:
300+
vc_keystores = preregistered_validator_keys_for_nodes[index]
301+
else:
302+
vc_keystores = preregistered_validator_keys_for_nodes[
303+
index + sub_index
304+
]
305+
306+
vc_context = None
307+
snooper_beacon_context = None
308+
309+
if participant.snooper_enabled:
310+
snooper_service_name = "snooper-beacon-{0}-{1}-{2}{3}".format(
311+
index_str,
312+
cl_type,
313+
vc_type,
314+
"-" + str(sub_index) if participant.vc_count != 1 else "",
315+
)
316+
snooper_beacon_context = beacon_snooper.launch(
317+
plan,
318+
snooper_service_name,
319+
cl_context,
320+
node_selectors,
321+
)
322+
plan.print(
323+
"Successfully added {0} snooper participants".format(
324+
snooper_beacon_context
325+
)
326+
)
327+
all_snooper_beacon_contexts.append(snooper_beacon_context)
328+
full_name = (
329+
"{0}-{1}-{2}-{3}{4}".format(
330+
index_str,
331+
el_type,
332+
cl_type,
333+
vc_type,
334+
"-" + str(sub_index) if participant.vc_count != 1 else "",
335+
)
336+
if participant.cl_type != participant.vc_type
337+
else "{0}-{1}-{2}{3}".format(
338+
index_str,
339+
el_type,
340+
cl_type,
341+
"-" + str(sub_index) if participant.vc_count != 1 else "",
309342
)
310343
)
311-
all_snooper_beacon_contexts.append(snooper_beacon_context)
312-
full_name = (
313-
"{0}-{1}-{2}-{3}".format(index_str, el_type, cl_type, vc_type)
314-
if participant.cl_type != participant.vc_type
315-
else "{0}-{1}-{2}".format(index_str, el_type, cl_type)
316-
)
317344

318-
vc_context = vc.launch(
319-
plan=plan,
320-
launcher=vc.new_vc_launcher(el_cl_genesis_data=el_cl_data),
321-
keymanager_file=keymanager_file,
322-
service_name="vc-{0}".format(full_name),
323-
vc_type=vc_type,
324-
image=participant.vc_image,
325-
participant_log_level=participant.vc_log_level,
326-
global_log_level=global_log_level,
327-
cl_context=cl_context,
328-
el_context=el_context,
329-
full_name=full_name,
330-
snooper_enabled=participant.snooper_enabled,
331-
snooper_beacon_context=snooper_beacon_context,
332-
node_keystore_files=vc_keystores,
333-
vc_min_cpu=participant.vc_min_cpu,
334-
vc_max_cpu=participant.vc_max_cpu,
335-
vc_min_mem=participant.vc_min_mem,
336-
vc_max_mem=participant.vc_max_mem,
337-
extra_params=participant.vc_extra_params,
338-
extra_env_vars=participant.vc_extra_env_vars,
339-
extra_labels=participant.vc_extra_labels,
340-
prysm_password_relative_filepath=prysm_password_relative_filepath,
341-
prysm_password_artifact_uuid=prysm_password_artifact_uuid,
342-
vc_tolerations=participant.vc_tolerations,
343-
participant_tolerations=participant.tolerations,
344-
global_tolerations=global_tolerations,
345-
node_selectors=node_selectors,
346-
keymanager_enabled=participant.keymanager_enabled,
347-
preset=network_params.preset,
348-
network=network_params.network,
349-
electra_fork_epoch=network_params.electra_fork_epoch,
350-
)
351-
all_vc_contexts.append(vc_context)
345+
vc_context = vc.launch(
346+
plan=plan,
347+
launcher=vc.new_vc_launcher(el_cl_genesis_data=el_cl_data),
348+
keymanager_file=keymanager_file,
349+
service_name="vc-{0}".format(full_name),
350+
vc_type=vc_type,
351+
image=participant.vc_image,
352+
participant_log_level=participant.vc_log_level,
353+
global_log_level=global_log_level,
354+
cl_context=cl_context,
355+
el_context=el_context,
356+
full_name=full_name,
357+
snooper_enabled=participant.snooper_enabled,
358+
snooper_beacon_context=snooper_beacon_context,
359+
node_keystore_files=vc_keystores,
360+
vc_min_cpu=participant.vc_min_cpu,
361+
vc_max_cpu=participant.vc_max_cpu,
362+
vc_min_mem=participant.vc_min_mem,
363+
vc_max_mem=participant.vc_max_mem,
364+
extra_params=participant.vc_extra_params,
365+
extra_env_vars=participant.vc_extra_env_vars,
366+
extra_labels=participant.vc_extra_labels,
367+
prysm_password_relative_filepath=prysm_password_relative_filepath,
368+
prysm_password_artifact_uuid=prysm_password_artifact_uuid,
369+
vc_tolerations=participant.vc_tolerations,
370+
participant_tolerations=participant.tolerations,
371+
global_tolerations=global_tolerations,
372+
node_selectors=node_selectors,
373+
keymanager_enabled=participant.keymanager_enabled,
374+
preset=network_params.preset,
375+
network=network_params.network,
376+
electra_fork_epoch=network_params.electra_fork_epoch,
377+
)
378+
all_vc_contexts.append(vc_context)
352379

353-
if vc_context and vc_context.metrics_info:
354-
vc_context.metrics_info["config"] = participant.prometheus_config
380+
if vc_context and vc_context.metrics_info:
381+
vc_context.metrics_info["config"] = participant.prometheus_config
355382

356-
all_participants = []
383+
all_participants = []
357384

358385
for index, participant in enumerate(participants):
359386
el_type = participant.el_type
@@ -364,7 +391,10 @@ def launch_participant_network(
364391

365392
el_context = all_el_contexts[index]
366393
cl_context = all_cl_contexts[index]
367-
vc_context = all_vc_contexts[index]
394+
if participant.vc_count != 0:
395+
vc_context = all_vc_contexts[index]
396+
else:
397+
vc_context = None
368398

369399
if participant.snooper_enabled:
370400
snooper_engine_context = all_snooper_engine_contexts[index]

0 commit comments

Comments
 (0)