Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Tx_spamer_params and move MEV to the bottom of main.star #208

Merged
merged 5 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,12 @@ To configure the package behaviour, you can modify your `network_params.json` fi
"deneb_fork_epoch": 4,
"electra_fork_epoch": null,
},

// Configuration place for transaction spammer - https://github.com/MariusVanDerWijden/tx-fuzz
"tx_spammer_params": {
// A list of optional extra params that will be passed to the TX Spammer container for modifying its behaviour
"tx_spammer_extra_args": []
}

// True by defaults such that in addition to the Ethereum network:
// - A transaction spammer is launched to fake transactions sent to the network
Expand Down
94 changes: 48 additions & 46 deletions main.star
Original file line number Diff line number Diff line change
Expand Up @@ -52,57 +52,14 @@ def run(plan, args = {}):
for participant in all_participants:
all_el_client_contexts.append(participant.el_client_context)
all_cl_client_contexts.append(participant.cl_client_context)


mev_endpoints = []
# passed external relays get priority
# perhaps add mev_type External or remove this
if hasattr(participant, "builder_network_params") and participant.builder_network_params != None:
mev_endpoints = participant.builder_network_params.relay_end_points
# otherwise dummy relays spinup if chosen
elif args_with_right_defaults.mev_type and args_with_right_defaults.mev_type == MOCK_MEV_TYPE:
el_uri = "{0}:{1}".format(all_el_client_contexts[0].ip_addr, all_el_client_contexts[0].engine_rpc_port_num)
beacon_uri = "{0}:{1}".format(all_cl_client_contexts[0].ip_addr, all_cl_client_contexts[0].http_port_num)
jwt_secret = all_el_client_contexts[0].jwt_secret
endpoint = mock_mev_launcher_module.launch_mock_mev(plan, el_uri, beacon_uri, jwt_secret, args_with_right_defaults.global_client_log_level)
mev_endpoints.append(endpoint)
elif args_with_right_defaults.mev_type and args_with_right_defaults.mev_type == FULL_MEV_TYPE:
el_uri = "http://{0}:{1}".format(all_el_client_contexts[0].ip_addr, all_el_client_contexts[0].rpc_port_num)
builder_uri = "http://{0}:{1}".format(all_el_client_contexts[-1].ip_addr, all_el_client_contexts[-1].rpc_port_num)
beacon_uri = ["http://{0}:{1}".format(context.ip_addr, context.http_port_num) for context in all_cl_client_contexts][-1]
beacon_uris = beacon_uri
first_cl_client = all_cl_client_contexts[0]
first_client_beacon_name = first_cl_client.beacon_service_name
mev_flood_module.launch_mev_flood(plan, mev_params.mev_flood_image, el_uri, genesis_constants.PRE_FUNDED_ACCOUNTS)
epoch_recipe = GetHttpRequestRecipe(
endpoint = "/eth/v2/beacon/blocks/head",
port_id = HTTP_PORT_ID_FOR_FACT,
extract = {
"epoch": ".data.message.body.attestations[0].data.target.epoch"
}
)
plan.wait(recipe = epoch_recipe, field = "extract.epoch", assertion = ">=", target_value = str(network_params.capella_fork_epoch), timeout = "20m", service_name = first_client_beacon_name)
plan.print("epoch 2 reached, can begin mev stuff")
endpoint = mev_relay_launcher_module.launch_mev_relay(plan, mev_params, network_params.network_id, beacon_uris, genesis_validators_root, builder_uri, network_params.seconds_per_slot, network_params.slots_per_epoch)
mev_flood_module.spam_in_background(plan, el_uri, mev_params.mev_flood_extra_args, mev_params.mev_flood_seconds_per_bundle, genesis_constants.PRE_FUNDED_ACCOUNTS)
if args_with_right_defaults.mev_params.launch_custom_flood:
mev_custom_flood_module.spam_in_background(plan, genesis_constants.PRE_FUNDED_ACCOUNTS[-1].private_key, genesis_constants.PRE_FUNDED_ACCOUNTS[0].address, el_uri)
mev_endpoints.append(endpoint)

