Commit 79c06978 authored by Gyanendra Mishra's avatar Gyanendra Mishra Committed by GitHub

Merge pull request #3 from kurtosis-tech/gyani/data-generator

added the data generator
parents 79731052 3bf66ded
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
### Features ### Features
- Changed the .circlei/config.yml to apply to Startosis - Changed the .circlei/config.yml to apply to Startosis
- Changed main.star to work - Added genesis_constants
- Added a lot of participant_network/pre_launch_data_generator
# 0.0.0 # 0.0.0
* Initial commit * Initial commit
module: module:
name: "github.com/kurtosis-tech/eth2-merge-startosis-module" name: "github.com/kurtosis-tech/eth2-module"
\ No newline at end of file
load("github.com/kurtosis-tech/eth2-module/src/participant_network/participant_network.star", "launch_participant_network")
def main(): def main():
print("This should work if CI is running correctly") network_params = new_network_params()
\ No newline at end of file num_participants = 2
print("Launching participant network with {0} participants and the following network params {1}".format(num_participants, json.indent(json.encode(network_params))))
launch_participant_network(num_participants, network_params)
def new_network_params():
# this is temporary till we get params working
return struct(
preregistered_validator_keys_mnemonic = "giant issue aisle success illegal bike spike question tent bar rely arctic volcano long crawl hungry vocal artwork sniff fantasy very lucky have athlete",
num_validator_keys_per_node = 64,
network_id = "3151908",
deposit_contract_address = "0x4242424242424242424242424242424242424242",
seconds_per_slot = 12,
)
...@@ -7,22 +7,10 @@ root_dirpath="$(dirname "${script_dirpath}")" ...@@ -7,22 +7,10 @@ root_dirpath="$(dirname "${script_dirpath}")"
# ==================================================================================================
# Constants
# ==================================================================================================
BUILD_SCRIPT_RELATIVE_FILEPATHS=(
"golang/scripts/build.sh"
"typescript/scripts/build.sh"
)
# ================================================================================================== # ==================================================================================================
# Main Logic # Main Logic
# ================================================================================================== # ==================================================================================================
for build_script_rel_filepath in "${BUILD_SCRIPT_RELATIVE_FILEPATHS[@]}"; do
build_script_abs_filepath="${root_dirpath}/${build_script_rel_filepath}" if ! "kurtosis" "startosis" "exec" "${root_dirpath}"; then
if ! bash "${build_script_abs_filepath}"; then echo "Error: running the startosis script"
echo "Error: Build script '${build_script_abs_filepath}' failed" >&2 fi
exit 1
fi
done
load("github.com/kurtosis-tech/eth2-module/src/participant_network/prelaunch_data_generator/cl_validator_keystores/cl_validator_keystore_generator.star", "generate_cl_validator_keystores")
load("github.com/kurtosis-tech/eth2-module/src/participant_network/prelaunch_data_generator/el_genesis/el_genesis_data_generator.star", "generate_el_genesis_data")
load("github.com/kurtosis-tech/eth2-module/src/participant_network/prelaunch_data_generator/cl_genesis/cl_genesis_data_generator.star", "generate_cl_genesis_data")
def launch_participant_network(num_participants, network_params):
print("Generating cl validator key stores")
keystore_result = generate_cl_validator_keystores(
network_params.preregistered_validator_keys_mnemonic,
num_participants,
network_params.num_validator_keys_per_node
)
print(json.indent(json.encode(keystore_result)))
genesis_timestamp = time.now().unix
print("Generating EL data")
el_genesis_generation_config_template = read_file("github.com/kurtosis-tech/eth2-module/static_files/genesis-generation-config/el/genesis-config.yaml.tmpl")
el_genesis_data = generate_el_genesis_data(
el_genesis_generation_config_template,
genesis_timestamp,
network_params.network_id,
network_params.deposit_contract_address
)
print(json.indent(json.encode(el_genesis_data)))
print("Generating CL data")
genesis_generation_config_yml_template = read_file("github.com/kurtosis-tech/eth2-module/static_files/genesis-generation-config/cl/config.yaml.tmpl")
genesis_generation_mnemonics_yml_template = read_file("github.com/kurtosis-tech/eth2-module/static_files/genesis-generation-config/cl/mnemonics.yaml.tmpl")
total_number_of_validator_keys = network_params.num_validator_keys_per_node * num_participants
cl_data = generate_cl_genesis_data(
genesis_generation_config_yml_template,
genesis_generation_mnemonics_yml_template,
el_genesis_data,
genesis_timestamp,
network_params.network_id,
network_params.deposit_contract_address,
network_params.seconds_per_slot,
network_params.preregistered_validator_keys_mnemonic,
total_number_of_validator_keys
)
print(json.indent(json.encode(cl_data)))
def new_cl_genesis_data(
files_artifact_uuid,
jwt_secret_rel_filepath,
config_yml_rel_filepath,
genesis_ssz_rel_filepath):
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,
)
load("github.com/kurtosis-tech/eth2-module/src/shared_utils/shared_utils.star", "new_template_and_data", "path_join", "path_base")
load("github.com/kurtosis-tech/eth2-module/src/participant_network/prelaunch_data_generator/cl_genesis/cl_genesis_data.star", "new_cl_genesis_data")
load("github.com/kurtosis-tech/eth2-module/src/participant_network/prelaunch_data_generator/prelaunch_data_generator_launcher/prelaunch_data_generator_launcher.star", "launch_prelaunch_data_generator")
# Needed to copy the JWT secret and the EL genesis.json file
EL_GENESIS_DIRPATH_ON_GENERATOR = "/el-genesis"
CONFIG_DIRPATH_ON_GENERATOR = "/config"
GENESIS_CONFIG_YML_FILENAME = "config.yaml" # WARNING: Do not change this! It will get copied to the CL genesis data, and the CL clients are hardcoded to look for this filename
MNEMONICS_YML_FILENAME = "mnemonics.yaml"
OUTPUT_DIRPATH_ON_GENERATOR = "/output"
TRANCHES_DIRANME = "tranches"
GENESIS_STATE_FILENAME = "genesis.ssz"
DEPLOY_BLOCK_FILENAME = "deploy_block.txt"
DEPOSIT_CONTRACT_FILENAME = "deposit_contract.txt"
# Generation constants
CL_GENESIS_GENERATION_BINARY_FILEPATH_ON_CONTAINER = "/usr/local/bin/eth2-testnet-genesis"
DEPLOY_BLOCK = "0"
ETH1_BLOCK = "0x0000000000000000000000000000000000000000000000000000000000000000"
SUCCESSFUL_EXEC_CMD_EXIT_CODE = 0
def generate_cl_genesis_data(
genesis_generation_config_yml_template,
genesis_generation_mnemonics_yml_template,
el_genesis_data,
genesis_unix_timestamp,
network_id,
deposit_contract_address,
seconds_per_slot,
preregistered_validator_keys_mnemonic,
total_num_validator_keys_to_preregister):
template_data = json.encode(new_cl_genesis_config_template_data(
network_id,
seconds_per_slot,
genesis_unix_timestamp,
total_num_validator_keys_to_preregister,
preregistered_validator_keys_mnemonic,
deposit_contract_address,
))
genesis_generation_mnemonics_template_and_data = new_template_and_data(genesis_generation_mnemonics_yml_template, template_data)
genesis_generation_config_template_and_data = new_template_and_data(genesis_generation_config_yml_template, template_data)
template_and_data_by_rel_dest_filepath = {}
template_and_data_by_rel_dest_filepath[MNEMONICS_YML_FILENAME] = genesis_generation_mnemonics_template_and_data
template_and_data_by_rel_dest_filepath[GENESIS_CONFIG_YML_FILENAME] = genesis_generation_config_template_and_data
genesis_generation_config_artifact_uuid = render_templates(template_and_data_by_rel_dest_filepath)
# TODO Make this the actual data generator
launcher_service_id = launch_prelaunch_data_generator(
{
genesis_generation_config_artifact_uuid: CONFIG_DIRPATH_ON_GENERATOR,
el_genesis_data.files_artifact_uuid: EL_GENESIS_DIRPATH_ON_GENERATOR,
},
)
# TODO add a remove_service call that removes the launcher_service_id, before the function returns
# do that when https://github.com/kurtosis-tech/kurtosis/issues/244 is closed
all_dirpaths_to_create_on_generator = [
CONFIG_DIRPATH_ON_GENERATOR,
OUTPUT_DIRPATH_ON_GENERATOR,
]
all_dirpath_creation_commands = []
for dirpath_to_create_on_generator in all_dirpaths_to_create_on_generator:
all_dirpath_creation_commands.append(
"mkdir -p {0}".format(dirpath_to_create_on_generator))
dir_creation_cmd = [
"bash",
"-c",
(" && ").join(all_dirpath_creation_commands),
]
exec(launcher_service_id, dir_creation_cmd, SUCCESSFUL_EXEC_CMD_EXIT_CODE)
# Copy files to output
all_filepaths_to_copy_to_ouptut_directory = [
path_join(CONFIG_DIRPATH_ON_GENERATOR, GENESIS_CONFIG_YML_FILENAME),
path_join(CONFIG_DIRPATH_ON_GENERATOR, MNEMONICS_YML_FILENAME),
path_join(EL_GENESIS_DIRPATH_ON_GENERATOR, el_genesis_data.jwt_secret_relative_filepath),
]
for filepath_on_generator in all_filepaths_to_copy_to_ouptut_directory:
cmd = [
"cp",
filepath_on_generator,
OUTPUT_DIRPATH_ON_GENERATOR,
]
exec(launcher_service_id, cmd, SUCCESSFUL_EXEC_CMD_EXIT_CODE)
# Generate files that need dynamic content
content_to_write_to_output_filename = {
DEPLOY_BLOCK: DEPLOY_BLOCK_FILENAME,
deposit_contract_address: DEPOSIT_CONTRACT_FILENAME,
}
for content, destFilename in content_to_write_to_output_filename.items():
destFilepath = path_join(OUTPUT_DIRPATH_ON_GENERATOR, destFilename)
cmd = [
"sh",
"-c",
"echo {0} > {1}".format(
content,
destFilepath,
)
]
exec(launcher_service_id, cmd, SUCCESSFUL_EXEC_CMD_EXIT_CODE)
cl_genesis_generation_cmd_args = [
CL_GENESIS_GENERATION_BINARY_FILEPATH_ON_CONTAINER,
"merge",
"--config", path_join(OUTPUT_DIRPATH_ON_GENERATOR, GENESIS_CONFIG_YML_FILENAME),
"--mnemonics", path_join(OUTPUT_DIRPATH_ON_GENERATOR, MNEMONICS_YML_FILENAME),
"--eth1-config", path_join(EL_GENESIS_DIRPATH_ON_GENERATOR, el_genesis_data.geth_genesis_json_relative_filepath),
"--tranches-dir", path_join(OUTPUT_DIRPATH_ON_GENERATOR, TRANCHES_DIRANME),
"--state-output", path_join(OUTPUT_DIRPATH_ON_GENERATOR, GENESIS_STATE_FILENAME)
]
exec(launcher_service_id, cl_genesis_generation_cmd_args, SUCCESSFUL_EXEC_CMD_EXIT_CODE)
cl_genesis_data_artifact_uuid = store_file_from_service(launcher_service_id, OUTPUT_DIRPATH_ON_GENERATOR)
jwt_secret_rel_filepath = path_join(
path_base(OUTPUT_DIRPATH_ON_GENERATOR),
path_base(el_genesis_data.jwt_secret_relative_filepath),
)
genesis_config_rel_filepath = path_join(
path_base(OUTPUT_DIRPATH_ON_GENERATOR),
GENESIS_CONFIG_YML_FILENAME,
)
genesis_ssz_rel_filepath = path_join(
path_base(OUTPUT_DIRPATH_ON_GENERATOR),
GENESIS_STATE_FILENAME,
)
result = new_cl_genesis_data(
cl_genesis_data_artifact_uuid,
jwt_secret_rel_filepath,
genesis_config_rel_filepath,
genesis_ssz_rel_filepath,
)
return result
def new_cl_genesis_config_template_data(network_id, seconds_per_slot, unix_timestamp, num_validator_keys_to_preregister, preregistered_validator_keys_mnemonic, deposit_contract_address):
return {
"NetworkId": network_id,
"SecondsPerSlot": seconds_per_slot,
"UnixTimestamp": unix_timestamp,
"NumValidatorKeysToPreregister": num_validator_keys_to_preregister,
"PreregisteredValidatorKeysMnemonic": preregistered_validator_keys_mnemonic,
"DepositContractAddress": deposit_contract_address,
}
load("github.com/kurtosis-tech/eth2-module/src/participant_network/prelaunch_data_generator/prelaunch_data_generator_launcher/prelaunch_data_generator_launcher.star", "launch_prelaunch_data_generator")
load("github.com/kurtosis-tech/eth2-module/src/shared_utils/shared_utils.star", "path_join", "path_base")
load("github.com/kurtosis-tech/eth2-module/src/participant_network/prelaunch_data_generator/cl_validator_keystores/keystore_files.star", "new_keystore_files")
load("github.com/kurtosis-tech/eth2-module/src/participant_network/prelaunch_data_generator/cl_validator_keystores/generate_keystores_result.star", "new_generate_keystores_result")
NODE_KEYSTORES_OUTPUT_DIRPATH_FORMAT_STR = "/node-{0}-keystores"
# Prysm keystores are encrypted with a password
PRYSM_PASSWORD = "password"
PRYSM_PASSWORD_FILEPATH_ON_GENERATOR = "/tmp/prysm-password.txt"
KEYSTORES_GENERATION_TOOL_NAME = "eth2-val-tools"
SUCCESSFUL_EXEC_CMD_EXIT_CODE = 0
RAW_KEYS_DIRNAME = "keys"
RAW_SECRETS_DIRNAME = "secrets"
NIMBUS_KEYS_DIRNAME = "nimbus-keys"
PRYSM_DIRNAME = "prysm"
TEKU_KEYS_DIRNAME = "teku-keys"
TEKU_SECRETS_DIRNAME = "teku-secrets"
# Generates keystores for the given number of nodes from the given mnemonic, where each keystore contains approximately
#
# num_keys / num_nodes keys
def generate_cl_validator_keystores(
mnemonic,
num_nodes,
num_validators_per_node):
service_id = launch_prelaunch_data_generator(
{},
)
# TODO remove the service added above
all_output_dirpaths = []
all_sub_command_strs = []
start_index = 0
stop_index = num_validators_per_node
for i in range(num_nodes):
output_dirpath = NODE_KEYSTORES_OUTPUT_DIRPATH_FORMAT_STR.format(i)
generate_keystores_cmd = "{0} keystores --insecure --prysm-pass {1} --out-loc {2} --source-mnemonic \"{3}\" --source-min {4} --source-max {5}".format(
KEYSTORES_GENERATION_TOOL_NAME,
PRYSM_PASSWORD,
output_dirpath,
mnemonic,
start_index,
stop_index,
)
all_sub_command_strs.append(generate_keystores_cmd)
all_output_dirpaths.append(output_dirpath)
start_index = stop_index
stop_index = stop_index + num_validators_per_node
command_str = " && ".join(all_sub_command_strs)
exec(service_id, ["sh", "-c", command_str], SUCCESSFUL_EXEC_CMD_EXIT_CODE)
# Store outputs into files artifacts
keystore_files = []
for idx, output_dirpath in enumerate(all_output_dirpaths):
artifact_uuid = store_file_from_service(service_id, output_dirpath)
# This is necessary because the way Kurtosis currently implements artifact-storing is
base_dirname_in_artifact = path_base(output_dirpath)
to_add = new_keystore_files(
artifact_uuid,
path_join(base_dirname_in_artifact, RAW_KEYS_DIRNAME),
path_join(base_dirname_in_artifact, RAW_SECRETS_DIRNAME),
path_join(base_dirname_in_artifact, NIMBUS_KEYS_DIRNAME),
path_join(base_dirname_in_artifact, PRYSM_DIRNAME),
path_join(base_dirname_in_artifact, TEKU_KEYS_DIRNAME),
path_join(base_dirname_in_artifact, TEKU_SECRETS_DIRNAME),
)
keystore_files.append(to_add)
write_prysm_password_file_cmd = [
"sh",
"-c",
"echo '{0}' > {1}".format(
PRYSM_PASSWORD,
PRYSM_PASSWORD_FILEPATH_ON_GENERATOR,
),
]
exec(service_id, write_prysm_password_file_cmd, SUCCESSFUL_EXEC_CMD_EXIT_CODE)
prysm_password_artifact_uuid = store_file_from_service(service_id, PRYSM_PASSWORD_FILEPATH_ON_GENERATOR)
result = new_generate_keystores_result(
prysm_password_artifact_uuid,
path_base(PRYSM_PASSWORD_FILEPATH_ON_GENERATOR),
keystore_files,
)
return result
# 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
PrysmPasswordArtifactUUid = prysm_password_artifact_uuid,
# Relative to root of files artifact
PrysmPasswordRelativeFilepath = prysm_password_relative_filepath,
# Contains keystores-per-client-type for each node in the network
PerNodeKeystores = 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(
FilesArtifactUUID = files_artifact_uuid,
# ------------ All directories below are relative to the root of the files artifact ----------------
RawKeysRelativeDirpath = raw_keys_relative_dirpath,
RawSecretsRelativeDirpath = raw_secrets_relative_dirpath,
NimbusKeysRelativeDirpath = nimbus_keys_relative_dirpath,
PrysmRelativeDirpath = prysm_relative_dirpath,
TekuKeysRelativeDirpath = teku_keys_relative_dirpath,
TekuSecretsRelativeDirpath = 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,
)
load("github.com/kurtosis-tech/eth2-module/src/shared_utils/shared_utils.star", "new_template_and_data", "path_join", "path_base")
load("github.com/kurtosis-tech/eth2-module/src/participant_network/prelaunch_data_generator/el_genesis/el_genesis_data.star", "new_el_genesis_data")
load("github.com/kurtosis-tech/eth2-module/src/participant_network/prelaunch_data_generator/prelaunch_data_generator_launcher/prelaunch_data_generator_launcher.star", "launch_prelaunch_data_generator")
CONFIG_DIRPATH_ON_GENERATOR = "/config"
GENESIS_CONFIG_FILENAME = "genesis-config.yaml"
OUTPUT_DIRPATH_ON_GENERATOR = "/output"
GETH_GENESIS_FILENAME = "genesis.json"
ERIGON_GENESIS_FILENAME = "erigon.json"
NETHERMIND_GENESIS_FILENAME = "nethermind.json"
BESU_GENESIS_FILENAME = "besu.json"
JWT_SECRET_FILENAME = "jwtsecret"
SUCCESSFUL_EXEC_CMD_EXIT_CODE = 0
# Mapping of output genesis filename -> generator to create the file
all_genesis_generation_cmds = {
GETH_GENESIS_FILENAME: lambda genesis_config_filepath_on_generator: ["python3", "/apps/el-gen/genesis_geth.py", genesis_config_filepath_on_generator],
ERIGON_GENESIS_FILENAME: lambda genesis_config_filepath_on_generator: ["python3", "/apps/el-gen/genesis_geth.py",genesis_config_filepath_on_generator],
NETHERMIND_GENESIS_FILENAME: lambda genesis_config_filepath_on_generator: ["python3", "/apps/el-gen/genesis_chainspec.py", genesis_config_filepath_on_generator],
BESU_GENESIS_FILENAME: lambda genesis_config_filepath_on_generator :["python3", "/apps/el-gen/genesis_besu.py", genesis_config_filepath_on_generator]
}
def generate_el_genesis_data(
genesis_generation_config_template,
genesis_unix_timestamp,
network_id,
deposit_contract_address):
template_data = json.encode(genesis_generation_config_template_data(
network_id,
deposit_contract_address,
genesis_unix_timestamp,
))
genesis_config_file_template_and_data = new_template_and_data(genesis_generation_config_template, template_data)
template_and_data_by_rel_dest_filepath = {}
template_and_data_by_rel_dest_filepath[GENESIS_CONFIG_FILENAME] = genesis_config_file_template_and_data
genesis_generation_config_artifact_uuid = render_templates(template_and_data_by_rel_dest_filepath)
# TODO Make this the actual data generator
launcher_service_id = launch_prelaunch_data_generator(
{
genesis_generation_config_artifact_uuid: CONFIG_DIRPATH_ON_GENERATOR,
},
)
# TODO defer remove the above generated service
all_dirpaths_to_create_on_generator = [
CONFIG_DIRPATH_ON_GENERATOR,
OUTPUT_DIRPATH_ON_GENERATOR,
]
all_dirpath_creation_commands = []
for dirpath_to_create_on_generator in all_dirpaths_to_create_on_generator:
all_dirpath_creation_commands.append(
"mkdir -p {0}".format(dirpath_to_create_on_generator),
)
dir_creation_cmd = [
"bash",
"-c",
" && ".join(all_dirpath_creation_commands),
]
exec(launcher_service_id, dir_creation_cmd, SUCCESSFUL_EXEC_CMD_EXIT_CODE)
genesis_config_filepath_on_generator = path_join(CONFIG_DIRPATH_ON_GENERATOR, GENESIS_CONFIG_FILENAME)
genesis_filename_to_relative_filepath_in_artifact = {}
for output_filename, generation_cmd in all_genesis_generation_cmds.items():
cmd = generation_cmd(genesis_config_filepath_on_generator)
output_filepath_on_generator = path_join(OUTPUT_DIRPATH_ON_GENERATOR, output_filename)
cmd.append(">")
cmd.append(output_filepath_on_generator)
cmd_to_execute = [
"bash",
"-c",
" ".join(cmd)
]
exec(launcher_service_id, cmd_to_execute, SUCCESSFUL_EXEC_CMD_EXIT_CODE)
genesis_filename_to_relative_filepath_in_artifact[output_filename] = path_join(
path_base(OUTPUT_DIRPATH_ON_GENERATOR),
output_filename,
)
jwt_secret_filepath_on_generator = path_join(OUTPUT_DIRPATH_ON_GENERATOR, JWT_SECRET_FILENAME)
jwt_secret_generation_cmd_args = [
"bash",
"-c",
"openssl rand -hex 32 | tr -d \"\\n\" | sed 's/^/0x/' > {0}".format(
jwt_secret_filepath_on_generator,
)
]
exec(launcher_service_id, jwt_secret_generation_cmd_args, SUCCESSFUL_EXEC_CMD_EXIT_CODE)
elGenesisDataArtifactUuid = store_file_from_service(launcher_service_id, OUTPUT_DIRPATH_ON_GENERATOR)
result = new_el_genesis_data(
elGenesisDataArtifactUuid,
path_join(path_base(OUTPUT_DIRPATH_ON_GENERATOR), JWT_SECRET_FILENAME),
genesis_filename_to_relative_filepath_in_artifact[GETH_GENESIS_FILENAME],
genesis_filename_to_relative_filepath_in_artifact[ERIGON_GENESIS_FILENAME],
genesis_filename_to_relative_filepath_in_artifact[NETHERMIND_GENESIS_FILENAME],
genesis_filename_to_relative_filepath_in_artifact[BESU_GENESIS_FILENAME],
)
return result
def genesis_generation_config_template_data(network_id, deposit_contract_address, unix_timestamp):
return {
"NetworkId": network_id,
"DepositContractAddress": deposit_contract_address,
"UnixTimestamp": unix_timestamp,
}
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",
),
]
IMAGE = "ethpandaops/ethereum-genesis-generator:1.0.2"
SERVICE_ID_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(files_artifact_mountpoints):
service_config = get_service_config(files_artifact_mountpoints)
service_id = "{0}{1}".format(
SERVICE_ID_PREFIX,
time.now().unix_nano,
)
add_service(service_id, service_config)
return service_id
def get_service_config(
files_artifact_mountpoints,
):
return struct(
# TODO used ports is supposed to be empty
used_ports = {},
container_image_name = IMAGE,
entry_point_args = ENTRYPOINT_ARGS,
files_artifact_mount_dirpaths = files_artifact_mountpoints,
)
def new_template_and_data(template, template_data_json):
return {"template": template, "template_data_json": template_data_json}
def path_join(*args):
joined_path = "/".join(args)
return joined_path.replace("//", "/")
def path_base(path):
split_path = path.split("/")
return split_path[-1]
[network]
name = "pithos"
etherscan_api_key = "some-etherscan-api-key"
[consensus_chain]
seconds_per_slot = {{ .SecondsPerSlot }}
slots_per_epoch = {{ .SlotsPerEpoch }}
genesis_time = {{ .GenesisUnixTimestamp }}
[weak_subjectivity]
provider_endpoint = "http://eth2-ws-provider_eth2_ws_server_1:80"
[monitor]
output_dir = "public"
port = {{ .ListenPortNum }}
{{ range $clClient := .CLClientInfo }}
[[monitor.endpoints]]
consensus = "http://{{ $clClient.IPAddr }}:{{ $clClient.PortNum }}"
execution = "N/A" # This doesn't seem to be used
{{ end }}
\ No newline at end of file
# Extends the mainnet preset
# This *could* be 'minimal', but it's not recommended to use because not every client supports 'minimal'
PRESET_BASE: 'mainnet'
CONFIG_NAME: testnet # needs to exist because of Prysm. Otherwise it conflicts with mainnet genesis
# Genesis
# ---------------------------------------------------------------
# `2**14` (= 16,384)
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: {{ .NumValidatorKeysToPreregister }}
MIN_GENESIS_TIME: {{ .UnixTimestamp }}
GENESIS_FORK_VERSION: 0x10000038
GENESIS_DELAY: 300
# Forking
# ---------------------------------------------------------------
# Some forks are disabled for now:
# - These may be re-assigned to another fork-version later
# - Temporarily set to max uint64 value: 2**64 - 1
# Note: The module runs a merged chain so ALTAIR_FORK_EPOCH, BELLATRIX_FORK_EPOCH and TERMINAL_TOTAL_DIFFICULTY
# are all hardcoded to zero.
# Altair
ALTAIR_FORK_VERSION: 0x20000038
ALTAIR_FORK_EPOCH: 0
# Merge
BELLATRIX_FORK_VERSION: 0x30000038
BELLATRIX_FORK_EPOCH: 0
TERMINAL_TOTAL_DIFFICULTY: 0
# 0x0000...000 indicates that we use TERMINAL_TOTAL_DIFFICULTY instead of a block has to trigger the merge
TERMINAL_BLOCK_HASH: 0x0000000000000000000000000000000000000000000000000000000000000000
# NOTE: This is commented out because Nimbus warns us that it's an unrecognized parameter
TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: 18446744073709551615
# Capella
CAPELLA_FORK_VERSION: 0x40000038
CAPELLA_FORK_EPOCH: 18446744073709551615
# Sharding
SHARDING_FORK_VERSION: 0x03001020
SHARDING_FORK_EPOCH: 18446744073709551615
# Time parameters
# ---------------------------------------------------------------
# 12 seconds
SECONDS_PER_SLOT: {{ .SecondsPerSlot }}
# 2**8 (= 256) epochs ~27 hours
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
# 2**8 (= 256) epochs ~27 hours
SHARD_COMMITTEE_PERIOD: 256
# It's very important that SECONDS_PER_ETH1_BLOCK * ETH1_FOLLOW_DISTANCE is a good amount of time, else
# jitter will cause the Beacon nodes to think they're far behind the Eth1 nodes and give up syncing
SECONDS_PER_ETH1_BLOCK: 10
ETH1_FOLLOW_DISTANCE: 12
# Validator cycle
# ---------------------------------------------------------------
# 2**2 (= 4)
INACTIVITY_SCORE_BIAS: 4
# 2**4 (= 16)
INACTIVITY_SCORE_RECOVERY_RATE: 16
# 2**4 * 10**9 (= 16,000,000,000) Gwei
EJECTION_BALANCE: 16000000000
# 2**2 (= 4)
MIN_PER_EPOCH_CHURN_LIMIT: 4
# 2**16 (= 65,536)
CHURN_LIMIT_QUOTIENT: 65536
# Deposit contract
# ---------------------------------------------------------------
DEPOSIT_CHAIN_ID: {{ .NetworkId }}
DEPOSIT_NETWORK_ID: {{ .NetworkId }}
DEPOSIT_CONTRACT_ADDRESS: {{ .DepositContractAddress }}
\ No newline at end of file
- mnemonic: "{{ .PreregisteredValidatorKeysMnemonic }}" # a 24 word BIP 39 mnemonic
# Number of validator keys to preregister inside the outputted CL genesis.ssz
count: {{ .NumValidatorKeysToPreregister }}
\ No newline at end of file
# NOTE: This does NOT have any relevance to the mnemonics & validator keys in the CL genesis!
mnemonic: "stumble horn valley travel milk void screen bulk wink hood cup item glove setup wrong toward erase invite saddle this poverty basket index lab"
el_premine:
"m/44'/60'/0'/0/0": 10000000ETH
"m/44'/60'/0'/0/1": 10000000ETH
"m/44'/60'/0'/0/2": 10000000ETH
"m/44'/60'/0'/0/3": 10000000ETH
"m/44'/60'/0'/0/4": 10000000ETH
"m/44'/60'/0'/0/5": 10000000ETH
el_premine_addrs: {}
chain_id: {{ .NetworkId }}
deposit_contract_address: "{{ .DepositContractAddress }}"
genesis_timestamp: {{ .UnixTimestamp }}
# Note: The module runs a merged chain so terminal_total_difficulty is hardcoded to zero.
terminal_total_difficulty: 0
# Set to 10 per Pari's recommendation
# To read more about what this is and does, see: https://notes.ethereum.org/cmyGUbKVTTqhUGDg_GYThg
mergeForkBlock: 10
clique:
enabled: false
\ No newline at end of file
{"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}
\ No newline at end of file
{"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}
\ No newline at end of file
{"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}
\ No newline at end of file
{"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}
\ No newline at end of file
{"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}
\ No newline at end of file
{"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}
\ No newline at end of file
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"target": {
"limit": 100,
"matchAny": false,
"tags": [],
"type": "dashboard"
},
"type": "dashboard"
}
]
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": 1,
"links": [],
"liveNow": false,
"panels": [
{
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 0
},
"id": 2,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"exemplar": true,
"expr": "beacon_head_slot{}",
"interval": "",
"legendFormat": "{{job}}",
"refId": "A"
}
],
"title": "Beacon Head Slot",
"type": "timeseries"
},
{
"fieldConfig": {
"defaults": {
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
},
"unit": "short"
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 0
},
"id": 4,
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"pluginVersion": "8.4.2",
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"exemplar": true,
"expr": "libp2p_peers{}",
"interval": "",
"legendFormat": "{{job}}",
"refId": "A"
}
],
"title": "Peers",
"type": "stat"
},
{
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 8,
"w": 24,
"x": 0,
"y": 8
},
"id": 6,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom"
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"exemplar": true,
"expr": "beacon_participation_prev_epoch_target_attesting_gwei_total/beacon_participation_prev_epoch_active_gwei_total",
"interval": "",
"legendFormat": "",
"refId": "A"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"exemplar": true,
"expr": "beacon_previous_live_validators / beacon_previous_active_validators",
"hide": false,
"interval": "",
"legendFormat": "",
"refId": "B"
},
{
"datasource": {
"type": "prometheus",
"uid": "PBFA97CFB590B2093"
},
"exemplar": true,
"expr": "beacon_previous_correct_validators / beacon_previous_active_validators",
"hide": false,
"interval": "",
"legendFormat": "",
"refId": "C"
}
],
"title": "Panel Title",
"type": "timeseries"
}
],
"schemaVersion": 35,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-15m",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Eth2 Merge Kurtosis Module Dashboard",
"uid": "QdTOwy-nz",
"version": 2,
"weekStart": ""
}
\ No newline at end of file
apiVersion: 1
providers:
# <string> an unique provider name. Required
- name: 'Eth2 Merge Kurtosis Module Dashboard Provider'
# <int> Org id. Default to 1
orgId: 1
# <string> name of the dashboard folder.
folder: ''
# <string> folder UID. will be automatically generated if not specified
folderUid: ''
# <string> provider type. Default to 'file'
type: file
# <bool> disable dashboard deletion
disableDeletion: false
# <int> how often Grafana will scan for changed dashboards
updateIntervalSeconds: 10
# <bool> allow updating provisioned dashboards from the UI
allowUiUpdates: true
editable: true
options:
# <string, required> path to dashboard files on disk. Required when using the 'file' type
path: {{ .DashboardsDirpath }}
# <bool> use folder names from filesystem to create folders in Grafana
foldersFromFilesStructure: true
\ No newline at end of file
apiVersion: 1
# TODO we can improve this, adding an array that we can use to iterate
# TODO an get different datasource configurations
datasources:
- name: Prometheus
type: prometheus
access: proxy
orgId: 1
url: {{ .PrometheusURL }}
basicAuth: false
isDefault: true
editable: true
\ No newline at end of file
global:
scrape_interval: 15s # By default, scrape targets every 15 seconds.
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
{{ range $clNode := .CLNodesMetricsInfo }}
- job_name: '{{ $clNode.name }}'
metrics_path: {{ $clNode.path }}
static_configs:
- targets: ['{{ $clNode.url }}']
{{ end }}
\ No newline at end of file
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