Commit b72dad35 authored by Gyanendra Mishra's avatar Gyanendra Mishra Committed by GitHub

refactor!: merge eth-network-package onto eth2-package (#228)

Notes for reviewer - perhaps @leoporoli ?

1. src/el & src/cl & src/node_metrics_info & src/participant.star &
src/participant_network.star & src/prelaunch_data_generator/ &
src/snooper & static_files have just been lifted and shifted
2. constants is just a union of the two
3. ️ parse input is a best effort union of the two; needs some 👀 
4. shared_utils.star is a best effort union of the two
5. package_io, shared_utils etc used to be at root level they have been
shifted
6. eth-network-package has been changed to eth2-package throughout all
`.star` files

Pending after PR - perhaps @leeederek ?
1. Get the README's to make sense together
2. Get the run.gif over here?

️  Note to testers

1. Clone the package
2. Check out this PR
3. Run `kurtosis run .` with args of choice
parent b943370b
...@@ -10,9 +10,10 @@ executors: ...@@ -10,9 +10,10 @@ executors:
parameters: parameters:
# To enable/disabled the check_latest_version workflow execution which will be triggered by this scheduled pipeline: https://app.circleci.com/settings/project/github/kurtosis-tech/eth2-package/triggers # To enable/disabled the check_latest_version workflow execution which will be triggered by this scheduled pipeline: https://app.circleci.com/settings/project/github/kurtosis-tech/eth2-package/triggers
# TODO revert this - setting this to true to get all existing tests to run on CI during merge
should-enable-check-latest-version-workflow: should-enable-check-latest-version-workflow:
type: boolean type: boolean
default: false default: true
# To enable/disabled the check_code workflow execution which will be triggered by the PR's checkers # To enable/disabled the check_code workflow execution which will be triggered by the PR's checkers
should-enable-build-workflow: should-enable-build-workflow:
type: boolean type: boolean
......
...@@ -2,16 +2,17 @@ parse_input = import_module( ...@@ -2,16 +2,17 @@ parse_input = import_module(
"github.com/kurtosis-tech/eth2-package/src/package_io/parse_input.star" "github.com/kurtosis-tech/eth2-package/src/package_io/parse_input.star"
) )
participant_network = import_module(
"github.com/kurtosis-tech/eth2-package/src/participant_network.star"
)
static_files = import_module( static_files = import_module(
"github.com/kurtosis-tech/eth2-package/src/static_files/static_files.star" "github.com/kurtosis-tech/eth2-package/src/static_files/static_files.star"
) )
genesis_constants = import_module( genesis_constants = import_module(
"github.com/kurtosis-tech/eth-network-package/src/prelaunch_data_generator/genesis_constants/genesis_constants.star" "github.com/kurtosis-tech/eth2-package/src/prelaunch_data_generator/genesis_constants/genesis_constants.star"
) )
eth_network_module = import_module(
"github.com/kurtosis-tech/eth-network-package/main.star"
)
transaction_spammer = import_module( transaction_spammer = import_module(
"github.com/kurtosis-tech/eth2-package/src/transaction_spammer/transaction_spammer.star" "github.com/kurtosis-tech/eth2-package/src/transaction_spammer/transaction_spammer.star"
) )
...@@ -66,13 +67,12 @@ PATH_TO_PARSED_BEACON_STATE = "/genesis/output/parsedBeaconState.json" ...@@ -66,13 +67,12 @@ PATH_TO_PARSED_BEACON_STATE = "/genesis/output/parsedBeaconState.json"
def run(plan, args={}): def run(plan, args={}):
args_with_right_defaults, args_with_defaults_dict = parse_input.parse_input( args_with_right_defaults = parse_input.parse_input(plan, args)
plan, args
)
num_participants = len(args_with_right_defaults.participants) num_participants = len(args_with_right_defaults.participants)
network_params = args_with_right_defaults.network_params network_params = args_with_right_defaults.network_params
mev_params = args_with_right_defaults.mev_params mev_params = args_with_right_defaults.mev_params
parallel_keystore_generation = args_with_right_defaults.parallel_keystore_generation
grafana_datasource_config_template = read_file( grafana_datasource_config_template = read_file(
static_files.GRAFANA_DATASOURCE_CONFIG_TEMPLATE_FILEPATH static_files.GRAFANA_DATASOURCE_CONFIG_TEMPLATE_FILEPATH
...@@ -95,7 +95,20 @@ def run(plan, args={}): ...@@ -95,7 +95,20 @@ def run(plan, args={}):
all_participants, all_participants,
cl_genesis_timestamp, cl_genesis_timestamp,
genesis_validators_root, genesis_validators_root,
) = eth_network_module.run(plan, args_with_defaults_dict) ) = participant_network.launch_participant_network(
plan,
args_with_right_defaults.participants,
network_params,
args_with_right_defaults.global_client_log_level,
parallel_keystore_generation,
)
plan.print(
"NODE JSON RPC URI: '{0}:{1}'".format(
all_participants[0].el_client_context.ip_addr,
all_participants[0].el_client_context.rpc_port_num,
)
)
all_el_client_contexts = [] all_el_client_contexts = []
all_cl_client_contexts = [] all_cl_client_contexts = []
......
def new_cl_client_context(
client_name,
enr,
ip_addr,
http_port_num,
cl_nodes_metrics_info,
beacon_service_name,
validator_service_name="",
multiaddr="",
peer_id="",
snooper_enabled=False,
snooper_engine_context=None,
):
return struct(
client_name=client_name,
enr=enr,
ip_addr=ip_addr,
http_port_num=http_port_num,
cl_nodes_metrics_info=cl_nodes_metrics_info,
beacon_service_name=beacon_service_name,
validator_service_name=validator_service_name,
multiaddr=multiaddr,
peer_id=peer_id,
snooper_enabled=snooper_enabled,
snooper_engine_context=snooper_engine_context,
)
def get_ready_conditions(port_id):
recipe = GetHttpRequestRecipe(endpoint="/eth/v1/node/health", port_id=port_id)
ready_conditions = ReadyCondition(
recipe=recipe,
field="code",
assertion="IN",
target_value=[200, 206],
timeout="15m",
)
return ready_conditions
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
shared_utils = import_module(
"github.com/kurtosis-tech/eth2-package/src/shared_utils/shared_utils.star"
)
input_parser = import_module(
"github.com/kurtosis-tech/eth2-package/src/package_io/parse_input.star"
)
el_client_context = import_module(
"github.com/kurtosis-tech/eth2-package/src/el/el_client_context.star"
)
el_admin_node_info = import_module(
"github.com/kurtosis-tech/eth2-package/src/el/el_admin_node_info.star"
)
node_metrics = import_module(
"github.com/kurtosis-tech/eth2-package/src/node_metrics_info.star"
)
package_io = import_module(
"github.com/kurtosis-tech/eth2-package/src/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"
KZG_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/opt/besu/genesis/output/trusted_setup.txt"
GENESIS_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/opt/besu/genesis"
METRICS_PATH = "/metrics"
RPC_PORT_NUM = 8545
WS_PORT_NUM = 8546
DISCOVERY_PORT_NUM = 30303
ENGINE_HTTP_RPC_PORT_NUM = 8551
METRICS_PORT_NUM = 9001
# The min/max CPU/memory that the execution node can use
EXECUTION_MIN_CPU = 100
EXECUTION_MAX_CPU = 1000
EXECUTION_MIN_MEMORY = 512
EXECUTION_MAX_MEMORY = 2048
# Port IDs
RPC_PORT_ID = "rpc"
WS_PORT_ID = "ws"
TCP_DISCOVERY_PORT_ID = "tcp-discovery"
UDP_DISCOVERY_PORT_ID = "udp-discovery"
ENGINE_HTTP_RPC_PORT_ID = "engine-rpc"
METRICS_PORT_ID = "metrics"
PRIVATE_IP_ADDRESS_PLACEHOLDER = "KURTOSIS_IP_ADDR_PLACEHOLDER"
USED_PORTS = {
RPC_PORT_ID: shared_utils.new_port_spec(RPC_PORT_NUM, shared_utils.TCP_PROTOCOL),
WS_PORT_ID: shared_utils.new_port_spec(WS_PORT_NUM, shared_utils.TCP_PROTOCOL),
TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
DISCOVERY_PORT_NUM, shared_utils.TCP_PROTOCOL
),
UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
DISCOVERY_PORT_NUM, shared_utils.UDP_PROTOCOL
),
ENGINE_HTTP_RPC_PORT_ID: shared_utils.new_port_spec(
ENGINE_HTTP_RPC_PORT_NUM, shared_utils.TCP_PROTOCOL
),
METRICS_PORT_ID: shared_utils.new_port_spec(
METRICS_PORT_NUM, shared_utils.TCP_PROTOCOL
),
}
ENTRYPOINT_ARGS = ["sh", "-c"]
BESU_LOG_LEVELS = {
package_io.GLOBAL_CLIENT_LOG_LEVEL.error: "ERROR",
package_io.GLOBAL_CLIENT_LOG_LEVEL.warn: "WARN",
package_io.GLOBAL_CLIENT_LOG_LEVEL.info: "INFO",
package_io.GLOBAL_CLIENT_LOG_LEVEL.debug: "DEBUG",
package_io.GLOBAL_CLIENT_LOG_LEVEL.trace: "TRACE",
}
def launch(
plan,
launcher,
service_name,
image,
participant_log_level,
global_log_level,
existing_el_clients,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
):
log_level = input_parser.get_client_log_level_or_default(
participant_log_level, global_log_level, BESU_LOG_LEVELS
)
el_min_cpu = int(el_min_cpu) if int(el_min_cpu) > 0 else EXECUTION_MIN_CPU
el_max_cpu = int(el_max_cpu) if int(el_max_cpu) > 0 else EXECUTION_MAX_CPU
el_min_mem = int(el_min_mem) if int(el_min_mem) > 0 else EXECUTION_MIN_MEMORY
el_max_mem = int(el_max_mem) if int(el_max_mem) > 0 else EXECUTION_MAX_MEMORY
config, jwt_secret_json_filepath_on_client = get_config(
launcher.network_id,
launcher.el_genesis_data,
image,
existing_el_clients,
log_level,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
)
service = plan.add_service(service_name, config)
enode = el_admin_node_info.get_enode_for_node(plan, service_name, RPC_PORT_ID)
jwt_secret = shared_utils.read_file_from_service(
plan, service_name, jwt_secret_json_filepath_on_client
)
metrics_url = "{0}:{1}".format(service.ip_address, METRICS_PORT_NUM)
besu_metrics_info = node_metrics.new_node_metrics_info(
service_name, METRICS_PATH, metrics_url
)
return el_client_context.new_el_client_context(
"besu",
"", # besu has no ENR
enode,
service.ip_address,
RPC_PORT_NUM,
WS_PORT_NUM,
ENGINE_HTTP_RPC_PORT_NUM,
jwt_secret,
service_name,
[besu_metrics_info],
)
def get_config(
network_id,
genesis_data,
image,
existing_el_clients,
log_level,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
):
genesis_json_filepath_on_client = shared_utils.path_join(
GENESIS_DATA_DIRPATH_ON_CLIENT_CONTAINER,
genesis_data.besu_genesis_json_relative_filepath,
)
jwt_secret_json_filepath_on_client = shared_utils.path_join(
GENESIS_DATA_DIRPATH_ON_CLIENT_CONTAINER,
genesis_data.jwt_secret_relative_filepath,
)
cmd = [
"besu",
"--logging=" + log_level,
"--data-path=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER,
"--genesis-file=" + genesis_json_filepath_on_client,
"--network-id=" + network_id,
"--host-allowlist=*",
"--rpc-http-enabled=true",
"--rpc-http-host=0.0.0.0",
"--rpc-http-port={0}".format(RPC_PORT_NUM),
"--rpc-http-api=ADMIN,CLIQUE,ETH,NET,DEBUG,TXPOOL,ENGINE,TRACE,WEB3",
"--rpc-http-cors-origins=*",
"--rpc-ws-enabled=true",
"--rpc-ws-host=0.0.0.0",
"--rpc-ws-port={0}".format(WS_PORT_NUM),
"--rpc-ws-api=ADMIN,CLIQUE,ETH,NET,DEBUG,TXPOOL,ENGINE,TRACE,WEB3",
"--p2p-enabled=true",
"--p2p-host=" + PRIVATE_IP_ADDRESS_PLACEHOLDER,
"--p2p-port={0}".format(DISCOVERY_PORT_NUM),
"--engine-rpc-enabled=true",
"--engine-jwt-secret={0}".format(jwt_secret_json_filepath_on_client),
"--engine-host-allowlist=*",
"--engine-rpc-port={0}".format(ENGINE_HTTP_RPC_PORT_NUM),
"--sync-mode=FULL",
"--data-storage-format=BONSAI",
"--kzg-trusted-setup=" + KZG_DATA_DIRPATH_ON_CLIENT_CONTAINER,
"--metrics-enabled=true",
"--metrics-host=0.0.0.0",
"--metrics-port={0}".format(METRICS_PORT_NUM),
]
if len(existing_el_clients) > 0:
cmd.append(
"--bootnodes="
+ ",".join(
[
ctx.enode
for ctx in existing_el_clients[: package_io.MAX_ENODE_ENTRIES]
]
)
)
if len(extra_params) > 0:
# we do this as extra_params isn't a normal [] but a proto repeated array
cmd.extend([param for param in extra_params])
cmd_str = " ".join(cmd)
return (
ServiceConfig(
image=image,
ports=USED_PORTS,
cmd=[cmd_str],
files={
GENESIS_DATA_DIRPATH_ON_CLIENT_CONTAINER: genesis_data.files_artifact_uuid
},
entrypoint=ENTRYPOINT_ARGS,
private_ip_address_placeholder=PRIVATE_IP_ADDRESS_PLACEHOLDER,
min_cpu=el_min_cpu,
max_cpu=el_max_cpu,
min_memory=el_min_mem,
max_memory=el_max_mem,
env_vars=extra_env_vars,
),
jwt_secret_json_filepath_on_client,
)
def new_besu_launcher(network_id, el_genesis_data):
return struct(network_id=network_id, el_genesis_data=el_genesis_data)
def get_enode_enr_for_node(plan, service_name, port_id):
recipe = PostHttpRequestRecipe(
endpoint="",
body='{"method":"admin_nodeInfo","params":[],"id":1,"jsonrpc":"2.0"}',
content_type="application/json",
port_id=port_id,
extract={
"enode": """.result.enode | split("?") | .[0]""",
"enr": ".result.enr",
},
)
response = plan.wait(
recipe=recipe,
field="extract.enode",
assertion="!=",
target_value="",
timeout="15m",
service_name=service_name,
)
return (response["extract.enode"], response["extract.enr"])
def get_enode_for_node(plan, service_name, port_id):
recipe = PostHttpRequestRecipe(
endpoint="",
body='{"method":"admin_nodeInfo","params":[],"id":1,"jsonrpc":"2.0"}',
content_type="application/json",
port_id=port_id,
extract={
"enode": """.result.enode | split("?") | .[0]""",
},
)
response = plan.wait(
recipe=recipe,
field="extract.enode",
assertion="!=",
target_value="",
timeout="15m",
service_name=service_name,
)
return response["extract.enode"]
def new_el_client_context(
client_name,
enr,
enode,
ip_addr,
rpc_port_num,
ws_port_num,
engine_rpc_port_num,
jwt_secret,
service_name="",
el_metrics_info=None,
):
return struct(
service_name=service_name,
client_name=client_name,
enr=enr,
enode=enode,
ip_addr=ip_addr,
rpc_port_num=rpc_port_num,
ws_port_num=ws_port_num,
engine_rpc_port_num=engine_rpc_port_num,
jwt_secret=jwt_secret,
el_metrics_info=el_metrics_info,
)
shared_utils = import_module(
"github.com/kurtosis-tech/eth2-package/src/shared_utils/shared_utils.star"
)
input_parser = import_module(
"github.com/kurtosis-tech/eth2-package/src/package_io/parse_input.star"
)
el_admin_node_info = import_module(
"github.com/kurtosis-tech/eth2-package/src/el/el_admin_node_info.star"
)
el_client_context = import_module(
"github.com/kurtosis-tech/eth2-package/src/el/el_client_context.star"
)
node_metrics = import_module(
"github.com/kurtosis-tech/eth2-package/src/node_metrics_info.star"
)
package_io = import_module(
"github.com/kurtosis-tech/eth2-package/src/package_io/constants.star"
)
# The dirpath of the execution data directory on the client container
EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/home/erigon/execution-data"
GENESIS_DATA_MOUNT_DIRPATH = "/genesis"
METRICS_PATH = "/metrics"
WS_RPC_PORT_NUM = 8545
DISCOVERY_PORT_NUM = 30303
ENGINE_RPC_PORT_NUM = 8551
METRICS_PORT_NUM = 9001
# The min/max CPU/memory that the execution node can use
EXECUTION_MIN_CPU = 100
EXECUTION_MAX_CPU = 1000
EXECUTION_MIN_MEMORY = 512
EXECUTION_MAX_MEMORY = 2048
# Port IDs
WS_RPC_PORT_ID = "ws-rpc"
TCP_DISCOVERY_PORT_ID = "tcp-discovery"
UDP_DISCOVERY_PORT_ID = "udp-discovery"
ENGINE_RPC_PORT_ID = "engine-rpc"
METRICS_PORT_ID = "metrics"
PRIVATE_IP_ADDRESS_PLACEHOLDER = "KURTOSIS_IP_ADDR_PLACEHOLDER"
USED_PORTS = {
WS_RPC_PORT_ID: shared_utils.new_port_spec(
WS_RPC_PORT_NUM, shared_utils.TCP_PROTOCOL
),
TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
DISCOVERY_PORT_NUM, shared_utils.TCP_PROTOCOL
),
UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
DISCOVERY_PORT_NUM, shared_utils.UDP_PROTOCOL
),
ENGINE_RPC_PORT_ID: shared_utils.new_port_spec(
ENGINE_RPC_PORT_NUM, shared_utils.TCP_PROTOCOL
),
METRICS_PORT_ID: shared_utils.new_port_spec(
METRICS_PORT_NUM, shared_utils.TCP_PROTOCOL
),
}
ENTRYPOINT_ARGS = ["sh", "-c"]
ERIGON_LOG_LEVELS = {
package_io.GLOBAL_CLIENT_LOG_LEVEL.error: "1",
package_io.GLOBAL_CLIENT_LOG_LEVEL.warn: "2",
package_io.GLOBAL_CLIENT_LOG_LEVEL.info: "3",
package_io.GLOBAL_CLIENT_LOG_LEVEL.debug: "4",
package_io.GLOBAL_CLIENT_LOG_LEVEL.trace: "5",
}
def launch(
plan,
launcher,
service_name,
image,
participant_log_level,
global_log_level,
existing_el_clients,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
):
log_level = input_parser.get_client_log_level_or_default(
participant_log_level, global_log_level, ERIGON_LOG_LEVELS
)
el_min_cpu = el_min_cpu if int(el_min_cpu) > 0 else EXECUTION_MIN_CPU
el_max_cpu = el_max_cpu if int(el_max_cpu) > 0 else EXECUTION_MAX_CPU
el_min_mem = el_min_mem if int(el_min_mem) > 0 else EXECUTION_MIN_MEMORY
el_max_mem = el_max_mem if int(el_max_mem) > 0 else EXECUTION_MAX_MEMORY
config, jwt_secret_json_filepath_on_client = get_config(
launcher.network_id,
launcher.el_genesis_data,
image,
existing_el_clients,
log_level,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
)
service = plan.add_service(service_name, config)
enode, enr = el_admin_node_info.get_enode_enr_for_node(
plan, service_name, WS_RPC_PORT_ID
)
jwt_secret = shared_utils.read_file_from_service(
plan, service_name, jwt_secret_json_filepath_on_client
)
metrics_url = "{0}:{1}".format(service.ip_address, METRICS_PORT_NUM)
erigon_metrics_info = node_metrics.new_node_metrics_info(
service_name, METRICS_PATH, metrics_url
)
return el_client_context.new_el_client_context(
"erigon",
enr,
enode,
service.ip_address,
WS_RPC_PORT_NUM,
WS_RPC_PORT_NUM,
ENGINE_RPC_PORT_NUM,
jwt_secret,
service_name,
[erigon_metrics_info],
)
def get_config(
network_id,
genesis_data,
image,
existing_el_clients,
verbosity_level,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
):
network_id = network_id
genesis_json_filepath_on_client = shared_utils.path_join(
GENESIS_DATA_MOUNT_DIRPATH, genesis_data.erigon_genesis_json_relative_filepath
)
jwt_secret_json_filepath_on_client = shared_utils.path_join(
GENESIS_DATA_MOUNT_DIRPATH, genesis_data.jwt_secret_relative_filepath
)
init_datadir_cmd_str = "erigon init --datadir={0} {1}".format(
EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER,
genesis_json_filepath_on_client,
)
# TODO remove this based on https://github.com/kurtosis-tech/eth2-merge-kurtosis-module/issues/152
if len(existing_el_clients) == 0:
fail("Erigon needs at least one node to exist, which it treats as the bootnode")
boot_node_1 = existing_el_clients[0]
cmd = [
"erigon",
"--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",
"--allow-insecure-unlock",
"--nat=extip:" + PRIVATE_IP_ADDRESS_PLACEHOLDER,
"--http",
"--http.addr=0.0.0.0",
"--http.corsdomain=*",
"--http.port={0}".format(WS_RPC_PORT_NUM),
"--authrpc.jwtsecret={0}".format(jwt_secret_json_filepath_on_client),
"--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),
]
if len(existing_el_clients) > 0:
cmd.append(
"--bootnodes="
+ ",".join(
[
ctx.enode
for ctx in existing_el_clients[: package_io.MAX_ENODE_ENTRIES]
]
)
)
cmd.append(
"--staticpeers="
+ ",".join(
[
ctx.enode
for ctx in existing_el_clients[: package_io.MAX_ENODE_ENTRIES]
]
)
)
if len(extra_params) > 0:
# this is a repeated<proto type>, we convert it into Starlark
cmd.extend([param for param in extra_params])
command_arg = [init_datadir_cmd_str, " ".join(cmd)]
command_arg_str = " && ".join(command_arg)
return (
ServiceConfig(
image=image,
ports=USED_PORTS,
cmd=[command_arg_str],
files={GENESIS_DATA_MOUNT_DIRPATH: genesis_data.files_artifact_uuid},
entrypoint=ENTRYPOINT_ARGS,
private_ip_address_placeholder=PRIVATE_IP_ADDRESS_PLACEHOLDER,
min_cpu=el_min_cpu,
max_cpu=el_max_cpu,
min_memory=el_min_mem,
max_memory=el_max_mem,
env_vars=extra_env_vars,
),
jwt_secret_json_filepath_on_client,
)
def new_erigon_launcher(network_id, el_genesis_data):
return struct(
network_id=network_id,
el_genesis_data=el_genesis_data,
)
shared_utils = import_module(
"github.com/kurtosis-tech/eth2-package/src/shared_utils/shared_utils.star"
)
input_parser = import_module(
"github.com/kurtosis-tech/eth2-package/src/package_io/parse_input.star"
)
el_client_context = import_module(
"github.com/kurtosis-tech/eth2-package/src/el/el_client_context.star"
)
el_admin_node_info = import_module(
"github.com/kurtosis-tech/eth2-package/src/el/el_admin_node_info.star"
)
node_metrics = import_module(
"github.com/kurtosis-tech/eth2-package/src/node_metrics_info.star"
)
package_io = import_module(
"github.com/kurtosis-tech/eth2-package/src/package_io/constants.star"
)
RPC_PORT_NUM = 8545
WS_PORT_NUM = 8546
WS_PORT_ENGINE_NUM = 8547
DISCOVERY_PORT_NUM = 30303
ENGINE_RPC_PORT_NUM = 8551
METRICS_PORT_NUM = 9001
# The min/max CPU/memory that the execution node can use
EXECUTION_MIN_CPU = 100
EXECUTION_MAX_CPU = 1000
EXECUTION_MIN_MEMORY = 256
EXECUTION_MAX_MEMORY = 1024
# Port IDs
RPC_PORT_ID = "rpc"
WS_PORT_ID = "ws"
TCP_DISCOVERY_PORT_ID = "tcp-discovery"
UDP_DISCOVERY_PORT_ID = "udp-discovery"
ENGINE_RPC_PORT_ID = "engine-rpc"
WS_PORT_ENGINE_ID = "ws-engine"
METRICS_PORT_ID = "metrics"
GENESIS_DATA_MOUNT_DIRPATH = "/genesis"
PREFUNDED_KEYS_MOUNT_DIRPATH = "/prefunded-keys"
METRICS_PATH = "/metrics"
# The dirpath of the execution data directory on the client container
EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/execution-data"
PRIVATE_IP_ADDRESS_PLACEHOLDER = "KURTOSIS_IP_ADDR_PLACEHOLDER"
USED_PORTS = {
RPC_PORT_ID: shared_utils.new_port_spec(RPC_PORT_NUM, shared_utils.TCP_PROTOCOL),
WS_PORT_ID: shared_utils.new_port_spec(WS_PORT_NUM, shared_utils.TCP_PROTOCOL),
WS_PORT_ENGINE_ID: shared_utils.new_port_spec(
WS_PORT_ENGINE_NUM, shared_utils.TCP_PROTOCOL
),
TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
DISCOVERY_PORT_NUM, shared_utils.TCP_PROTOCOL
),
UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
DISCOVERY_PORT_NUM, shared_utils.UDP_PROTOCOL
),
ENGINE_RPC_PORT_ID: shared_utils.new_port_spec(
ENGINE_RPC_PORT_NUM, shared_utils.TCP_PROTOCOL
),
# METRICS_PORT_ID: shared_utils.new_port_spec(METRICS_PORT_NUM, shared_utils.TCP_PROTOCOL)
}
ENTRYPOINT_ARGS = []
VERBOSITY_LEVELS = {
package_io.GLOBAL_CLIENT_LOG_LEVEL.error: "error",
package_io.GLOBAL_CLIENT_LOG_LEVEL.warn: "warn",
package_io.GLOBAL_CLIENT_LOG_LEVEL.info: "info",
package_io.GLOBAL_CLIENT_LOG_LEVEL.debug: "debug",
package_io.GLOBAL_CLIENT_LOG_LEVEL.trace: "trace",
}
def launch(
plan,
launcher,
service_name,
image,
participant_log_level,
global_log_level,
# If empty then the node will be launched as a bootnode
existing_el_clients,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
):
log_level = input_parser.get_client_log_level_or_default(
participant_log_level, global_log_level, VERBOSITY_LEVELS
)
el_min_cpu = el_min_cpu if int(el_min_cpu) > 0 else EXECUTION_MIN_CPU
el_max_cpu = el_max_cpu if int(el_max_cpu) > 0 else EXECUTION_MAX_CPU
el_min_mem = el_min_mem if int(el_min_mem) > 0 else EXECUTION_MIN_MEMORY
el_max_mem = el_max_mem if int(el_max_mem) > 0 else EXECUTION_MAX_MEMORY
config, jwt_secret_json_filepath_on_client = get_config(
launcher.el_genesis_data,
image,
existing_el_clients,
log_level,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
)
service = plan.add_service(service_name, config)
enode = el_admin_node_info.get_enode_for_node(plan, service_name, RPC_PORT_ID)
jwt_secret = shared_utils.read_file_from_service(
plan, service_name, jwt_secret_json_filepath_on_client
)
# TODO: Passing empty string for metrics_url for now https://github.com/kurtosis-tech/eth2-package/issues/127
# metrics_url = "http://{0}:{1}".format(service.ip_address, METRICS_PORT_NUM)
ethjs_metrics_info = None
return el_client_context.new_el_client_context(
"ethereumjs",
"", # ethereumjs has no enr
enode,
service.ip_address,
RPC_PORT_NUM,
WS_PORT_NUM,
ENGINE_RPC_PORT_NUM,
jwt_secret,
service_name,
[ethjs_metrics_info],
)
def get_config(
genesis_data,
image,
existing_el_clients,
verbosity_level,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
):
genesis_json_filepath_on_client = shared_utils.path_join(
GENESIS_DATA_MOUNT_DIRPATH, genesis_data.geth_genesis_json_relative_filepath
)
jwt_secret_json_filepath_on_client = shared_utils.path_join(
GENESIS_DATA_MOUNT_DIRPATH, genesis_data.jwt_secret_relative_filepath
)
cmd = [
"--gethGenesis=" + genesis_json_filepath_on_client,
"--dataDir=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER,
"--port={0}".format(DISCOVERY_PORT_NUM),
"--rpc",
"--rpcAddr=0.0.0.0",
"--rpcPort={0}".format(RPC_PORT_NUM),
"--rpcCors=*",
"--rpcEngine",
"--rpcEngineAddr=0.0.0.0",
"--rpcEnginePort={0}".format(ENGINE_RPC_PORT_NUM),
"--ws",
"--wsAddr=0.0.0.0",
"--wsPort={0}".format(WS_PORT_NUM),
"--wsEnginePort={0}".format(WS_PORT_ENGINE_NUM),
"--wsEngineAddr=0.0.0.0",
"--jwt-secret={0}".format(jwt_secret_json_filepath_on_client),
"--extIP={0}".format(PRIVATE_IP_ADDRESS_PLACEHOLDER),
"--sync=full",
"--isSingleNode=true",
"--logLevel={0}".format(verbosity_level),
]
if len(existing_el_clients) > 0:
cmd.append(
"--bootnodes="
+ ",".join(
[
ctx.enode
for ctx in existing_el_clients[: package_io.MAX_ENODE_ENTRIES]
]
)
)
if len(extra_params) > 0:
# this is a repeated<proto type>, we convert it into Starlark
cmd.extend([param for param in extra_params])
return (
ServiceConfig(
image=image,
ports=USED_PORTS,
cmd=cmd,
files={
GENESIS_DATA_MOUNT_DIRPATH: genesis_data.files_artifact_uuid,
},
entrypoint=ENTRYPOINT_ARGS,
private_ip_address_placeholder=PRIVATE_IP_ADDRESS_PLACEHOLDER,
min_cpu=el_min_cpu,
max_cpu=el_max_cpu,
min_memory=el_min_mem,
max_memory=el_max_mem,
env_vars=extra_env_vars,
),
jwt_secret_json_filepath_on_client,
)
def new_ethereumjs_launcher(el_genesis_data):
return struct(
el_genesis_data=el_genesis_data,
)
This diff is collapsed.
shared_utils = import_module(
"github.com/kurtosis-tech/eth2-package/src/shared_utils/shared_utils.star"
)
input_parser = import_module(
"github.com/kurtosis-tech/eth2-package/src/package_io/parse_input.star"
)
el_client_context = import_module(
"github.com/kurtosis-tech/eth2-package/src/el/el_client_context.star"
)
el_admin_node_info = import_module(
"github.com/kurtosis-tech/eth2-package/src/el/el_admin_node_info.star"
)
node_metrics = import_module(
"github.com/kurtosis-tech/eth2-package/src/node_metrics_info.star"
)
package_io = import_module(
"github.com/kurtosis-tech/eth2-package/src/package_io/constants.star"
)
# The dirpath of the execution data directory on the client container
EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/execution-data"
KZG_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/genesis/output/trusted_setup.txt"
GENESIS_DATA_MOUNT_DIRPATH = "/genesis"
METRICS_PATH = "/metrics"
RPC_PORT_NUM = 8545
WS_PORT_NUM = 8546
DISCOVERY_PORT_NUM = 30303
ENGINE_RPC_PORT_NUM = 8551
METRICS_PORT_NUM = 9001
# The min/max CPU/memory that the execution node can use
EXECUTION_MIN_CPU = 100
EXECUTION_MAX_CPU = 1000
EXECUTION_MIN_MEMORY = 512
EXECUTION_MAX_MEMORY = 2048
# Port IDs
RPC_PORT_ID = "rpc"
WS_PORT_ID = "ws"
TCP_DISCOVERY_PORT_ID = "tcp-discovery"
UDP_DISCOVERY_PORT_ID = "udp-discovery"
ENGINE_RPC_PORT_ID = "engine-rpc"
METRICS_PORT_ID = "metrics"
PRIVATE_IP_ADDRESS_PLACEHOLDER = "KURTOSIS_IP_ADDR_PLACEHOLDER"
USED_PORTS = {
RPC_PORT_ID: shared_utils.new_port_spec(RPC_PORT_NUM, shared_utils.TCP_PROTOCOL),
WS_PORT_ID: shared_utils.new_port_spec(WS_PORT_NUM, shared_utils.TCP_PROTOCOL),
TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
DISCOVERY_PORT_NUM, shared_utils.TCP_PROTOCOL
),
UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
DISCOVERY_PORT_NUM, shared_utils.UDP_PROTOCOL
),
ENGINE_RPC_PORT_ID: shared_utils.new_port_spec(
ENGINE_RPC_PORT_NUM, shared_utils.TCP_PROTOCOL
),
METRICS_PORT_ID: shared_utils.new_port_spec(
METRICS_PORT_NUM, shared_utils.TCP_PROTOCOL
),
}
NETHERMIND_LOG_LEVELS = {
package_io.GLOBAL_CLIENT_LOG_LEVEL.error: "ERROR",
package_io.GLOBAL_CLIENT_LOG_LEVEL.warn: "WARN",
package_io.GLOBAL_CLIENT_LOG_LEVEL.info: "INFO",
package_io.GLOBAL_CLIENT_LOG_LEVEL.debug: "DEBUG",
package_io.GLOBAL_CLIENT_LOG_LEVEL.trace: "TRACE",
}
def launch(
plan,
launcher,
service_name,
image,
participant_log_level,
global_log_level,
existing_el_clients,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
):
log_level = input_parser.get_client_log_level_or_default(
participant_log_level, global_log_level, NETHERMIND_LOG_LEVELS
)
el_min_cpu = el_min_cpu if int(el_min_cpu) > 0 else EXECUTION_MIN_CPU
el_max_cpu = el_max_cpu if int(el_max_cpu) > 0 else EXECUTION_MAX_CPU
el_min_mem = el_min_mem if int(el_min_mem) > 0 else EXECUTION_MIN_MEMORY
el_max_mem = el_max_mem if int(el_max_mem) > 0 else EXECUTION_MAX_MEMORY
config, jwt_secret_json_filepath_on_client = get_config(
launcher.el_genesis_data,
image,
existing_el_clients,
log_level,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
)
service = plan.add_service(service_name, config)
enode = el_admin_node_info.get_enode_for_node(plan, service_name, RPC_PORT_ID)
jwt_secret = shared_utils.read_file_from_service(
plan, service_name, jwt_secret_json_filepath_on_client
)
metrics_url = "{0}:{1}".format(service.ip_address, METRICS_PORT_NUM)
nethermind_metrics_info = node_metrics.new_node_metrics_info(
service_name, METRICS_PATH, metrics_url
)
return el_client_context.new_el_client_context(
"nethermind",
"", # nethermind has no ENR in the eth2-merge-kurtosis-module either
# Nethermind node info endpoint doesn't return ENR field https://docs.nethermind.io/nethermind/ethereum-client/json-rpc/admin
enode,
service.ip_address,
RPC_PORT_NUM,
WS_PORT_NUM,
ENGINE_RPC_PORT_NUM,
jwt_secret,
service_name,
[nethermind_metrics_info],
)
def get_config(
genesis_data,
image,
existing_el_clients,
log_level,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
):
genesis_json_filepath_on_client = shared_utils.path_join(
GENESIS_DATA_MOUNT_DIRPATH,
genesis_data.nethermind_genesis_json_relative_filepath,
)
jwt_secret_json_filepath_on_client = shared_utils.path_join(
GENESIS_DATA_MOUNT_DIRPATH, genesis_data.jwt_secret_relative_filepath
)
cmd = [
"--log=" + log_level,
"--datadir=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER,
"--Init.ChainSpecPath=" + genesis_json_filepath_on_client,
"--Init.WebSocketsEnabled=true",
"--Init.KzgSetupPath=" + KZG_DATA_DIRPATH_ON_CLIENT_CONTAINER,
"--config=none.cfg",
"--JsonRpc.Enabled=true",
"--JsonRpc.EnabledModules=net,eth,consensus,subscribe,web3,admin",
"--JsonRpc.Host=0.0.0.0",
"--JsonRpc.Port={0}".format(RPC_PORT_NUM),
"--JsonRpc.WebSocketsPort={0}".format(WS_PORT_NUM),
"--JsonRpc.EngineHost=0.0.0.0",
"--JsonRpc.EnginePort={0}".format(ENGINE_RPC_PORT_NUM),
"--Network.ExternalIp={0}".format(PRIVATE_IP_ADDRESS_PLACEHOLDER),
"--Network.DiscoveryPort={0}".format(DISCOVERY_PORT_NUM),
"--Network.P2PPort={0}".format(DISCOVERY_PORT_NUM),
"--JsonRpc.JwtSecretFile={0}".format(jwt_secret_json_filepath_on_client),
"--Network.OnlyStaticPeers=true",
"--Metrics.Enabled=true",
"--Metrics.ExposePort={0}".format(METRICS_PORT_NUM),
]
if len(existing_el_clients) > 0:
cmd.append(
"--Network.StaticPeers="
+ ",".join(
[
ctx.enode
for ctx in existing_el_clients[: package_io.MAX_ENODE_ENTRIES]
]
)
)
if len(extra_params) > 0:
# this is a repeated<proto type>, we convert it into Starlark
cmd.extend([param for param in extra_params])
return (
ServiceConfig(
image=image,
ports=USED_PORTS,
cmd=cmd,
files={
GENESIS_DATA_MOUNT_DIRPATH: genesis_data.files_artifact_uuid,
},
private_ip_address_placeholder=PRIVATE_IP_ADDRESS_PLACEHOLDER,
min_cpu=el_min_cpu,
max_cpu=el_max_cpu,
min_memory=el_min_mem,
max_memory=el_max_mem,
env_vars=extra_env_vars,
),
jwt_secret_json_filepath_on_client,
)
def new_nethermind_launcher(el_genesis_data):
return struct(el_genesis_data=el_genesis_data)
shared_utils = import_module(
"github.com/kurtosis-tech/eth2-package/src/shared_utils/shared_utils.star"
)
input_parser = import_module(
"github.com/kurtosis-tech/eth2-package/src/package_io/parse_input.star"
)
el_client_context = import_module(
"github.com/kurtosis-tech/eth2-package/src/el/el_client_context.star"
)
el_admin_node_info = import_module(
"github.com/kurtosis-tech/eth2-package/src/el/el_admin_node_info.star"
)
node_metrics = import_module(
"github.com/kurtosis-tech/eth2-package/src/node_metrics_info.star"
)
package_io = import_module(
"github.com/kurtosis-tech/eth2-package/src/package_io/constants.star"
)
RPC_PORT_NUM = 8545
WS_PORT_NUM = 8546
DISCOVERY_PORT_NUM = 30303
ENGINE_RPC_PORT_NUM = 8551
METRICS_PORT_NUM = 9001
# The min/max CPU/memory that the execution node can use
EXECUTION_MIN_CPU = 100
EXECUTION_MAX_CPU = 1000
EXECUTION_MIN_MEMORY = 256
EXECUTION_MAX_MEMORY = 1024
# Port IDs
RPC_PORT_ID = "rpc"
WS_PORT_ID = "ws"
TCP_DISCOVERY_PORT_ID = "tcp-discovery"
UDP_DISCOVERY_PORT_ID = "udp-discovery"
ENGINE_RPC_PORT_ID = "engine-rpc"
METRICS_PORT_ID = "metrics"
# Paths
METRICS_PATH = "/metrics"
GENESIS_DATA_MOUNT_DIRPATH = "/genesis"
PREFUNDED_KEYS_MOUNT_DIRPATH = "/prefunded-keys"
# The dirpath of the execution data directory on the client container
EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER = "/execution-data"
PRIVATE_IP_ADDRESS_PLACEHOLDER = "KURTOSIS_IP_ADDR_PLACEHOLDER"
USED_PORTS = {
RPC_PORT_ID: shared_utils.new_port_spec(RPC_PORT_NUM, shared_utils.TCP_PROTOCOL),
WS_PORT_ID: shared_utils.new_port_spec(WS_PORT_NUM, shared_utils.TCP_PROTOCOL),
TCP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
DISCOVERY_PORT_NUM, shared_utils.TCP_PROTOCOL
),
UDP_DISCOVERY_PORT_ID: shared_utils.new_port_spec(
DISCOVERY_PORT_NUM, shared_utils.UDP_PROTOCOL
),
ENGINE_RPC_PORT_ID: shared_utils.new_port_spec(
ENGINE_RPC_PORT_NUM, shared_utils.TCP_PROTOCOL
),
METRICS_PORT_ID: shared_utils.new_port_spec(
METRICS_PORT_NUM, shared_utils.TCP_PROTOCOL
),
}
ENTRYPOINT_ARGS = ["sh", "-c"]
VERBOSITY_LEVELS = {
package_io.GLOBAL_CLIENT_LOG_LEVEL.error: "v",
package_io.GLOBAL_CLIENT_LOG_LEVEL.warn: "vv",
package_io.GLOBAL_CLIENT_LOG_LEVEL.info: "vvv",
package_io.GLOBAL_CLIENT_LOG_LEVEL.debug: "vvvv",
package_io.GLOBAL_CLIENT_LOG_LEVEL.trace: "vvvvv",
}
def launch(
plan,
launcher,
service_name,
image,
participant_log_level,
global_log_level,
# If empty then the node will be launched as a bootnode
existing_el_clients,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
):
log_level = input_parser.get_client_log_level_or_default(
participant_log_level, global_log_level, VERBOSITY_LEVELS
)
el_min_cpu = el_min_cpu if int(el_min_cpu) > 0 else EXECUTION_MIN_CPU
el_max_cpu = el_max_cpu if int(el_max_cpu) > 0 else EXECUTION_MAX_CPU
el_min_mem = el_min_mem if int(el_min_mem) > 0 else EXECUTION_MIN_MEMORY
el_max_mem = el_max_mem if int(el_max_mem) > 0 else EXECUTION_MAX_MEMORY
config, jwt_secret_json_filepath_on_client = get_config(
launcher.el_genesis_data,
image,
existing_el_clients,
log_level,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
)
service = plan.add_service(service_name, config)
enode = el_admin_node_info.get_enode_for_node(plan, service_name, RPC_PORT_ID)
jwt_secret = shared_utils.read_file_from_service(
plan, service_name, jwt_secret_json_filepath_on_client
)
metric_url = "{0}:{1}".format(service.ip_address, METRICS_PORT_NUM)
reth_metrics_info = node_metrics.new_node_metrics_info(
service_name, METRICS_PATH, metric_url
)
return el_client_context.new_el_client_context(
"reth",
"", # reth has no enr
enode,
service.ip_address,
RPC_PORT_NUM,
WS_PORT_NUM,
ENGINE_RPC_PORT_NUM,
jwt_secret,
service_name,
[reth_metrics_info],
)
def get_config(
genesis_data,
image,
existing_el_clients,
verbosity_level,
el_min_cpu,
el_max_cpu,
el_min_mem,
el_max_mem,
extra_params,
extra_env_vars,
):
genesis_json_filepath_on_client = shared_utils.path_join(
GENESIS_DATA_MOUNT_DIRPATH, genesis_data.geth_genesis_json_relative_filepath
)
jwt_secret_json_filepath_on_client = shared_utils.path_join(
GENESIS_DATA_MOUNT_DIRPATH, genesis_data.jwt_secret_relative_filepath
)
init_datadir_cmd_str = "reth init --datadir={0} --chain={1}".format(
EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER,
genesis_json_filepath_on_client,
)
cmd = [
"reth",
"node",
"-{0}".format(verbosity_level),
"--datadir=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER,
"--chain=" + genesis_json_filepath_on_client,
"--http",
"--http.port={0}".format(RPC_PORT_NUM),
"--http.addr=0.0.0.0",
"--http.corsdomain=*",
# WARNING: The admin info endpoint is enabled so that we can easily get ENR/enode, which means
# that users should NOT store private information in these Kurtosis nodes!
"--http.api=admin,net,eth",
"--ws",
"--ws.addr=0.0.0.0",
"--ws.port={0}".format(WS_PORT_NUM),
"--ws.api=net,eth",
"--ws.origins=*",
"--nat=extip:" + PRIVATE_IP_ADDRESS_PLACEHOLDER,
"--authrpc.port={0}".format(ENGINE_RPC_PORT_NUM),
"--authrpc.jwtsecret={0}".format(jwt_secret_json_filepath_on_client),
"--authrpc.addr=0.0.0.0",
"--metrics=0.0.0.0:{0}".format(METRICS_PORT_NUM),
]
if len(existing_el_clients) > 0:
cmd.append(
"--bootnodes="
+ ",".join(
[
ctx.enode
for ctx in existing_el_clients[: package_io.MAX_ENODE_ENTRIES]
]
)
)
if len(extra_params) > 0:
# this is a repeated<proto type>, we convert it into Starlark
cmd.extend([param for param in extra_params])
cmd_str = " ".join(cmd)
subcommand_strs = [
init_datadir_cmd_str,
cmd_str,
]
command_str = " && ".join(subcommand_strs)
return (
ServiceConfig(
image=image,
ports=USED_PORTS,
cmd=[command_str],
files={
GENESIS_DATA_MOUNT_DIRPATH: genesis_data.files_artifact_uuid,
},
entrypoint=ENTRYPOINT_ARGS,
private_ip_address_placeholder=PRIVATE_IP_ADDRESS_PLACEHOLDER,
min_cpu=el_min_cpu,
max_cpu=el_max_cpu,
min_memory=el_min_mem,
max_memory=el_max_mem,
env_vars=extra_env_vars,
),
jwt_secret_json_filepath_on_client,
)
def new_reth_launcher(el_genesis_data):
return struct(
el_genesis_data=el_genesis_data,
)
...@@ -45,7 +45,7 @@ def get_config(mev_boost_launcher, network_id, mev_boost_image): ...@@ -45,7 +45,7 @@ def get_config(mev_boost_launcher, network_id, mev_boost_image):
cmd=command, cmd=command,
env_vars={ env_vars={
# TODO(maybe) remove the hardcoding # TODO(maybe) remove the hardcoding
# This is set to match this file https://github.com/kurtosis-tech/eth-network-package/blob/main/static_files/genesis-generation-config/cl/config.yaml.tmpl#L11 # This is set to match this file https://github.com/kurtosis-tech/eth2-package/blob/main/static_files/genesis-generation-config/cl/config.yaml.tmpl#L11
# latest-notes # latest-notes
# does this need genesis time to be set as well # does this need genesis time to be set as well
"GENESIS_FORK_VERSION": "0x10000038", "GENESIS_FORK_VERSION": "0x10000038",
......
# this is a dictionary as this will get serialzed to JSON
def new_node_metrics_info(name, path, url):
return {"name": name, "path": path, "url": url}
EL_CLIENT_TYPE = struct( EL_CLIENT_TYPE = struct(
geth="geth", erigon="erigon", nethermind="nethermind", besu="besu" geth="geth",
erigon="erigon",
nethermind="nethermind",
besu="besu",
reth="reth",
ethereumjs="ethereumjs",
) )
CL_CLIENT_TYPE = struct( CL_CLIENT_TYPE = struct(
...@@ -17,3 +22,13 @@ GLOBAL_CLIENT_LOG_LEVEL = struct( ...@@ -17,3 +22,13 @@ GLOBAL_CLIENT_LOG_LEVEL = struct(
debug="debug", debug="debug",
trace="trace", trace="trace",
) )
VALIDATING_REWARDS_ACCOUNT = "0x878705ba3f8Bc32FCf7F4CAa1A35E72AF65CF766"
MAX_ENR_ENTRIES = 20
MAX_ENODE_ENTRIES = 20
GENESIS_VALIDATORS_ROOT_PLACEHOLDER = "GENESIS_VALIDATORS_ROOT_PLACEHOLDER"
DEFAULT_SNOOPER_IMAGE = "parithoshj/json_rpc_snoop:v1.0.0-x86"
ARCHIVE_MODE = True
This diff is collapsed.
def new_participant(
el_client_type,
cl_client_type,
el_client_context,
cl_client_context,
snooper_engine_context,
):
return struct(
el_client_type=el_client_type,
cl_client_type=cl_client_type,
el_client_context=el_client_context,
cl_client_context=cl_client_context,
snooper_engine_context=snooper_engine_context,
)
This diff is collapsed.
def new_cl_genesis_data(
files_artifact_uuid,
jwt_secret_rel_filepath,
config_yml_rel_filepath,
genesis_ssz_rel_filepath,
genesis_validators_root="",
):
return struct(
files_artifact_uuid=files_artifact_uuid,
jwt_secret_rel_filepath=jwt_secret_rel_filepath,
config_yml_rel_filepath=config_yml_rel_filepath,
genesis_ssz_rel_filepath=genesis_ssz_rel_filepath,
genesis_validators_root=genesis_validators_root,
)
# Package object containing information about the keystores that were generated for validators
# during genesis creation
def new_generate_keystores_result(
prysm_password_artifact_uuid, prysm_password_relative_filepath, per_node_keystores
):
return struct(
# Files artifact UUID where the Prysm password is stored
prysm_password_artifact_uuid=prysm_password_artifact_uuid,
# Relative to root of files artifact
prysm_password_relative_filepath=prysm_password_relative_filepath,
# Contains keystores-per-client-type for each node in the network
per_node_keystores=per_node_keystores,
)
# One of these will be created per node we're trying to start
def new_keystore_files(
files_artifact_uuid,
raw_keys_relative_dirpath,
raw_secrets_relative_dirpath,
nimbus_keys_relative_dirpath,
prysm_relative_dirpath,
teku_keys_relative_dirpath,
teku_secrets_relative_dirpath,
):
return struct(
files_artifact_uuid=files_artifact_uuid,
# ------------ All directories below are relative to the root of the files artifact ----------------
raw_keys_relative_dirpath=raw_keys_relative_dirpath,
raw_secrets_relative_dirpath=raw_secrets_relative_dirpath,
nimbus_keys_relative_dirpath=nimbus_keys_relative_dirpath,
prysm_relative_dirpath=prysm_relative_dirpath,
teku_keys_relative_dirpath=teku_keys_relative_dirpath,
teku_secrets_relative_dirpath=teku_secrets_relative_dirpath,
)
def new_el_genesis_data(
files_artifact_uuid,
jwt_secret_relative_filepath,
geth_genesis_json_relative_filepath,
erigon_genesis_json_relative_filepath,
nethermind_genesis_json_relative_filepath,
besu_genesis_json_relative_filepath,
):
return struct(
files_artifact_uuid=files_artifact_uuid,
jwt_secret_relative_filepath=jwt_secret_relative_filepath,
geth_genesis_json_relative_filepath=geth_genesis_json_relative_filepath,
erigon_genesis_json_relative_filepath=erigon_genesis_json_relative_filepath,
nethermind_genesis_json_relative_filepath=nethermind_genesis_json_relative_filepath,
besu_genesis_json_relative_filepath=besu_genesis_json_relative_filepath,
)
def new_prefunded_account(address, private_key):
return struct(address=address, private_key=private_key)
# This information was generated by:
# 1) Installing Wagyu: https://github.com/AleoHQ/wagyu
# 2) Running `wagyu ethereum import-hd -m MNEMONIC_FROM_GENESIS -d PREFUNDED_ACCOUNT_DERIVATION_PATH`
# 3) Copying the outputted information
PRE_FUNDED_ACCOUNTS = [
# UTC--2021-12-22T19-14-08.590377700Z--878705ba3f8bc32fcf7f4caa1a35e72af65cf766
# m/44'/60'/0'/0/0
new_prefunded_account(
"0x878705ba3f8Bc32FCf7F4CAa1A35E72AF65CF766",
"ef5177cd0b6b21c87db5a0bf35d4084a8a57a9d6a064f86d51ac85f2b873a4e2",
),
# UTC--2021-12-22T19-14-13.423928600Z--4e9a3d9d1cd2a2b2371b8b3f489ae72259886f1a
# m/44'/60'/0'/0/1
new_prefunded_account(
"0x4E9A3d9D1cd2A2b2371b8b3F489aE72259886f1A",
"48fcc39ae27a0e8bf0274021ae6ebd8fe4a0e12623d61464c498900b28feb567",
),
# UTC--2021-12-22T19-14-16.977667900Z--df8466f277964bb7a0ffd819403302c34dcd530a
# m/44'/60'/0'/0/2
new_prefunded_account(
"0xdF8466f277964Bb7a0FFD819403302C34DCD530A",
"7988b3a148716ff800414935b305436493e1f25237a2a03e5eebc343735e2f31",
),
# UTC--2021-12-22T19-14-21.531351400Z--5c613e39fc0ad91afda24587e6f52192d75fba50
# m/44'/60'/0'/0/3
new_prefunded_account(
"0x5c613e39Fc0Ad91AfDA24587e6f52192d75FBA50",
"b3c409b6b0b3aa5e65ab2dc1930534608239a478106acf6f3d9178e9f9b00b35",
),
# UTC--2021-12-22T19-14-25.369306000Z--375ae6107f8cc4cf34842b71c6f746a362ad8eac
# m/44'/60'/0'/0/4
new_prefunded_account(
"0x375ae6107f8cC4cF34842B71C6F746a362Ad8EAc",
"df9bb6de5d3dc59595bcaa676397d837ff49441d211878c024eabda2cd067c9f",
),
# UTC--2021-12-22T19-14-33.473095100Z--1f6298457c5d76270325b724da5d1953923a6b88
# m/44'/60'/0'/0/5
new_prefunded_account(
"0x1F6298457C5d76270325B724Da5d1953923a6B88",
"7da08f856b5956d40a72968f93396f6acff17193f013e8053f6fbb6c08c194d6",
),
# Use geth account import to generate the key inside genesis-prefunded-keys/geth
# use password "password"
# UTC--2023-05-19T11-17-22.403583626Z--fe08e6f330f4e5e624ad759625b71b2e52594feb
# m/44'/60'/0'/0/6
new_prefunded_account(
"0xFE08e6f330F4E5E624Ad759625B71B2e52594FEB",
"17fdf89989597e8bcac6cdfcc001b6241c64cece2c358ffc818b72ca70f5e1ce",
),
]
SERVICE_NAME_PREFIX = "prelaunch-data-generator-"
# We use Docker exec commands to run the commands we need, so we override the default
ENTRYPOINT_ARGS = [
"sleep",
"999999",
]
# Launches a prelaunch data generator IMAGE, for use in various of the genesis generation
def launch_prelaunch_data_generator(
plan,
files_artifact_mountpoints,
service_name_suffix,
capella_fork_epoch,
electra_fork_epoch,
):
config = get_config(
files_artifact_mountpoints, capella_fork_epoch, electra_fork_epoch
)
service_name = "{0}{1}".format(
SERVICE_NAME_PREFIX,
service_name_suffix,
)
plan.add_service(service_name, config)
return service_name
def launch_prelaunch_data_generator_parallel(
plan,
files_artifact_mountpoints,
service_name_suffixes,
capella_fork_epoch,
electra_fork_epoch,
):
config = get_config(
files_artifact_mountpoints, capella_fork_epoch, electra_fork_epoch
)
service_names = [
"{0}{1}".format(
SERVICE_NAME_PREFIX,
service_name_suffix,
)
for service_name_suffix in service_name_suffixes
]
services_to_add = {service_name: config for service_name in service_names}
plan.add_services(services_to_add)
return service_names
def get_config(files_artifact_mountpoints, capella_fork_epoch, electra_fork_epoch):
if capella_fork_epoch > 0 and electra_fork_epoch == None: # we are running capella
img = "ethpandaops/ethereum-genesis-generator:1.3.4"
elif (
capella_fork_epoch == 0 and electra_fork_epoch == None
): # we are running dencun
img = "ethpandaops/ethereum-genesis-generator:2.0.0-rc.6"
else: # we are running electra
img = "ethpandaops/ethereum-genesis-generator:3.0.0-rc.2"
return ServiceConfig(
image=img,
entrypoint=ENTRYPOINT_ARGS,
files=files_artifact_mountpoints,
)
This diff is collapsed.
def new_snooper_engine_client_context(ip_addr, engine_rpc_port_num):
return struct(
ip_addr=ip_addr,
engine_rpc_port_num=engine_rpc_port_num,
)
This diff is collapsed.
This diff is collapsed.
- mnemonic: "{{ .PreregisteredValidatorKeysMnemonic }}" # a 24 word BIP 39 mnemonic
# Number of validator keys to preregister inside the outputted CL genesis.ssz
count: {{ .NumValidatorKeysToPreregister }}
{"address":"878705ba3f8bc32fcf7f4caa1a35e72af65cf766","crypto":{"cipher":"aes-128-ctr","ciphertext":"f02daebbf456faf787c5cd61a33ce780857c1ca10b00972aa451f0e9688e4ead","cipherparams":{"iv":"ef1668814155862f0653f15dae845e58"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"55e5ee70d3e882d2f00a073eda252ff01437abf51d7bfa76c06dcc73f7e8f1a3"},"mac":"d8d04625d0769fe286756734f946c78663961b74f0caaff1d768f0d255632f04"},"id":"5fb9083a-a221-412b-b0e0-921e22cc9645","version":3}
{"address":"4e9a3d9d1cd2a2b2371b8b3f489ae72259886f1a","crypto":{"cipher":"aes-128-ctr","ciphertext":"ab715382b1e1f13d927b2e3d22e087a51ccb72b32f9bac71727ec8438ecb6d54","cipherparams":{"iv":"dee12212262986854a0bfd9a5c766ced"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"7112f2fed838981fde1ca00cdd1d95630981bd22f772666fafd0778525cf1cc4"},"mac":"2a75795bb0513859355ce2086668398ee821a2e708edd856f8a85cf638fede9a"},"id":"f849b7fe-aff7-454f-91e1-838de2a8da6b","version":3}
{"address":"df8466f277964bb7a0ffd819403302c34dcd530a","crypto":{"cipher":"aes-128-ctr","ciphertext":"322e59ab95797f2ea9a1162e3f28e2ff7e27415b6e9d7d990a197e09dc9043d7","cipherparams":{"iv":"6179d5971b93a09799ace7371801e371"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"5ac65d7e25467366764d4539e8ae0c78d31dce4002042c06d3971b103c95f2a3"},"mac":"b5d060f2c0a5f8446dd4d718eee66c7eeff3feb90aafa8201fd7501c8f5c180a"},"id":"c5fda7a7-816a-4740-8804-afdc0d410cfb","version":3}
{"address":"5c613e39fc0ad91afda24587e6f52192d75fba50","crypto":{"cipher":"aes-128-ctr","ciphertext":"4ba38c15225d92f2cbac5eafb7cf5ef358332037cd9730dce595a7a4cc3a39d0","cipherparams":{"iv":"6a83dc5b43b0c9c8948905ccc697455a"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"cdfa581366dbc4f566404b0ac64d9d0c1a8a9d24202fe3c428212f020fd6cdbb"},"mac":"95a2e987cbe87d4b532f830df8c5cabc8a7bbd4e70eda672252ed4d8b967e660"},"id":"09d1b784-fb8f-4d25-8720-a683bb0c13ab","version":3}
{"address":"375ae6107f8cc4cf34842b71c6f746a362ad8eac","crypto":{"cipher":"aes-128-ctr","ciphertext":"ab13f28ad41bcb73f5ae982a5bde37ba737515fef848ea365911be3d97682530","cipherparams":{"iv":"fb4d9bfab1d9c5d47e46052ea80275e1"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"56ba7f86161cb419f27c19b5845b6dd8033927ff0d362863e5723e3568d5d0c7"},"mac":"ad9197d47c57c601313d49fb15392a29c8a16418d1bf6f39ac3b822bd5205593"},"id":"353e4c37-a37f-4b2a-8729-81460c6a92d4","version":3}
{"address":"1f6298457c5d76270325b724da5d1953923a6b88","crypto":{"cipher":"aes-128-ctr","ciphertext":"42348bd719f9225cc91184a3daf7005a89cec8be7d907c92c57ac01f29b61e2d","cipherparams":{"iv":"ee8d92dde2c3dc230f1f6e765641e0ce"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"74992f3587a487202cd76d6aa625af6b0e5b2f68eb0ea3647edb4541ce24adb9"},"mac":"27cd4f0aa624fce848aebccbd80efda35d615da2d274cc39e5185170d2ff4017"},"id":"27bfc138-d358-4c21-b040-93458f11e4c4","version":3}
{"address":"fe08e6f330f4e5e624ad759625b71b2e52594feb","crypto":{"cipher":"aes-128-ctr","ciphertext":"df41d4a4eef8ce781354c4058eac980bd349c12b40efeba38189e3d20f65eccd","cipherparams":{"iv":"c8ee56c122b8b70ab026a80ddaeaf987"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"d284320c522d4cec86d2965f8827ca63429f95c1f0a02f410393754f44b49480"},"mac":"c8d798da5f3de89fccf0a9d502f9bfb89876bee6c86d3d9176f043d9a8310579"},"id":"c9320f41-e707-49a2-9271-660c59e3bbdc","version":3}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment