From 525a8fb3d794f8030a574f55f3a7e719c1b58dca Mon Sep 17 00:00:00 2001 From: Barnabas Busa Date: Mon, 6 May 2024 09:49:48 +0200 Subject: [PATCH] feat!: add mev-rs relay/builder/boost (#586) This PR introduces a new mev boost/mev relay created by @ralexstokes. It can be triggered by: `mev_type: mev-rs` It gets rid of the previously used `full` flag and flashbots will work under the `mev_type: flashbots` following this PR. --- .github/tests/mev.yaml | 2 +- .github/tests/minimal-mev-rs.yaml | 23 +++ .github/tests/minimal.yaml | 7 - .github/tests/mix-with-tools-mev.yaml | 2 +- .github/tests/nimbus-mev.yaml | 2 +- README.md | 6 +- main.star | 148 ++++++++++---- rename.sh | 2 + src/cl/cl_launcher.star | 12 +- src/cl/grandine/grandine_launcher.star | 4 +- src/cl/lighthouse/lighthouse_launcher.star | 4 +- src/cl/lodestar/lodestar_launcher.star | 11 +- src/cl/nimbus/nimbus_launcher.star | 4 +- src/cl/prysm/prysm_launcher.star | 10 +- src/cl/teku/teku_launcher.star | 4 +- src/el/el_launcher.star | 13 +- src/el/reth/reth_launcher.star | 34 ++-- .../mev_boost/mev_boost_context.star | 0 .../mev_boost/mev_boost_launcher.star | 12 +- .../mev_custom_flood_launcher.star | 0 .../mev_custom_flood/sender.py | 0 .../mev_flood/mev_flood_launcher.star | 0 .../mev_relay/mev_relay_launcher.star | 13 +- .../mock_mev/mock_mev_launcher.star | 5 +- .../mev-rs/mev_boost/mev_boost_context.star | 11 + .../mev-rs/mev_boost/mev_boost_launcher.star | 122 ++++++++++++ .../mev_builder/mev_builder_launcher.star | 75 +++++++ .../mev-rs/mev_relay/mev_relay_launcher.star | 111 +++++++++++ src/package_io/constants.star | 22 +- src/package_io/input_parser.star | 188 ++++++++++++++---- src/participant_network.star | 1 + src/static_files/static_files.star | 14 +- .../transaction_spammer.star | 6 +- src/vc/lodestar.star | 4 + src/vc/vc_launcher.star | 2 + .../mev/mev-rs/mev_boost/config.toml.tmpl | 10 + .../mev/mev-rs/mev_builder/config.toml.tmpl | 37 ++++ .../mev/mev-rs/mev_relay/config.toml.tmpl | 10 + 38 files changed, 772 insertions(+), 159 deletions(-) create mode 100644 .github/tests/minimal-mev-rs.yaml rename src/mev/{ => flashbots}/mev_boost/mev_boost_context.star (100%) rename src/mev/{ => flashbots}/mev_boost/mev_boost_launcher.star (82%) rename src/mev/{ => flashbots}/mev_custom_flood/mev_custom_flood_launcher.star (100%) rename src/mev/{ => flashbots}/mev_custom_flood/sender.py (100%) rename src/mev/{ => flashbots}/mev_flood/mev_flood_launcher.star (100%) rename src/mev/{ => flashbots}/mev_relay/mev_relay_launcher.star (92%) rename src/mev/{ => flashbots}/mock_mev/mock_mev_launcher.star (85%) create mode 100644 src/mev/mev-rs/mev_boost/mev_boost_context.star create mode 100644 src/mev/mev-rs/mev_boost/mev_boost_launcher.star create mode 100644 src/mev/mev-rs/mev_builder/mev_builder_launcher.star create mode 100644 src/mev/mev-rs/mev_relay/mev_relay_launcher.star create mode 100644 static_files/mev/mev-rs/mev_boost/config.toml.tmpl create mode 100644 static_files/mev/mev-rs/mev_builder/config.toml.tmpl create mode 100644 static_files/mev/mev-rs/mev_relay/config.toml.tmpl diff --git a/.github/tests/mev.yaml b/.github/tests/mev.yaml index f1d515051..0ea0ab96c 100644 --- a/.github/tests/mev.yaml +++ b/.github/tests/mev.yaml @@ -1,4 +1,4 @@ -mev_type: full +mev_type: flashbots additional_services: - tx_spammer - blob_spammer diff --git a/.github/tests/minimal-mev-rs.yaml b/.github/tests/minimal-mev-rs.yaml new file mode 100644 index 000000000..0a4198beb --- /dev/null +++ b/.github/tests/minimal-mev-rs.yaml @@ -0,0 +1,23 @@ +participants: + - el_type: geth + cl_type: teku + - el_type: geth + cl_type: prysm + - el_type: erigon + cl_type: nimbus + - el_type: besu + cl_type: lighthouse + - el_type: reth + cl_type: lodestar + - el_type: geth + cl_type: grandine +network_params: + preset: minimal + seconds_per_slot: 6 +additional_services: + - dora + - tx_spammer + - apache + +mev_type: mev-rs + diff --git a/.github/tests/minimal.yaml b/.github/tests/minimal.yaml index ce44ed818..59f88a860 100644 --- a/.github/tests/minimal.yaml +++ b/.github/tests/minimal.yaml @@ -3,21 +3,14 @@ participants: cl_type: teku - el_type: geth cl_type: prysm - cl_extra_params: [--minimal-config=true] - cl_image: ethpandaops/prysm-beacon-chain:develop-minimal - el_type: erigon cl_type: nimbus - cl_image: ethpandaops/nimbus-eth2:unstable-minimal - el_type: besu cl_type: lighthouse - cl_image: ethpandaops/lighthouse:unstable-minimal - el_type: reth cl_type: lodestar - cl_extra_env_vars: { LODESTAR_PRESET: minimal } - vc_extra_env_vars: { LODESTAR_PRESET: minimal } - el_type: geth cl_type: grandine - cl_image: ethpandaops/grandine:develop-minimal network_params: preset: minimal seconds_per_slot: 6 diff --git a/.github/tests/mix-with-tools-mev.yaml b/.github/tests/mix-with-tools-mev.yaml index 41d627594..260749643 100644 --- a/.github/tests/mix-with-tools-mev.yaml +++ b/.github/tests/mix-with-tools-mev.yaml @@ -27,7 +27,7 @@ additional_services: - apache ethereum_metrics_exporter_enabled: true snooper_enabled: true -mev_type: full +mev_type: flashbots mev_params: mev_relay_image: flashbots/mev-boost-relay:latest persistent: True diff --git a/.github/tests/nimbus-mev.yaml b/.github/tests/nimbus-mev.yaml index b6d1e42ff..0428d8d9c 100644 --- a/.github/tests/nimbus-mev.yaml +++ b/.github/tests/nimbus-mev.yaml @@ -1,4 +1,4 @@ participants: - el_type: geth cl_type: nimbus -mev_type: full +mev_type: flashbots diff --git a/README.md b/README.md index d204813ab..a8518c8f9 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ v_max_mem -> vc_max_mem ### Global flags ``` global_client_log_level -> global_log_level +mev_type: full -> mev_type: flashbots # new rename as of 3 May 2024 ``` To help you with the transition, we have added a script that will automatically update your `yaml` file to the new format. You can run the following command to update your network_params.yaml file: @@ -665,7 +666,8 @@ persistent: false # Supports three valeus # Default: "null" - no mev boost, mev builder, mev flood or relays are spun up # "mock" - mock-builder & mev-boost are spun up -# "full" - mev-boost, relays, flooder and builder are all spun up +# "flashbots" - mev-boost, relays, flooder and builder are all spun up, powered by [flashbots](https://github.com/flashbots) +# "mev-rs" - mev-boost, relays and builder are all spun up, powered by [mev-rs](https://github.com/ralexstokes/mev-rs/) # We have seen instances of multibuilder instances failing to start mev-relay-api with non zero epochs mev_type: null @@ -841,7 +843,7 @@ participants: - el_type: besu cl_type: prysm count: 2 -mev_type: full +mev_type: flashbots network_params: deneb_fork_epoch: 1 additional_services: [] diff --git a/main.star b/main.star index a5a71ab9e..ba55cef75 100644 --- a/main.star +++ b/main.star @@ -31,12 +31,21 @@ full_beaconchain_explorer = import_module( blockscout = import_module("./src/blockscout/blockscout_launcher.star") prometheus = import_module("./src/prometheus/prometheus_launcher.star") grafana = import_module("./src/grafana/grafana_launcher.star") -mev_boost = import_module("./src/mev/mev_boost/mev_boost_launcher.star") -mock_mev = import_module("./src/mev/mock_mev/mock_mev_launcher.star") -mev_relay = import_module("./src/mev/mev_relay/mev_relay_launcher.star") -mev_flood = import_module("./src/mev/mev_flood/mev_flood_launcher.star") +mev_rs_mev_boost = import_module("./src/mev/mev-rs/mev_boost/mev_boost_launcher.star") +mev_rs_mev_relay = import_module("./src/mev/mev-rs/mev_relay/mev_relay_launcher.star") +mev_rs_mev_builder = import_module( + "./src/mev/mev-rs/mev_builder/mev_builder_launcher.star" +) +flashbots_mev_boost = import_module( + "./src/mev/flashbots/mev_boost/mev_boost_launcher.star" +) +flashbots_mev_relay = import_module( + "./src/mev/flashbots/mev_relay/mev_relay_launcher.star" +) +mock_mev = import_module("./src/mev/flashbots/mock_mev/mock_mev_launcher.star") +mev_flood = import_module("./src/mev/flashbots/mev_flood/mev_flood_launcher.star") mev_custom_flood = import_module( - "./src/mev/mev_custom_flood/mev_custom_flood_launcher.star" + "./src/mev/flashbots/mev_custom_flood/mev_custom_flood_launcher.star" ) broadcaster = import_module("./src/broadcaster/broadcaster.star") assertoor = import_module("./src/assertoor/assertoor_launcher.star") @@ -49,8 +58,6 @@ FIRST_NODE_FINALIZATION_FACT = "cl-boot-finalization-fact" HTTP_PORT_ID_FOR_FACT = "http" MEV_BOOST_SHOULD_CHECK_RELAY = True -MOCK_MEV_TYPE = "mock" -FULL_MEV_TYPE = "full" PATH_TO_PARSED_BEACON_STATE = "/genesis/output/parsedBeaconState.json" @@ -92,6 +99,18 @@ def run(plan, args={}): plan.print("Read the prometheus, grafana templates") + if args_with_right_defaults.mev_type == constants.MEV_RS_MEV_TYPE: + plan.print("Generating mev-rs builder config file") + mev_rs__builder_config_file = mev_rs_mev_builder.new_builder_config( + plan, + constants.MEV_RS_MEV_TYPE, + network_params.network, + constants.VALIDATING_REWARDS_ACCOUNT, + network_params.preregistered_validator_keys_mnemonic, + args_with_right_defaults.mev_params.mev_builder_extra_data, + global_node_selectors, + ) + plan.print( "Launching participant network with {0} participants and the following network params {1}".format( num_participants, network_params @@ -179,7 +198,7 @@ def run(plan, args={}): # otherwise dummy relays spinup if chosen elif ( args_with_right_defaults.mev_type - and args_with_right_defaults.mev_type == MOCK_MEV_TYPE + and args_with_right_defaults.mev_type == constants.MOCK_MEV_TYPE ): el_uri = "{0}:{1}".format( all_el_contexts[0].ip_addr, @@ -197,13 +216,14 @@ def run(plan, args={}): global_node_selectors, ) mev_endpoints.append(endpoint) - elif ( - args_with_right_defaults.mev_type - and args_with_right_defaults.mev_type == FULL_MEV_TYPE + elif args_with_right_defaults.mev_type and ( + args_with_right_defaults.mev_type == constants.FLASHBOTS_MEV_TYPE + or args_with_right_defaults.mev_type == constants.MEV_RS_MEV_TYPE ): builder_uri = "http://{0}:{1}".format( all_el_contexts[-1].ip_addr, all_el_contexts[-1].rpc_port_num ) + beacon_uri = all_cl_contexts[-1].beacon_http_url beacon_uris = ",".join( ["{0}".format(context.beacon_http_url) for context in all_cl_contexts] ) @@ -232,17 +252,30 @@ def run(plan, args={}): timeout="20m", service_name=first_client_beacon_name, ) - endpoint = mev_relay.launch_mev_relay( - plan, - mev_params, - network_params.network_id, - beacon_uris, - genesis_validators_root, - builder_uri, - network_params.seconds_per_slot, - persistent, - global_node_selectors, - ) + if args_with_right_defaults.mev_type == constants.FLASHBOTS_MEV_TYPE: + endpoint = flashbots_mev_relay.launch_mev_relay( + plan, + mev_params, + network_params.network_id, + beacon_uris, + genesis_validators_root, + builder_uri, + network_params.seconds_per_slot, + persistent, + global_node_selectors, + ) + elif args_with_right_defaults.mev_type == constants.MEV_RS_MEV_TYPE: + endpoint, relay_ip_address, relay_port = mev_rs_mev_relay.launch_mev_relay( + plan, + mev_params, + network_params.network, + beacon_uri, + el_cl_data_files_artifact_uuid, + global_node_selectors, + ) + else: + fail("Invalid MEV type") + mev_flood.spam_in_background( plan, fuzz_target, @@ -260,26 +293,59 @@ def run(plan, args={}): index_str = shared_utils.zfill_custom( index + 1, len(str(len(all_participants))) ) - if args_with_right_defaults.participants[index].validator_count != 0: - mev_boost_launcher = mev_boost.new_mev_boost_launcher( - MEV_BOOST_SHOULD_CHECK_RELAY, - mev_endpoints, - ) - mev_boost_service_name = "{0}-{1}-{2}-{3}".format( - input_parser.MEV_BOOST_SERVICE_NAME_PREFIX, - index_str, - participant.cl_type, - participant.el_type, - ) - mev_boost_context = mev_boost.launch( - plan, - mev_boost_launcher, - mev_boost_service_name, - network_params.network_id, - mev_params.mev_boost_image, - mev_params.mev_boost_args, - global_node_selectors, + plan.print( + "args_with_right_defaults.participants[index].validator_count {0}".format( + args_with_right_defaults.participants[index].validator_count ) + ) + if args_with_right_defaults.participants[index].validator_count != 0: + if ( + args_with_right_defaults.mev_type == constants.FLASHBOTS_MEV_TYPE + or args_with_right_defaults.mev_type == constants.MOCK_MEV_TYPE + ): + mev_boost_launcher = flashbots_mev_boost.new_mev_boost_launcher( + MEV_BOOST_SHOULD_CHECK_RELAY, + mev_endpoints, + ) + mev_boost_service_name = "{0}-{1}-{2}-{3}".format( + input_parser.MEV_BOOST_SERVICE_NAME_PREFIX, + index_str, + participant.cl_type, + participant.el_type, + ) + mev_boost_context = flashbots_mev_boost.launch( + plan, + mev_boost_launcher, + mev_boost_service_name, + network_params.network_id, + mev_params.mev_boost_image, + mev_params.mev_boost_args, + global_node_selectors, + ) + elif args_with_right_defaults.mev_type == constants.MEV_RS_MEV_TYPE: + plan.print("Launching mev-rs mev boost") + mev_boost_launcher = mev_rs_mev_boost.new_mev_boost_launcher( + MEV_BOOST_SHOULD_CHECK_RELAY, + mev_endpoints, + ) + mev_boost_service_name = "{0}-{1}-{2}-{3}".format( + input_parser.MEV_BOOST_SERVICE_NAME_PREFIX, + index_str, + participant.cl_type, + participant.el_type, + ) + mev_boost_context = mev_rs_mev_boost.launch( + plan, + mev_boost_launcher, + mev_boost_service_name, + network_params.network, + mev_params, + mev_endpoints, + el_cl_data_files_artifact_uuid, + global_node_selectors, + ) + else: + fail("Invalid MEV type") all_mevboost_contexts.append(mev_boost_context) if len(args_with_right_defaults.additional_services) == 0: diff --git a/rename.sh b/rename.sh index 8308683e8..5f909c83b 100755 --- a/rename.sh +++ b/rename.sh @@ -74,6 +74,8 @@ replacements=( vc_max_mem global_client_log_level global_log_level + full + flashbots ) # Perform replacements diff --git a/src/cl/cl_launcher.star b/src/cl/cl_launcher.star index 5b4373771..87324d3de 100644 --- a/src/cl/cl_launcher.star +++ b/src/cl/cl_launcher.star @@ -38,13 +38,13 @@ def launch( cl_launchers = { constants.CL_TYPE.lighthouse: { "launcher": lighthouse.new_lighthouse_launcher( - el_cl_data, jwt_file, network_params.network + el_cl_data, jwt_file, network_params ), "launch_method": lighthouse.launch, }, constants.CL_TYPE.lodestar: { "launcher": lodestar.new_lodestar_launcher( - el_cl_data, jwt_file, network_params.network + el_cl_data, jwt_file, network_params ), "launch_method": lodestar.launch, }, @@ -52,7 +52,7 @@ def launch( "launcher": nimbus.new_nimbus_launcher( el_cl_data, jwt_file, - network_params.network, + network_params, keymanager_file, ), "launch_method": nimbus.launch, @@ -61,7 +61,7 @@ def launch( "launcher": prysm.new_prysm_launcher( el_cl_data, jwt_file, - network_params.network, + network_params, prysm_password_relative_filepath, prysm_password_artifact_uuid, ), @@ -71,7 +71,7 @@ def launch( "launcher": teku.new_teku_launcher( el_cl_data, jwt_file, - network_params.network, + network_params, keymanager_file, ), "launch_method": teku.launch, @@ -80,7 +80,7 @@ def launch( "launcher": grandine.new_grandine_launcher( el_cl_data, jwt_file, - network_params.network, + network_params, ), "launch_method": grandine.launch, }, diff --git a/src/cl/grandine/grandine_launcher.star b/src/cl/grandine/grandine_launcher.star index b2c24c951..8bfdc135e 100644 --- a/src/cl/grandine/grandine_launcher.star +++ b/src/cl/grandine/grandine_launcher.star @@ -422,10 +422,10 @@ def get_beacon_config( def new_grandine_launcher( el_cl_genesis_data, jwt_file, - network, + network_params, ): return struct( el_cl_genesis_data=el_cl_genesis_data, jwt_file=jwt_file, - network=network, + network=network_params.network, ) diff --git a/src/cl/lighthouse/lighthouse_launcher.star b/src/cl/lighthouse/lighthouse_launcher.star index 1e1ee4582..ca5b4cfac 100644 --- a/src/cl/lighthouse/lighthouse_launcher.star +++ b/src/cl/lighthouse/lighthouse_launcher.star @@ -414,9 +414,9 @@ def get_beacon_config( ) -def new_lighthouse_launcher(el_cl_genesis_data, jwt_file, network): +def new_lighthouse_launcher(el_cl_genesis_data, jwt_file, network_params): return struct( el_cl_genesis_data=el_cl_genesis_data, jwt_file=jwt_file, - network=network, + network=network_params.network, ) diff --git a/src/cl/lodestar/lodestar_launcher.star b/src/cl/lodestar/lodestar_launcher.star index 4d2b97e9a..e410b2229 100644 --- a/src/cl/lodestar/lodestar_launcher.star +++ b/src/cl/lodestar/lodestar_launcher.star @@ -140,6 +140,7 @@ def launch( tolerations, node_selectors, port_publisher, + launcher.preset, ) beacon_service = plan.add_service(beacon_service_name, beacon_config) @@ -239,6 +240,7 @@ def get_beacon_config( tolerations, node_selectors, port_publisher, + preset, ): el_client_rpc_url_str = "http://{0}:{1}".format( el_context.ip_addr, @@ -367,6 +369,10 @@ def get_beacon_config( persistent_key="data-{0}".format(service_name), size=cl_volume_size, ) + + if preset == "minimal": + extra_env_vars["LODESTAR_PRESET"] = "minimal" + return ServiceConfig( image=image, ports=used_ports, @@ -394,9 +400,10 @@ def get_beacon_config( ) -def new_lodestar_launcher(el_cl_genesis_data, jwt_file, network): +def new_lodestar_launcher(el_cl_genesis_data, jwt_file, network_params): return struct( el_cl_genesis_data=el_cl_genesis_data, jwt_file=jwt_file, - network=network, + network=network_params.network, + preset=network_params.preset, ) diff --git a/src/cl/nimbus/nimbus_launcher.star b/src/cl/nimbus/nimbus_launcher.star index 9750425aa..2b04d4510 100644 --- a/src/cl/nimbus/nimbus_launcher.star +++ b/src/cl/nimbus/nimbus_launcher.star @@ -407,10 +407,10 @@ def get_beacon_config( ) -def new_nimbus_launcher(el_cl_genesis_data, jwt_file, network, keymanager_file): +def new_nimbus_launcher(el_cl_genesis_data, jwt_file, network_params, keymanager_file): return struct( el_cl_genesis_data=el_cl_genesis_data, jwt_file=jwt_file, - network=network, + network=network_params.network, keymanager_file=keymanager_file, ) diff --git a/src/cl/prysm/prysm_launcher.star b/src/cl/prysm/prysm_launcher.star index 02179e06b..8c36b28f6 100644 --- a/src/cl/prysm/prysm_launcher.star +++ b/src/cl/prysm/prysm_launcher.star @@ -148,6 +148,7 @@ def launch( tolerations, node_selectors, port_publisher, + launcher.preset, ) beacon_service = plan.add_service(beacon_service_name, beacon_config) @@ -226,6 +227,7 @@ def get_beacon_config( tolerations, node_selectors, port_publisher, + preset, ): # If snooper is enabled use the snooper engine context, otherwise use the execution client context if snooper_enabled: @@ -282,6 +284,9 @@ def get_beacon_config( # ^^^^^^^^^^^^^^^^^^^ METRICS CONFIG ^^^^^^^^^^^^^^^^^^^^^ ] + if preset == "minimal": + cmd.append("--minimal-config=true") + if network not in constants.PUBLIC_NETWORKS: cmd.append("--p2p-static-id=true") cmd.append( @@ -382,14 +387,15 @@ def get_beacon_config( def new_prysm_launcher( el_cl_genesis_data, jwt_file, - network, + network_params, prysm_password_relative_filepath, prysm_password_artifact_uuid, ): return struct( el_cl_genesis_data=el_cl_genesis_data, jwt_file=jwt_file, - network=network, + network=network_params.network, + preset=network_params.preset, prysm_password_artifact_uuid=prysm_password_artifact_uuid, prysm_password_relative_filepath=prysm_password_relative_filepath, ) diff --git a/src/cl/teku/teku_launcher.star b/src/cl/teku/teku_launcher.star index 90d6e3a05..d8e967b9b 100644 --- a/src/cl/teku/teku_launcher.star +++ b/src/cl/teku/teku_launcher.star @@ -442,10 +442,10 @@ def get_beacon_config( ) -def new_teku_launcher(el_cl_genesis_data, jwt_file, network, keymanager_file): +def new_teku_launcher(el_cl_genesis_data, jwt_file, network_params, keymanager_file): return struct( el_cl_genesis_data=el_cl_genesis_data, jwt_file=jwt_file, - network=network, + network=network_params.network, keymanager_file=keymanager_file, ) diff --git a/src/el/el_launcher.star b/src/el/el_launcher.star index f08a4379f..993077062 100644 --- a/src/el/el_launcher.star +++ b/src/el/el_launcher.star @@ -37,7 +37,7 @@ def launch( ), "launch_method": geth.launch, }, - constants.EL_TYPE.gethbuilder: { + constants.EL_TYPE.geth_builder: { "launcher": geth.new_geth_launcher( el_cl_data, jwt_file, @@ -82,6 +82,15 @@ def launch( ), "launch_method": reth.launch, }, + constants.EL_TYPE.reth_builder: { + "launcher": reth.new_reth_launcher( + el_cl_data, + jwt_file, + network_params.network, + builder=True, + ), + "launch_method": reth.launch, + }, constants.EL_TYPE.ethereumjs: { "launcher": ethereumjs.new_ethereumjs_launcher( el_cl_data, @@ -115,7 +124,7 @@ def launch( if el_type not in el_launchers: fail( "Unsupported launcher '{0}', need one of '{1}'".format( - el_type, ",".join([el.name for el in el_launchers.keys()]) + el_type, ",".join(el_launchers.keys()) ) ) diff --git a/src/el/reth/reth_launcher.star b/src/el/reth/reth_launcher.star index 3608c9680..2158d5eb8 100644 --- a/src/el/reth/reth_launcher.star +++ b/src/el/reth/reth_launcher.star @@ -1,9 +1,10 @@ shared_utils = import_module("../../shared_utils/shared_utils.star") input_parser = import_module("../../package_io/input_parser.star") -el_context = import_module("../../el/el_context.star") -el_admin_node_info = import_module("../../el/el_admin_node_info.star") +el_context = import_module("../el_context.star") +el_admin_node_info = import_module("../el_admin_node_info.star") node_metrics = import_module("../../node_metrics_info.star") constants = import_module("../../package_io/constants.star") +mev_rs_builder = import_module("../../mev/mev-rs/mev_builder/mev_builder_launcher.star") RPC_PORT_NUM = 8545 WS_PORT_NUM = 8546 @@ -135,6 +136,7 @@ def launch( el_volume_size, tolerations, node_selectors, + launcher.builder, port_publisher, ) @@ -181,13 +183,9 @@ def get_config( el_volume_size, tolerations, node_selectors, + builder, port_publisher, ): - init_datadir_cmd_str = "reth init --datadir={0} --chain={1}".format( - EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, - constants.GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER + "/genesis.json", - ) - public_ports = {} discovery_port = DISCOVERY_PORT_NUM if port_publisher.public_port_start: @@ -203,7 +201,7 @@ def get_config( used_ports = get_used_ports(discovery_port) cmd = [ - "reth", + "/usr/local/bin/mev build" if builder else "reth", "node", "-{0}".format(verbosity_level), "--datadir=" + EXECUTION_DATA_DIRPATH_ON_CLIENT_CONTAINER, @@ -232,6 +230,7 @@ def get_config( "--discovery.port={0}".format(discovery_port), "--port={0}".format(discovery_port), ] + if network == constants.NETWORK_NAME.kurtosis: if len(existing_el_clients) > 0: cmd.append( @@ -256,15 +255,6 @@ def get_config( cmd.extend([param for param in extra_params]) cmd_str = " ".join(cmd) - if network not in constants.PUBLIC_NETWORKS: - subcommand_strs = [ - init_datadir_cmd_str, - cmd_str, - ] - else: - subcommand_strs = [cmd_str] - - command_str = " && ".join(subcommand_strs) files = { constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data.files_artifact_uuid, @@ -277,11 +267,16 @@ def get_config( size=el_volume_size, ) + if builder: + files[ + mev_rs_builder.MEV_BUILDER_MOUNT_DIRPATH_ON_SERVICE + ] = mev_rs_builder.MEV_BUILDER_FILES_ARTIFACT_NAME + return ServiceConfig( image=image, ports=used_ports, public_ports=public_ports, - cmd=[command_str], + cmd=[cmd_str], files=files, entrypoint=ENTRYPOINT_ARGS, private_ip_address_placeholder=constants.PRIVATE_IP_ADDRESS_PLACEHOLDER, @@ -302,9 +297,10 @@ def get_config( ) -def new_reth_launcher(el_cl_genesis_data, jwt_file, network): +def new_reth_launcher(el_cl_genesis_data, jwt_file, network, builder=False): return struct( el_cl_genesis_data=el_cl_genesis_data, jwt_file=jwt_file, network=network, + builder=builder, ) diff --git a/src/mev/mev_boost/mev_boost_context.star b/src/mev/flashbots/mev_boost/mev_boost_context.star similarity index 100% rename from src/mev/mev_boost/mev_boost_context.star rename to src/mev/flashbots/mev_boost/mev_boost_context.star diff --git a/src/mev/mev_boost/mev_boost_launcher.star b/src/mev/flashbots/mev_boost/mev_boost_launcher.star similarity index 82% rename from src/mev/mev_boost/mev_boost_launcher.star rename to src/mev/flashbots/mev_boost/mev_boost_launcher.star index 4445e5d64..73d42096c 100644 --- a/src/mev/mev_boost/mev_boost_launcher.star +++ b/src/mev/flashbots/mev_boost/mev_boost_launcher.star @@ -1,12 +1,12 @@ -shared_utils = import_module("../../shared_utils/shared_utils.star") +shared_utils = import_module("../../../shared_utils/shared_utils.star") mev_boost_context_module = import_module("../mev_boost/mev_boost_context.star") -input_parser = import_module("../../package_io/input_parser.star") +input_parser = import_module("../../../package_io/input_parser.star") FLASHBOTS_MEV_BOOST_PROTOCOL = "TCP" USED_PORTS = { "api": shared_utils.new_port_spec( - input_parser.FLASHBOTS_MEV_BOOST_PORT, FLASHBOTS_MEV_BOOST_PROTOCOL, wait="5s" + input_parser.MEV_BOOST_PORT, shared_utils.TCP_PROTOCOL, wait="5s" ) } @@ -43,7 +43,7 @@ def launch( mev_boost_service = plan.add_service(service_name, config) return mev_boost_context_module.new_mev_boost_context( - mev_boost_service.ip_address, input_parser.FLASHBOTS_MEV_BOOST_PORT + mev_boost_service.ip_address, input_parser.MEV_BOOST_PORT ) @@ -66,9 +66,7 @@ def get_config( # latest-notes # does this need genesis time to be set as well "GENESIS_FORK_VERSION": "0x10000038", - "BOOST_LISTEN_ADDR": "0.0.0.0:{0}".format( - input_parser.FLASHBOTS_MEV_BOOST_PORT - ), + "BOOST_LISTEN_ADDR": "0.0.0.0:{0}".format(input_parser.MEV_BOOST_PORT), # maybe this is breaking; this isn't verifyign the bid and not sending it to the validator "SKIP_RELAY_SIGNATURE_CHECK": "1", "RELAYS": mev_boost_launcher.relay_end_points[0], diff --git a/src/mev/mev_custom_flood/mev_custom_flood_launcher.star b/src/mev/flashbots/mev_custom_flood/mev_custom_flood_launcher.star similarity index 100% rename from src/mev/mev_custom_flood/mev_custom_flood_launcher.star rename to src/mev/flashbots/mev_custom_flood/mev_custom_flood_launcher.star diff --git a/src/mev/mev_custom_flood/sender.py b/src/mev/flashbots/mev_custom_flood/sender.py similarity index 100% rename from src/mev/mev_custom_flood/sender.py rename to src/mev/flashbots/mev_custom_flood/sender.py diff --git a/src/mev/mev_flood/mev_flood_launcher.star b/src/mev/flashbots/mev_flood/mev_flood_launcher.star similarity index 100% rename from src/mev/mev_flood/mev_flood_launcher.star rename to src/mev/flashbots/mev_flood/mev_flood_launcher.star diff --git a/src/mev/mev_relay/mev_relay_launcher.star b/src/mev/flashbots/mev_relay/mev_relay_launcher.star similarity index 92% rename from src/mev/mev_relay/mev_relay_launcher.star rename to src/mev/flashbots/mev_relay/mev_relay_launcher.star index 8c3f35d45..e83d27959 100644 --- a/src/mev/mev_relay/mev_relay_launcher.star +++ b/src/mev/flashbots/mev_relay/mev_relay_launcher.star @@ -1,9 +1,6 @@ redis_module = import_module("github.com/kurtosis-tech/redis-package/main.star") postgres_module = import_module("github.com/kurtosis-tech/postgres-package/main.star") -constants = import_module("../../package_io/constants.star") - -DUMMY_SECRET_KEY = "0x607a11b45a7219cc61a3d9c5fd08c7eebd602a6a19a977f8d3771d5711a550f2" -DUMMY_PUB_KEY = "0xa55c1285d84ba83a5ad26420cd5ad3091e49c55a813eee651cd467db38a8c8e63192f47955e9376f6b42f6d190571cb5" +constants = import_module("../../../package_io/constants.star") MEV_RELAY_WEBSITE = "mev-relay-website" MEV_RELAY_ENDPOINT = "mev-relay-api" @@ -129,7 +126,7 @@ def launch_mev_relay( "--db", postgres_url, "--secret-key", - DUMMY_SECRET_KEY, + constants.DEFAULT_MEV_SECRET_KEY, "--listen-addr", "0.0.0.0:{0}".format(MEV_RELAY_ENDPOINT_PORT), "--redis-uri", @@ -168,7 +165,9 @@ def launch_mev_relay( "0.0.0.0:{0}".format(MEV_RELAY_WEBSITE_PORT), "--redis-uri", redis_url, - "https://{0}@{1}".format(DUMMY_PUB_KEY, MEV_RELAY_ENDPOINT), + "https://{0}@{1}".format( + constants.DEFAULT_MEV_PUBKEY, MEV_RELAY_ENDPOINT + ), ] + mev_params.mev_relay_website_extra_args, ports={ @@ -188,5 +187,5 @@ def launch_mev_relay( ) return "http://{0}@{1}:{2}".format( - DUMMY_PUB_KEY, api.ip_address, MEV_RELAY_ENDPOINT_PORT + constants.DEFAULT_MEV_PUBKEY, api.ip_address, MEV_RELAY_ENDPOINT_PORT ) diff --git a/src/mev/mock_mev/mock_mev_launcher.star b/src/mev/flashbots/mock_mev/mock_mev_launcher.star similarity index 85% rename from src/mev/mock_mev/mock_mev_launcher.star rename to src/mev/flashbots/mock_mev/mock_mev_launcher.star index e8c11c43e..b83112d8c 100644 --- a/src/mev/mock_mev/mock_mev_launcher.star +++ b/src/mev/flashbots/mock_mev/mock_mev_launcher.star @@ -1,7 +1,8 @@ +constants = import_module("../../../package_io/constants.star") + MOCK_MEV_IMAGE = "ethpandaops/mock-builder:latest" MOCK_MEV_SERVICE_NAME = "mock-mev" MOCK_MEV_BUILDER_PORT = 18550 -DEFAULT_MOCK_MEV_PUB_KEY = "0x95fde78acd5f6886ddaf5d0056610167c513d09c1c0efabbc7cdcc69beea113779c4a81e2d24daafc5387dbf6ac5fe48" # The min/max CPU/memory that mev-mock-builder can use MIN_CPU = 100 @@ -42,5 +43,5 @@ def launch_mock_mev( ), ) return "http://{0}@{1}:{2}".format( - DEFAULT_MOCK_MEV_PUB_KEY, mock_builder.ip_address, MOCK_MEV_BUILDER_PORT + constants.DEFAULT_MEV_PUBKEY, mock_builder.ip_address, MOCK_MEV_BUILDER_PORT ) diff --git a/src/mev/mev-rs/mev_boost/mev_boost_context.star b/src/mev/mev-rs/mev_boost/mev_boost_context.star new file mode 100644 index 000000000..1d6cb6c1d --- /dev/null +++ b/src/mev/mev-rs/mev_boost/mev_boost_context.star @@ -0,0 +1,11 @@ +def new_mev_boost_context(private_ip_address, port): + return struct( + private_ip_address=private_ip_address, + port=port, + ) + + +def mev_boost_endpoint(mev_boost_context): + return "http://{0}:{1}".format( + mev_boost_context.private_ip_address, mev_boost_context.port + ) diff --git a/src/mev/mev-rs/mev_boost/mev_boost_launcher.star b/src/mev/mev-rs/mev_boost/mev_boost_launcher.star new file mode 100644 index 000000000..ca55cd837 --- /dev/null +++ b/src/mev/mev-rs/mev_boost/mev_boost_launcher.star @@ -0,0 +1,122 @@ +shared_utils = import_module("../../../shared_utils/shared_utils.star") +mev_boost_context_module = import_module("../mev_boost/mev_boost_context.star") +input_parser = import_module("../../../package_io/input_parser.star") +static_files = import_module("../../../static_files/static_files.star") +constants = import_module("../../../package_io/constants.star") + +MEV_BOOST_CONFIG_FILENAME = "config.toml" +MEV_BOOST_MOUNT_DIRPATH_ON_SERVICE = "/config" +MEV_BOOST_FILES_ARTIFACT_NAME = "mev-rs-mev-boost-config" + +USED_PORTS = { + "http": shared_utils.new_port_spec( + input_parser.MEV_BOOST_PORT, shared_utils.TCP_PROTOCOL + ) +} + +# The min/max CPU/memory that mev-boost can use +MIN_CPU = 10 +MAX_CPU = 500 +MIN_MEMORY = 16 +MAX_MEMORY = 256 + + +def launch( + plan, + mev_boost_launcher, + service_name, + network, + mev_params, + relays, + el_cl_genesis_data, + global_node_selectors, +): + network = ( + network + if network in constants.PUBLIC_NETWORKS + else constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS + ) + image = mev_params.mev_boost_image + template_data = new_config_template_data( + network, + input_parser.MEV_BOOST_PORT, + relays, + ) + + mev_rs_boost_config_template = read_file( + static_files.MEV_RS_MEV_BOOST_CONFIG_FILEPATH + ) + + template_and_data = shared_utils.new_template_and_data( + mev_rs_boost_config_template, template_data + ) + + template_and_data_by_rel_dest_filepath = {} + template_and_data_by_rel_dest_filepath[ + MEV_BOOST_CONFIG_FILENAME + ] = template_and_data + + config_files_artifact_name = plan.render_templates( + template_and_data_by_rel_dest_filepath, + MEV_BOOST_FILES_ARTIFACT_NAME + service_name, + ) + + config_file_path = shared_utils.path_join( + MEV_BOOST_MOUNT_DIRPATH_ON_SERVICE, MEV_BOOST_CONFIG_FILENAME + ) + + config = get_config( + mev_boost_launcher, + image, + config_file_path, + config_files_artifact_name, + el_cl_genesis_data, + global_node_selectors, + ) + + mev_boost_service = plan.add_service(service_name, config) + + return mev_boost_context_module.new_mev_boost_context( + mev_boost_service.ip_address, input_parser.MEV_BOOST_PORT + ) + + +def get_config( + mev_boost_launcher, + image, + config_file_path, + config_file, + el_cl_genesis_data, + node_selectors, +): + return ServiceConfig( + image=image, + ports=USED_PORTS, + cmd=[ + "boost", + config_file_path, + ], + files={ + MEV_BOOST_MOUNT_DIRPATH_ON_SERVICE: config_file, + constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data, + }, + min_cpu=MIN_CPU, + max_cpu=MAX_CPU, + min_memory=MIN_MEMORY, + max_memory=MAX_MEMORY, + node_selectors=node_selectors, + ) + + +def new_mev_boost_launcher(should_check_relay, relay_end_points): + return struct( + should_check_relay=should_check_relay, relay_end_points=relay_end_points + ) + + +def new_config_template_data(network, port, relays): + return { + "Network": network, + "Port": port, + "Relays": relays, + } diff --git a/src/mev/mev-rs/mev_builder/mev_builder_launcher.star b/src/mev/mev-rs/mev_builder/mev_builder_launcher.star new file mode 100644 index 000000000..b9fd3a787 --- /dev/null +++ b/src/mev/mev-rs/mev_builder/mev_builder_launcher.star @@ -0,0 +1,75 @@ +shared_utils = import_module("../../../shared_utils/shared_utils.star") +input_parser = import_module("../../../package_io/input_parser.star") +static_files = import_module("../../../static_files/static_files.star") +constants = import_module("../../../package_io/constants.star") +mev_rs_relay = import_module("../mev_relay/mev_relay_launcher.star") + +# MEV Builder flags + +MEV_BUILDER_CONFIG_FILENAME = "config.toml" +MEV_BUILDER_MOUNT_DIRPATH_ON_SERVICE = "/config" +MEV_BUILDER_FILES_ARTIFACT_NAME = "mev-rs-mev-builder-config" +MEV_FILE_PATH_ON_CONTAINER = ( + MEV_BUILDER_MOUNT_DIRPATH_ON_SERVICE + MEV_BUILDER_CONFIG_FILENAME +) + + +def new_builder_config( + plan, + service_name, + network, + fee_recipient, + mnemonic, + extra_data, + global_node_selectors, +): + builder_template_data = new_builder_config_template_data( + network, + constants.DEFAULT_MEV_PUBKEY, + constants.DEFAULT_MEV_SECRET_KEY, + mnemonic, + fee_recipient, + extra_data, + ) + mev_rs_builder_config_template = read_file( + static_files.MEV_RS_MEV_BUILDER_CONFIG_FILEPATH + ) + + template_and_data = shared_utils.new_template_and_data( + mev_rs_builder_config_template, builder_template_data + ) + + template_and_data_by_rel_dest_filepath = {} + template_and_data_by_rel_dest_filepath[ + MEV_BUILDER_CONFIG_FILENAME + ] = template_and_data + + config_files_artifact_name = plan.render_templates( + template_and_data_by_rel_dest_filepath, MEV_BUILDER_FILES_ARTIFACT_NAME + ) + + config_file_path = shared_utils.path_join( + MEV_BUILDER_MOUNT_DIRPATH_ON_SERVICE, MEV_BUILDER_CONFIG_FILENAME + ) + + return config_files_artifact_name + + +def new_builder_config_template_data( + network, + pubkey, + secret, + mnemonic, + fee_recipient, + extra_data, +): + return { + "Network": network, + "Relay": "mev-rs-relay", + "RelayPort": mev_rs_relay.MEV_RELAY_ENDPOINT_PORT, + "PublicKey": pubkey, + "SecretKey": secret, + "Mnemonic": mnemonic, + "FeeRecipient": fee_recipient, + "ExtraData": extra_data, + } diff --git a/src/mev/mev-rs/mev_relay/mev_relay_launcher.star b/src/mev/mev-rs/mev_relay/mev_relay_launcher.star new file mode 100644 index 000000000..8f1669391 --- /dev/null +++ b/src/mev/mev-rs/mev_relay/mev_relay_launcher.star @@ -0,0 +1,111 @@ +shared_utils = import_module("../../../shared_utils/shared_utils.star") +input_parser = import_module("../../../package_io/input_parser.star") +static_files = import_module("../../../static_files/static_files.star") +constants = import_module("../../../package_io/constants.star") + +MEV_RELAY_CONFIG_FILENAME = "config.toml" +MEV_RELAY_MOUNT_DIRPATH_ON_SERVICE = "/config" +MEV_RELAY_FILES_ARTIFACT_NAME = "mev-rs-relay-config" + +MEV_RELAY_ENDPOINT_PORT = 28545 + +USED_PORTS = { + "http": shared_utils.new_port_spec( + MEV_RELAY_ENDPOINT_PORT, + "TCP", + ) +} + +# The min/max CPU/memory that mev-relay can use +MIN_CPU = 10 +MAX_CPU = 500 +MIN_MEMORY = 16 +MAX_MEMORY = 256 + + +def launch_mev_relay( + plan, + mev_params, + network, + beacon_uri, + el_cl_genesis_data, + global_node_selectors, +): + node_selectors = global_node_selectors + image = mev_params.mev_relay_image + network = ( + network + if network in constants.PUBLIC_NETWORKS + else constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS + ) + + relay_template_data = new_relay_config_template_data( + network, + MEV_RELAY_ENDPOINT_PORT, + beacon_uri, + constants.DEFAULT_MEV_PUBKEY, + constants.DEFAULT_MEV_SECRET_KEY, + ) + + mev_rs_relay_config_template = read_file( + static_files.MEV_RS_MEV_RELAY_CONFIG_FILEPATH + ) + + template_and_data = shared_utils.new_template_and_data( + mev_rs_relay_config_template, relay_template_data + ) + + template_and_data_by_rel_dest_filepath = {} + template_and_data_by_rel_dest_filepath[ + MEV_RELAY_CONFIG_FILENAME + ] = template_and_data + + config_files_artifact_name = plan.render_templates( + template_and_data_by_rel_dest_filepath, MEV_RELAY_FILES_ARTIFACT_NAME + ) + + config_file_path = shared_utils.path_join( + MEV_RELAY_MOUNT_DIRPATH_ON_SERVICE, MEV_RELAY_CONFIG_FILENAME + ) + + mev_relay_service = plan.add_service( + name="mev-rs-relay", + config=ServiceConfig( + image=image, + cmd=[ + "relay", + config_file_path, + ], + files={ + MEV_RELAY_MOUNT_DIRPATH_ON_SERVICE: config_files_artifact_name, + constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data, + }, + ports=USED_PORTS, + min_cpu=MIN_CPU, + max_cpu=MAX_CPU, + min_memory=MIN_MEMORY, + max_memory=MAX_MEMORY, + node_selectors=node_selectors, + env_vars={"RUST_BACKTRACE": "1"}, + ), + ) + + return ( + "http://{0}@{1}:{2}".format( + constants.DEFAULT_MEV_PUBKEY, + mev_relay_service.ip_address, + MEV_RELAY_ENDPOINT_PORT, + ), + mev_relay_service.ip_address, + MEV_RELAY_ENDPOINT_PORT, + ) + + +def new_relay_config_template_data(network, port, beacon_uri, pubkey, secret): + return { + "Network": network, + "Port": port, + "BeaconNodeURL": beacon_uri, + "PublicKey": pubkey, + "SecretKey": secret, + } diff --git a/src/package_io/constants.star b/src/package_io/constants.star index 8573d7aaf..1439197b1 100644 --- a/src/package_io/constants.star +++ b/src/package_io/constants.star @@ -1,10 +1,11 @@ EL_TYPE = struct( - gethbuilder="geth-builder", + geth_builder="geth-builder", geth="geth", erigon="erigon", nethermind="nethermind", besu="besu", reth="reth", + reth_builder="reth-builder", ethereumjs="ethereumjs", nimbus="nimbus", ) @@ -60,12 +61,21 @@ KEYMANAGER_MOUNT_PATH_ON_CLIENTS = "/keymanager" KEYMANAGER_MOUNT_PATH_ON_CONTAINER = ( KEYMANAGER_MOUNT_PATH_ON_CLIENTS + "/keymanager.txt" ) -KEYMANAGER_P12_MOUNT_PATH_ON_CLIENTS = "/keymanager-p12" -KEYMANAGER_P12_MOUNT_PATH_ON_CONTAINER = ( - KEYMANAGER_P12_MOUNT_PATH_ON_CLIENTS + "/validator_keystore.p12" -) + +MOCK_MEV_TYPE = "mock" +FLASHBOTS_MEV_TYPE = "flashbots" +MEV_RS_MEV_TYPE = "mev-rs" DEFAULT_SNOOPER_IMAGE = "ethpandaops/rpc-snooper:latest" +DEFAULT_FLASHBOTS_RELAY_IMAGE = "flashbots/mev-boost-relay:0.27" +DEFAULT_FLASHBOTS_BUILDER_IMAGE = "flashbots/builder:latest" +DEFAULT_FLASHBOTS_MEV_BOOST_IMAGE = "flashbots/mev-boost" +DEFAULT_MEV_RS_IMAGE = "ethpandaops/mev-rs:main" +DEFAULT_MEV_RS_IMAGE_MINIMAL = "ethpandaops/mev-rs:main-minimal" +DEFAULT_MEV_PUBKEY = "0xa55c1285d84ba83a5ad26420cd5ad3091e49c55a813eee651cd467db38a8c8e63192f47955e9376f6b42f6d190571cb5" +DEFAULT_MEV_SECRET_KEY = ( + "0x607a11b45a7219cc61a3d9c5fd08c7eebd602a6a19a977f8d3771d5711a550f2" +) PRIVATE_IP_ADDRESS_PLACEHOLDER = "KURTOSIS_IP_ADDR_PLACEHOLDER" @@ -77,7 +87,7 @@ ELECTRA_FORK_VERSION = "0x60000038" ETHEREUM_GENESIS_GENERATOR = struct( capella_genesis="ethpandaops/ethereum-genesis-generator:2.0.12", # Deprecated (no support for minimal config) - deneb_genesis="ethpandaops/ethereum-genesis-generator:3.0.3", # Default + deneb_genesis="ethpandaops/ethereum-genesis-generator:3.0.5", # Default verkle_support_genesis="ethpandaops/ethereum-genesis-generator:3.0.0-rc.19", # soon to be deneb genesis, waiting for rebase verkle_genesis="ethpandaops/ethereum-genesis-generator:verkle-gen-v1.0.0", ) diff --git a/src/package_io/input_parser.star b/src/package_io/input_parser.star index 99c3baa5a..8f8f910ce 100644 --- a/src/package_io/input_parser.star +++ b/src/package_io/input_parser.star @@ -19,29 +19,43 @@ DEFAULT_CL_IMAGES = { "teku": "consensys/teku:latest", "nimbus": "statusim/nimbus-eth2:multiarch-latest", "prysm": "gcr.io/prysmaticlabs/prysm/beacon-chain:latest", - "lodestar": "chainsafe/lodestar:next", - "grandine": "ethpandaops/grandine:develop", + "lodestar": "chainsafe/lodestar:latest", + "grandine": "ethpandaops/grandine:master", +} + +DEFAULT_CL_IMAGES_MINIMAL = { + "lighthouse": "ethpandaops/lighthouse:stable-minimal", + "teku": "consensys/teku:latest", + "nimbus": "ethpandaops/nimbus-eth2:stable-minimal", + "prysm": "ethpandaops/prysm-beacon-chain:develop-minimal", + "lodestar": "chainsafe/lodestar:latest", + "grandine": "ethpandaops/grandine:master-minimal", } DEFAULT_VC_IMAGES = { "lighthouse": "sigp/lighthouse:latest", - "lodestar": "chainsafe/lodestar:next", + "lodestar": "chainsafe/lodestar:latest", "nimbus": "statusim/nimbus-validator-client:multiarch-latest", "prysm": "gcr.io/prysmaticlabs/prysm/validator:latest", "teku": "consensys/teku:latest", - "grandine": "sifrai/grandine:latest", + "grandine": "ethpandaops/grandine:master", } -MEV_BOOST_RELAY_DEFAULT_IMAGE = "flashbots/mev-boost-relay:0.27" - -MEV_BOOST_RELAY_IMAGE_NON_ZERO_CAPELLA = "flashbots/mev-boost-relay:0.26" +DEFAULT_VC_IMAGES_MINIMAL = { + "lighthouse": "ethpandaops/lighthouse:stable-minimal", + "lodestar": "chainsafe/lodestar:latest", + "nimbus": "ethpandaops/nimbus-validator-client:stable-minimal", + "prysm": "ethpandaops/prysm-validator:develop-minimal", + "teku": "consensys/teku:latest", + "grandine": "ethpandaops/grandine:master-minimal", +} # Placeholder value for the deneb fork epoch if electra is being run # TODO: This is a hack, and should be removed once we electra is rebased on deneb HIGH_DENEB_VALUE_FORK_VERKLE = 2000000000 # MEV Params -FLASHBOTS_MEV_BOOST_PORT = 18550 +MEV_BOOST_PORT = 18550 MEV_BOOST_SERVICE_NAME_PREFIX = "mev-boost" # Minimum number of validators required for a network to be valid is 64 @@ -70,11 +84,12 @@ ATTR_TO_BE_SKIPPED_AT_ROOT = ( def input_parser(plan, input_args): - result = parse_network_params(input_args) + result = parse_network_params(plan, input_args) # add default eth2 input params - result["mev_type"] = None - result["mev_params"] = get_default_mev_params() + result["mev_params"] = get_default_mev_params( + result.get("mev_type"), result["network_params"]["preset"] + ) if ( result["network_params"]["network"] == constants.NETWORK_NAME.kurtosis or constants.NETWORK_NAME.shadowfork in result["network_params"]["network"] @@ -144,13 +159,25 @@ def input_parser(plan, input_args): if result.get("disable_peer_scoring"): result = enrich_disable_peer_scoring(result) - if result.get("mev_type") in ("mock", "full"): + if result.get("mev_type") in ( + constants.MOCK_MEV_TYPE, + constants.FLASHBOTS_MEV_TYPE, + constants.MEV_RS_MEV_TYPE, + ): result = enrich_mev_extra_params( result, MEV_BOOST_SERVICE_NAME_PREFIX, - FLASHBOTS_MEV_BOOST_PORT, + MEV_BOOST_PORT, result.get("mev_type"), ) + elif result.get("mev_type") == None: + pass + else: + fail( + "Unsupported MEV type: {0}, please use 'mock', 'flashbots' or 'mev-rs' type".format( + result.get("mev_type") + ) + ) if result["port_publisher"]["nat_exit_ip"] == "auto": result["port_publisher"]["nat_exit_ip"] = get_public_ip(plan) @@ -252,6 +279,7 @@ def input_parser(plan, input_args): mev_relay_image=result["mev_params"]["mev_relay_image"], mev_builder_image=result["mev_params"]["mev_builder_image"], mev_builder_cl_image=result["mev_params"]["mev_builder_cl_image"], + mev_builder_extra_data=result["mev_params"]["mev_builder_extra_data"], mev_boost_image=result["mev_params"]["mev_boost_image"], mev_boost_args=result["mev_params"]["mev_boost_args"], mev_relay_api_extra_args=result["mev_params"]["mev_relay_api_extra_args"], @@ -267,7 +295,9 @@ def input_parser(plan, input_args): mev_flood_seconds_per_bundle=result["mev_params"][ "mev_flood_seconds_per_bundle" ], - ), + ) + if result["mev_params"] + else None, tx_spammer_params=struct( tx_spammer_extra_args=result["tx_spammer_params"]["tx_spammer_extra_args"], ), @@ -325,8 +355,10 @@ def input_parser(plan, input_args): ) -def parse_network_params(input_args): +def parse_network_params(plan, input_args): result = default_input_args() + if input_args.get("network_params", {}).get("preset") == "minimal": + result["network_params"] = default_minimal_network_params() for attr in input_args: value = input_args[attr] # if its insterted we use the value inserted @@ -391,7 +423,10 @@ def parse_network_params(input_args): cl_image = participant["cl_image"] if cl_image == "": - default_image = DEFAULT_CL_IMAGES.get(cl_type, "") + if result["network_params"]["preset"] == "minimal": + default_image = DEFAULT_CL_IMAGES_MINIMAL.get(cl_type, "") + else: + default_image = DEFAULT_CL_IMAGES.get(cl_type, "") if default_image == "": fail( "{0} received an empty image name and we don't have a default for it".format( @@ -425,7 +460,10 @@ def parse_network_params(input_args): if vc_image == "": if cl_image == "" or vc_type != cl_type: # If the validator client image is also empty, default to the image for the chosen CL client - default_image = DEFAULT_VC_IMAGES.get(vc_type, "") + if result["network_params"]["preset"] == "minimal": + default_image = DEFAULT_VC_IMAGES_MINIMAL.get(vc_type, "") + else: + default_image = DEFAULT_VC_IMAGES.get(vc_type, "") else: if cl_type == "prysm": default_image = cl_image.replace("beacon-chain", "validator") @@ -638,7 +676,6 @@ def default_input_args(): def default_network_params(): - # this is temporary till we get params working return { "network": "kurtosis", "network_id": "3151908", @@ -660,6 +697,28 @@ def default_network_params(): } +def default_minimal_network_params(): + return { + "network": "kurtosis", + "network_id": "3151908", + "deposit_contract_address": "0x4242424242424242424242424242424242424242", + "seconds_per_slot": 6, + "num_validator_keys_per_node": 64, + "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", + "preregistered_validator_count": 0, + "genesis_delay": 20, + "max_churn": 4, + "ejection_balance": 16000000000, + "eth1_follow_distance": 16, + "min_validator_withdrawability_delay": 256, + "shard_committee_period": 64, + "deneb_fork_epoch": 0, + "electra_fork_epoch": 500, + "network_sync_base_url": "https://ethpandaops-ethereum-node-snapshots.ams3.digitaloceanspaces.com/", + "preset": "minimal", + } + + def default_participant(): return { "el_type": "geth", @@ -716,24 +775,59 @@ def default_participant(): } -def get_default_mev_params(): +def get_default_mev_params(mev_type, preset): + mev_relay_image = constants.DEFAULT_FLASHBOTS_RELAY_IMAGE + mev_builder_image = constants.DEFAULT_FLASHBOTS_BUILDER_IMAGE + if preset == "minimal": + mev_builder_cl_image = DEFAULT_CL_IMAGES_MINIMAL[constants.CL_TYPE.lighthouse] + else: + mev_builder_cl_image = DEFAULT_CL_IMAGES[constants.CL_TYPE.lighthouse] + mev_builder_extra_data = None + mev_boost_image = constants.DEFAULT_FLASHBOTS_MEV_BOOST_IMAGE + mev_boost_args = ["mev-boost", "--relay-check"] + mev_relay_api_extra_args = [] + mev_relay_housekeeper_extra_args = [] + mev_relay_website_extra_args = [] + mev_builder_extra_args = [] + mev_flood_image = "flashbots/mev-flood" + mev_flood_extra_args = [] + mev_flood_seconds_per_bundle = 15 + mev_builder_prometheus_config = { + "scrape_interval": "15s", + "labels": None, + } + + if mev_type == constants.MEV_RS_MEV_TYPE: + if preset == "minimal": + mev_relay_image = constants.DEFAULT_MEV_RS_IMAGE_MINIMAL + mev_builder_image = constants.DEFAULT_MEV_RS_IMAGE_MINIMAL + mev_builder_cl_image = DEFAULT_CL_IMAGES_MINIMAL[ + constants.CL_TYPE.lighthouse + ] + mev_boost_image = constants.DEFAULT_MEV_RS_IMAGE_MINIMAL + else: + mev_relay_image = constants.DEFAULT_MEV_RS_IMAGE + mev_builder_image = constants.DEFAULT_MEV_RS_IMAGE + mev_builder_cl_image = DEFAULT_CL_IMAGES[constants.CL_TYPE.lighthouse] + mev_boost_image = constants.DEFAULT_MEV_RS_IMAGE + mev_builder_extra_data = "0x68656C6C6F20776F726C640A" # "hello world\n" + mev_builder_extra_args = ["--mev-builder-config=" + "/config/config.toml"] + return { - "mev_relay_image": MEV_BOOST_RELAY_DEFAULT_IMAGE, - "mev_builder_image": "flashbots/builder:latest", - "mev_builder_cl_image": "sigp/lighthouse:latest", - "mev_boost_image": "flashbots/mev-boost", - "mev_boost_args": ["mev-boost", "--relay-check"], - "mev_relay_api_extra_args": [], - "mev_relay_housekeeper_extra_args": [], - "mev_relay_website_extra_args": [], - "mev_builder_extra_args": [], - "mev_flood_image": "flashbots/mev-flood", - "mev_flood_extra_args": [], - "mev_flood_seconds_per_bundle": 15, - "mev_builder_prometheus_config": { - "scrape_interval": "15s", - "labels": None, - }, + "mev_relay_image": mev_relay_image, + "mev_builder_image": mev_builder_image, + "mev_builder_cl_image": mev_builder_cl_image, + "mev_builder_extra_data": mev_builder_extra_data, + "mev_builder_extra_args": mev_builder_extra_args, + "mev_boost_image": mev_boost_image, + "mev_boost_args": mev_boost_args, + "mev_relay_api_extra_args": mev_relay_api_extra_args, + "mev_relay_housekeeper_extra_args": mev_relay_housekeeper_extra_args, + "mev_relay_website_extra_args": mev_relay_website_extra_args, + "mev_flood_image": mev_flood_image, + "mev_flood_extra_args": mev_flood_extra_args, + "mev_flood_seconds_per_bundle": mev_flood_seconds_per_bundle, + "mev_builder_prometheus_config": mev_builder_prometheus_config, } @@ -843,9 +937,9 @@ def enrich_mev_extra_params(parsed_arguments_dict, mev_prefix, mev_port, mev_typ index_str = shared_utils.zfill_custom( num_participants + 1, len(str(num_participants + 1)) ) - if mev_type == "full": + if mev_type == constants.FLASHBOTS_MEV_TYPE: mev_participant = default_participant() - mev_participant["el_type"] = mev_participant["el_type"] + "-builder" + mev_participant["el_type"] = "geth-builder" mev_participant.update( { "el_image": parsed_arguments_dict["mev_params"]["mev_builder_image"], @@ -890,6 +984,26 @@ def enrich_mev_extra_params(parsed_arguments_dict, mev_prefix, mev_port, mev_typ parsed_arguments_dict["participants"].append(mev_participant) + if mev_type == constants.MEV_RS_MEV_TYPE: + mev_participant = default_participant() + mev_participant["el_type"] = "reth-builder" + mev_participant.update( + { + "el_image": parsed_arguments_dict["mev_params"]["mev_builder_image"], + "cl_image": parsed_arguments_dict["mev_params"]["mev_builder_cl_image"], + "cl_extra_params": [ + "--always-prepare-payload", + "--prepare-payload-lookahead", + "12000", + "--disable-peer-scoring", + ], + "el_extra_params": parsed_arguments_dict["mev_params"][ + "mev_builder_extra_args" + ], + "validator_count": 0, + } + ) + parsed_arguments_dict["participants"].append(mev_participant) return parsed_arguments_dict diff --git a/src/participant_network.star b/src/participant_network.star index 54fe05027..52cacb755 100644 --- a/src/participant_network.star +++ b/src/participant_network.star @@ -337,6 +337,7 @@ def launch_participant_network( global_tolerations=global_tolerations, node_selectors=node_selectors, keymanager_enabled=participant.keymanager_enabled, + preset=network_params.preset, network=network_params.network, electra_fork_epoch=network_params.electra_fork_epoch, ) diff --git a/src/static_files/static_files.star b/src/static_files/static_files.star index 022f5b300..a6e50f1de 100644 --- a/src/static_files/static_files.star +++ b/src/static_files/static_files.star @@ -77,8 +77,16 @@ CL_GENESIS_GENERATION_MNEMONICS_TEMPLATE_FILEPATH = ( JWT_PATH_FILEPATH = STATIC_FILES_DIRPATH + "/jwt/jwtsecret" KEYMANAGER_PATH_FILEPATH = STATIC_FILES_DIRPATH + "/keymanager/keymanager.txt" -KEYMANAGER_P12_PATH_FILEPATH = ( - STATIC_FILES_DIRPATH + "/keymanager/validator_keystore.p12" -) + SHADOWFORK_FILEPATH = "/network-configs/latest_block.json" + +MEV_RS_MEV_BOOST_CONFIG_FILEPATH = ( + STATIC_FILES_DIRPATH + "/mev/mev-rs/mev_boost/config.toml.tmpl" +) +MEV_RS_MEV_RELAY_CONFIG_FILEPATH = ( + STATIC_FILES_DIRPATH + "/mev/mev-rs/mev_relay/config.toml.tmpl" +) +MEV_RS_MEV_BUILDER_CONFIG_FILEPATH = ( + STATIC_FILES_DIRPATH + "/mev/mev-rs/mev_builder/config.toml.tmpl" +) diff --git a/src/transaction_spammer/transaction_spammer.star b/src/transaction_spammer/transaction_spammer.star index 275492a6d..53279a87a 100644 --- a/src/transaction_spammer/transaction_spammer.star +++ b/src/transaction_spammer/transaction_spammer.star @@ -33,11 +33,7 @@ def get_config( electra_fork_epoch, node_selectors, ): - # Temp hack to use the old tx-fuzz image until we can get the new one working - if electra_fork_epoch != None: - tx_spammer_image = "ethpandaops/tx-fuzz:kaustinen-281adbc" - else: - tx_spammer_image = "ethpandaops/tx-fuzz:master" + tx_spammer_image = "ethpandaops/tx-fuzz:master" cmd = [ "spam", diff --git a/src/vc/lodestar.star b/src/vc/lodestar.star index fb16f443a..3b3c1ca9b 100644 --- a/src/vc/lodestar.star +++ b/src/vc/lodestar.star @@ -33,6 +33,7 @@ def get_config( tolerations, node_selectors, keymanager_enabled, + preset, ): log_level = input_parser.get_client_log_level_or_default( participant_log_level, global_log_level, VERBOSITY_LEVELS @@ -93,6 +94,9 @@ def get_config( cmd.extend(keymanager_api_cmd) ports.update(vc_shared.VALIDATOR_KEYMANAGER_USED_PORTS) + if preset == "minimal": + extra_env_vars["LODESTAR_PRESET"] = "minimal" + return ServiceConfig( image=image, ports=ports, diff --git a/src/vc/vc_launcher.star b/src/vc/vc_launcher.star index cb36fd8e0..36163dd2a 100644 --- a/src/vc/vc_launcher.star +++ b/src/vc/vc_launcher.star @@ -46,6 +46,7 @@ def launch( global_tolerations, node_selectors, keymanager_enabled, + preset, network, # TODO: remove when deneb rebase is done electra_fork_epoch, # TODO: remove when deneb rebase is done ): @@ -116,6 +117,7 @@ def launch( tolerations=tolerations, node_selectors=node_selectors, keymanager_enabled=keymanager_enabled, + preset=preset, ) elif vc_type == constants.VC_TYPE.teku: config = teku.get_config( diff --git a/static_files/mev/mev-rs/mev_boost/config.toml.tmpl b/static_files/mev/mev-rs/mev_boost/config.toml.tmpl new file mode 100644 index 000000000..a595a5009 --- /dev/null +++ b/static_files/mev/mev-rs/mev_boost/config.toml.tmpl @@ -0,0 +1,10 @@ +network = "{{ .Network }}" + +[boost] +host = "0.0.0.0" +port = {{ .Port }} +relays = [ +{{ range $relays := .Relays }} + "{{ $relays }}", +{{- end }} +] diff --git a/static_files/mev/mev-rs/mev_builder/config.toml.tmpl b/static_files/mev/mev-rs/mev_builder/config.toml.tmpl new file mode 100644 index 000000000..57c05b112 --- /dev/null +++ b/static_files/mev/mev-rs/mev_builder/config.toml.tmpl @@ -0,0 +1,37 @@ +network = "{{ .Network }}" + +[builder] +# number of milliseconds to submit bids ahead of the target slot +bidding_deadline_ms = 1000 +# amount of value to bid as a fraction of the payload's revenue +bid_percent = 0.9 +# amount to add to the bid on top of the payload's revenue, +# currently sourced from the builder's wallet authoring the payment transaction +subsidy_gwei = 100000000 # 0.1 eth + +[builder.auctioneer] +# builder BLS secret key +secret_key = "{{ .SecretKey }}" +# list of relays to connect to +relays = [ + "http://{{ .PublicKey }}@{{ .Relay }}:{{ .RelayPort }}", +] +[builder.builder] +# address to collect transaction fees +fee_recipient = "{{ .FeeRecipient }}" +# [optional] extra data to write into built execution payload +extra_data = "{{ .ExtraData }}" +# wallet seed for builder to author payment transactions +execution_mnemonic = "{{ .Mnemonic }}" + +[builder.bidder] +# amount in milliseconds of time to wait until submitting bids +wait_until_ms = 3000 +# [optional] amount of value to bid as a fraction of the payload's revenue +# if missing, defaults to 1.0 (100%) +# validation: should be between [0, 1] inclusive. +bid_percent = 0.9 +# [optional] amount to add to the bid on top of the payload's revenue, +# if missing, defaults to 0 wei +# currently sourced from the builder's wallet authoring the payment transaction +subsidy_wei = "0x0000000000000000000000000000000000000000000000000000000000000001" diff --git a/static_files/mev/mev-rs/mev_relay/config.toml.tmpl b/static_files/mev/mev-rs/mev_relay/config.toml.tmpl new file mode 100644 index 000000000..2c4005e9c --- /dev/null +++ b/static_files/mev/mev-rs/mev_relay/config.toml.tmpl @@ -0,0 +1,10 @@ +network = "{{ .Network }}" + +[relay] +host = "0.0.0.0" +port = {{ .Port }} +beacon_node_url = "{{ .BeaconNodeURL }}" +secret_key = "{{ .SecretKey }}" +accepted_builders = [ + "{{ .PublicKey }}", +]