# spin up the mev boost contexts if some endpoints for relays have been passed
all_mevboost_contexts = []
if mev_endpoints:
for index, participant in enumerate(all_participants):
mev_boost_launcher = mev_boost_launcher_module.new_mev_boost_launcher(MEV_BOOST_SHOULD_CHECK_RELAY, mev_endpoints)
mev_boost_service_name = "{0}{1}".format(parse_input.MEV_BOOST_SERVICE_NAME_PREFIX, index)
mev_boost_context = mev_boost_launcher_module.launch(plan, mev_boost_launcher, mev_boost_service_name, network_params.network_id, mev_params.mev_boost_image)
all_mevboost_contexts.append(mev_boost_context)


if not args_with_right_defaults.launch_additional_services:
return

plan.print("Launching transaction spammer")
transaction_spammer.launch_transaction_spammer(plan, genesis_constants.PRE_FUNDED_ACCOUNTS, all_el_client_contexts[0])
tx_spammer_params = args_with_right_defaults.tx_spammer_params
transaction_spammer.launch_transaction_spammer(plan, genesis_constants.PRE_FUNDED_ACCOUNTS, all_el_client_contexts[0], tx_spammer_params)
plan.print("Succesfully launched transaction spammer")

plan.print("Launching Blob spammer")
Expand Down Expand Up @@ -184,4 +141,49 @@ def run(plan, args = {}):
)
output = struct(grafana_info = grafana_info)


mev_endpoints = []
# passed external relays get priority
# perhaps add mev_type External or remove this
if hasattr(participant, "builder_network_params") and participant.builder_network_params != None:
mev_endpoints = participant.builder_network_params.relay_end_points
# otherwise dummy relays spinup if chosen
elif args_with_right_defaults.mev_type and args_with_right_defaults.mev_type == MOCK_MEV_TYPE:
el_uri = "{0}:{1}".format(all_el_client_contexts[0].ip_addr, all_el_client_contexts[0].engine_rpc_port_num)
beacon_uri = "{0}:{1}".format(all_cl_client_contexts[0].ip_addr, all_cl_client_contexts[0].http_port_num)
jwt_secret = all_el_client_contexts[0].jwt_secret
endpoint = mock_mev_launcher_module.launch_mock_mev(plan, el_uri, beacon_uri, jwt_secret, args_with_right_defaults.global_client_log_level)
mev_endpoints.append(endpoint)
elif args_with_right_defaults.mev_type and args_with_right_defaults.mev_type == FULL_MEV_TYPE:
el_uri = "http://{0}:{1}".format(all_el_client_contexts[0].ip_addr, all_el_client_contexts[0].rpc_port_num)
builder_uri = "http://{0}:{1}".format(all_el_client_contexts[-1].ip_addr, all_el_client_contexts[-1].rpc_port_num)
beacon_uri = ["http://{0}:{1}".format(context.ip_addr, context.http_port_num) for context in all_cl_client_contexts][-1]
beacon_uris = beacon_uri
first_cl_client = all_cl_client_contexts[0]
first_client_beacon_name = first_cl_client.beacon_service_name
mev_flood_module.launch_mev_flood(plan, mev_params.mev_flood_image, el_uri, genesis_constants.PRE_FUNDED_ACCOUNTS)
epoch_recipe = GetHttpRequestRecipe(
endpoint = "/eth/v2/beacon/blocks/head",
port_id = HTTP_PORT_ID_FOR_FACT,
extract = {
"epoch": ".data.message.body.attestations[0].data.target.epoch"
}
)
plan.wait(recipe = epoch_recipe, field = "extract.epoch", assertion = ">=", target_value = str(network_params.capella_fork_epoch), timeout = "20m", service_name = first_client_beacon_name)
plan.print("epoch 2 reached, can begin mev stuff")
endpoint = mev_relay_launcher_module.launch_mev_relay(plan, mev_params, network_params.network_id, beacon_uris, genesis_validators_root, builder_uri, network_params.seconds_per_slot, network_params.slots_per_epoch)
mev_flood_module.spam_in_background(plan, el_uri, mev_params.mev_flood_extra_args, mev_params.mev_flood_seconds_per_bundle, genesis_constants.PRE_FUNDED_ACCOUNTS)
if args_with_right_defaults.mev_params.launch_custom_flood:
mev_custom_flood_module.spam_in_background(plan, genesis_constants.PRE_FUNDED_ACCOUNTS[-1].private_key, genesis_constants.PRE_FUNDED_ACCOUNTS[0].address, el_uri)
mev_endpoints.append(endpoint)

# spin up the mev boost contexts if some endpoints for relays have been passed
all_mevboost_contexts = []
if mev_endpoints:
for index, participant in enumerate(all_participants):
mev_boost_launcher = mev_boost_launcher_module.new_mev_boost_launcher(MEV_BOOST_SHOULD_CHECK_RELAY, mev_endpoints)
mev_boost_service_name = "{0}{1}".format(parse_input.MEV_BOOST_SERVICE_NAME_PREFIX, index)
mev_boost_context = mev_boost_launcher_module.launch(plan, mev_boost_launcher, mev_boost_service_name, network_params.network_id, mev_params.mev_boost_image)
all_mevboost_contexts.append(mev_boost_context)

return output
12 changes: 11 additions & 1 deletion src/package_io/parse_input.star
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
FLASHBOTS_MEV_BOOST_PORT = 18550
MEV_BOOST_SERVICE_NAME_PREFIX = "mev-boost-"

ATTR_TO_BE_SKIPPED_AT_ROOT = ("network_params", "participants", "mev_params")
ATTR_TO_BE_SKIPPED_AT_ROOT = ("network_params", "participants", "mev_params", "tx_spammer_params")

package_io_constants = import_module("github.com/kurtosis-tech/eth-network-package/package_io/constants.star")
package_io_parser = import_module("github.com/kurtosis-tech/eth-network-package/package_io/input_parser.star")
Expand Down Expand Up @@ -35,6 +35,8 @@ def parse_input(plan, input_args):
if result.get("mev_type") == "full" and result["network_params"]["capella_fork_epoch"] == 0:
fail("capella_fork_epoch needs to be set to a non-zero value when using full MEV, set it using network_params.capella_fork_epoch")

result["tx_spammer_params"] = get_default_tx_spammer_params()

return struct(
participants=[struct(
el_client_type=participant["el_client_type"],
Expand Down Expand Up @@ -73,6 +75,9 @@ def parse_input(plan, input_args):
mev_flood_seconds_per_bundle = result["mev_params"]["mev_flood_seconds_per_bundle"],
launch_custom_flood = result["mev_params"]["launch_custom_flood"],
),
tx_spammer_params = struct(
tx_spammer_extra_args = result["tx_spammer_params"]["tx_spammer_extra_args"],
),
launch_additional_services=result["launch_additional_services"],
wait_for_finalization=result["wait_for_finalization"],
wait_for_verifications=result["wait_for_verifications"],
Expand All @@ -98,6 +103,11 @@ def get_default_mev_params():
"launch_custom_flood": False
}

def get_default_tx_spammer_params():
return {
"tx_spammer_extra_args": []
}

# TODO perhaps clean this up into a map
def enrich_mev_extra_params(parsed_arguments_dict, mev_prefix, mev_port, mev_type):
for index, participant in enumerate(parsed_arguments_dict["participants"]):
Expand Down
10 changes: 6 additions & 4 deletions src/transaction_spammer/transaction_spammer.star
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
#TODO: Add Image and Service Name to tx_spammer_params
IMAGE_NAME = "ethpandaops/tx-fuzz:latest"
SERVICE_NAME = "transaction-spammer"

def launch_transaction_spammer(plan, prefunded_addresses, el_client_context):
config = get_config(prefunded_addresses, el_client_context)
def launch_transaction_spammer(plan, prefunded_addresses, el_client_context, tx_spammer_params):
config = get_config(prefunded_addresses, el_client_context, tx_spammer_params.tx_spammer_extra_args)
plan.add_service(SERVICE_NAME, config)


def get_config(prefunded_addresses, el_client_context):
def get_config(prefunded_addresses, el_client_context, tx_spammer_extra_args):
return ServiceConfig(
image = IMAGE_NAME,
cmd = [
"spam",
"--rpc=http://{0}:{1}".format(el_client_context.ip_addr, el_client_context.rpc_port_num),
"--sk={0}".format(prefunded_addresses[3].private_key),
"--sk={0}".format(prefunded_addresses[0].private_key),
"{0}".format(" ".join(tx_spammer_extra_args))
kamilchodola marked this conversation as resolved.
Show resolved Hide resolved
]
)