From 28f7b7d4849ceeab56ac648949b74a1aa0e28dee Mon Sep 17 00:00:00 2001 From: pk910 Date: Wed, 18 Dec 2024 16:23:36 +0100 Subject: [PATCH] fix: replace goomy with spamoor (#860) This PR replaces [goomy](https://github.com/ethpandaops/goomy-blob) with [spamoor](https://github.com/ethpandaops/spamoor). The spamoor project is based on goomy, but was improved a lot to handle high transaction throughput reliably. It supports all features that goomy provides, but blob scenarios are prefixed with `blob-`. As spamoor works much better by now, it makes sense to deprecate goomy and replace it with spamoor. --- .github/tests/geth-all.yaml | 2 +- .github/tests/mev.yaml | 2 +- .github/tests/mix-with-tools-mev.yaml | 2 +- .github/tests/mix-with-tools-minimal.yaml | 2 +- .github/tests/mix-with-tools.yaml | 2 +- .github/tests/peerdas-fulu.yaml.norun | 2 +- README.md | 50 ++++++++++++----- main.star | 24 ++++---- network_params.yaml | 4 +- src/goomy_blob/goomy_blob.star | 67 ----------------------- src/package_io/input_parser.star | 47 ++++++++++------ src/package_io/sanity_check.star | 16 ++++-- src/spamoor/spamoor.star | 14 +++-- src/spamoor_blob/spamoor_blob.star | 64 ++++++++++++++++++++++ 14 files changed, 169 insertions(+), 129 deletions(-) delete mode 100644 src/goomy_blob/goomy_blob.star create mode 100644 src/spamoor_blob/spamoor_blob.star diff --git a/.github/tests/geth-all.yaml b/.github/tests/geth-all.yaml index 681d221c0..1e75c41f6 100644 --- a/.github/tests/geth-all.yaml +++ b/.github/tests/geth-all.yaml @@ -12,5 +12,5 @@ participants: - el_type: geth cl_type: grandine additional_services: - - goomy_blob + - spamoor_blob - dora diff --git a/.github/tests/mev.yaml b/.github/tests/mev.yaml index e3331ff0f..28f81586e 100644 --- a/.github/tests/mev.yaml +++ b/.github/tests/mev.yaml @@ -6,7 +6,7 @@ additional_services: - tx_spammer - blob_spammer - custom_flood - - goomy_blob + - spamoor_blob - beacon_metrics_gazer - dora - prometheus_grafana diff --git a/.github/tests/mix-with-tools-mev.yaml b/.github/tests/mix-with-tools-mev.yaml index ae82f9943..a228e77d3 100644 --- a/.github/tests/mix-with-tools-mev.yaml +++ b/.github/tests/mix-with-tools-mev.yaml @@ -18,7 +18,7 @@ additional_services: - beacon_metrics_gazer - dora - prometheus_grafana - - goomy_blob + - spamoor_blob - custom_flood - blobscan - blockscout diff --git a/.github/tests/mix-with-tools-minimal.yaml b/.github/tests/mix-with-tools-minimal.yaml index 744789604..119dfca6f 100644 --- a/.github/tests/mix-with-tools-minimal.yaml +++ b/.github/tests/mix-with-tools-minimal.yaml @@ -20,7 +20,7 @@ additional_services: - beacon_metrics_gazer - dora - prometheus_grafana - - goomy_blob + - spamoor_blob - custom_flood - blobscan - blockscout diff --git a/.github/tests/mix-with-tools.yaml b/.github/tests/mix-with-tools.yaml index bc9317ff6..d91e6c08b 100644 --- a/.github/tests/mix-with-tools.yaml +++ b/.github/tests/mix-with-tools.yaml @@ -20,7 +20,7 @@ additional_services: - beacon_metrics_gazer - dora - prometheus_grafana - - goomy_blob + - spamoor_blob - custom_flood - blobscan - blockscout diff --git a/.github/tests/peerdas-fulu.yaml.norun b/.github/tests/peerdas-fulu.yaml.norun index 49e130978..f39fafb3c 100644 --- a/.github/tests/peerdas-fulu.yaml.norun +++ b/.github/tests/peerdas-fulu.yaml.norun @@ -34,7 +34,7 @@ snooper_enabled: true global_log_level: debug additional_services: - dora - - goomy_blob + - spamoor_blob - prometheus_grafana - assertoor ethereum_metrics_exporter_enabled: true diff --git a/README.md b/README.md index 99a94d26e..debf95222 100644 --- a/README.md +++ b/README.md @@ -644,7 +644,8 @@ additional_services: - tx_spammer - blob_spammer - custom_flood - - goomy_blob + - spamoor + - spamoor_blob - el_forkmon - blockscout - beacon_metrics_gazer @@ -686,14 +687,6 @@ 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: [] -# Configuration place for goomy the blob spammer - https://github.com/ethpandaops/goomy-blob -goomy_blob_params: - # Goomy Blob docker image to use - # Defaults to the latest - image: "ethpandaops/goomy-blob:latest" - # A list of optional params that will be passed to the blob-spammer comamnd for modifying its behaviour - goomy_blob_args: [] - # Configuration place for prometheus prometheus_params: storage_tsdb_retention_time: "1d" @@ -936,14 +929,15 @@ checkpoint_sync_enabled: false # Global flag to set checkpoint sync url checkpoint_sync_url: "" -# Spamoor params +# Configuration place for spamoor as transaction spammer spamoor_params: # The image to use for spamoor image: ethpandaops/spamoor:latest - # The type of transactions to send - # Valid values are eoatx, erctx, deploytx, depoy-destruct, blobs, gasburnertx + # The spamoor scenario to use (see https://github.com/ethpandaops/spamoor) + # Valid scenarios are: + # eoatx, erctx, deploytx, depoy-destruct, blobs, gasburnertx # Defaults to eoatx - tx_type: eoatx + scenario: eoatx # Throughput of spamoor # Defaults to 1000 throughput: 1000 @@ -957,6 +951,34 @@ spamoor_params: # Defaults to empty spamoor_extra_args: [] +# Configuration place for spammor as blob spammer +spamoor_blob_params: + # spamoor docker image to use + # Defaults to the latest + image: "ethpandaops/spamoor:latest" + # The spamoor blob scenario to use (see https://github.com/ethpandaops/spamoor) + # Valid blob scenarios are: + # - blobs (normal blob transactions only) + # - blob-combined (normal & special blobs with replacements) + # - blob-conflicting (conflicting blob & dynfee transactions) + # - blob-replacements (normal blobs with replacement blob transactions) + # Defaults to blob-combined + scenario: blob-combined + # Throughput of spamoor + # Defaults to 3 + throughput: 3 + # Maximum number of blobs per transaction + # Defaults to 2 + max_blobs: 2 + # Max pending blob transactions for spamoor + # Defaults to 6 + max_pending: 6 + # Max wallets for spamoor + # Defaults to 20 + max_wallets: 20 + # A list of optional params that will be passed to the spamoor comamnd for modifying its behaviour + spamoor_extra_args: [] + # Ethereum genesis generator params ethereum_genesis_generator_params: # The image to use for ethereum genesis generator @@ -1195,7 +1217,7 @@ Here's a table of where the keys are used | 0 | mev_custom_flood | | ✅ | As the receiver of balance | | 1 | blob_spammer | ✅ | | As the sender of blobs | | 3 | transaction_spammer | ✅ | | To spam transactions with | -| 4 | goomy_blob | ✅ | | As the sender of blobs | +| 4 | spamoor_blob | ✅ | | As the sender of blobs | | 6 | mev_flood | ✅ | | As the contract owner | | 7 | mev_flood | ✅ | | As the user_key | | 8 | assertoor | ✅ | ✅ | As the funding for tests | diff --git a/main.star b/main.star index 1f39d5f6d..2d2925792 100644 --- a/main.star +++ b/main.star @@ -15,7 +15,7 @@ transaction_spammer = import_module( "./src/transaction_spammer/transaction_spammer.star" ) blob_spammer = import_module("./src/blob_spammer/blob_spammer.star") -goomy_blob = import_module("./src/goomy_blob/goomy_blob.star") +spamoor_blob = import_module("./src/spamoor_blob/spamoor_blob.star") el_forkmon = import_module("./src/el_forkmon/el_forkmon_launcher.star") beacon_metrics_gazer = import_module( "./src/beacon_metrics_gazer/beacon_metrics_gazer_launcher.star" @@ -462,19 +462,6 @@ def run(plan, args={}): args_with_right_defaults.tx_spammer_params, ) plan.print("Successfully launched blob spammer") - elif additional_service == "goomy_blob": - plan.print("Launching Goomy the blob spammer") - goomy_blob_params = args_with_right_defaults.goomy_blob_params - goomy_blob.launch_goomy_blob( - plan, - prefunded_accounts, - all_el_contexts, - all_cl_contexts[0], - network_params.seconds_per_slot, - goomy_blob_params, - global_node_selectors, - ) - plan.print("Successfully launched goomy the blob spammer") # We need a way to do time.sleep # TODO add code that waits for CL genesis elif additional_service == "el_forkmon": @@ -696,6 +683,15 @@ def run(plan, args={}): args_with_right_defaults.spamoor_params, global_node_selectors, ) + elif additional_service == "spamoor_blob": + plan.print("Launching spamoor as blob spammer") + spamoor_blob.launch_spamoor_blob( + plan, + prefunded_accounts, + all_el_contexts, + args_with_right_defaults.spamoor_blob_params, + global_node_selectors, + ) else: fail("Invalid additional service %s" % (additional_service)) if launch_prometheus_grafana: diff --git a/network_params.yaml b/network_params.yaml index b0572c963..27b65b4ec 100644 --- a/network_params.yaml +++ b/network_params.yaml @@ -104,8 +104,8 @@ dora_params: image: "" tx_spammer_params: tx_spammer_extra_args: [] -goomy_blob_params: - goomy_blob_args: [] +spamoor_blob_params: + spamoor_extra_args: [] prometheus_params: storage_tsdb_retention_time: "1d" storage_tsdb_retention_size: "512MB" diff --git a/src/goomy_blob/goomy_blob.star b/src/goomy_blob/goomy_blob.star deleted file mode 100644 index 1c4016752..000000000 --- a/src/goomy_blob/goomy_blob.star +++ /dev/null @@ -1,67 +0,0 @@ -SERVICE_NAME = "goomy-blob-spammer" - -ENTRYPOINT_ARGS = ["/bin/sh", "-c"] - -# The min/max CPU/memory that goomy can use -MIN_CPU = 100 -MAX_CPU = 1000 -MIN_MEMORY = 20 -MAX_MEMORY = 300 - - -def launch_goomy_blob( - plan, - prefunded_addresses, - el_contexts, - cl_context, - seconds_per_slot, - goomy_blob_params, - global_node_selectors, -): - config = get_config( - prefunded_addresses, - el_contexts, - cl_context, - seconds_per_slot, - goomy_blob_params, - global_node_selectors, - ) - plan.add_service(SERVICE_NAME, config) - - -def get_config( - prefunded_addresses, - el_contexts, - cl_context, - seconds_per_slot, - goomy_blob_params, - node_selectors, -): - goomy_cli_args = [] - for index, client in enumerate(el_contexts): - goomy_cli_args.append( - "-h http://{0}:{1}".format( - client.ip_addr, - client.rpc_port_num, - ) - ) - - goomy_args = " ".join(goomy_blob_params.goomy_blob_args) - if goomy_args == "": - goomy_args = "combined -b 2 -t 2 --max-pending 3" - goomy_cli_args.append(goomy_args) - - cmd = "./blob-spammer -p {0} {1}".format( - prefunded_addresses[4].private_key, " ".join(goomy_cli_args) - ) - - return ServiceConfig( - image=goomy_blob_params.image, - entrypoint=ENTRYPOINT_ARGS, - cmd=[cmd], - min_cpu=MIN_CPU, - max_cpu=MAX_CPU, - min_memory=MIN_MEMORY, - max_memory=MAX_MEMORY, - node_selectors=node_selectors, - ) diff --git a/src/package_io/input_parser.star b/src/package_io/input_parser.star index e50fd932b..298b6ccbd 100644 --- a/src/package_io/input_parser.star +++ b/src/package_io/input_parser.star @@ -81,12 +81,12 @@ ATTR_TO_BE_SKIPPED_AT_ROOT = ( "assertoor_params", "prometheus_params", "grafana_params", - "goomy_blob_params", "tx_spammer_params", "custom_flood_params", "xatu_sentry_params", "port_publisher", "spamoor_params", + "spamoor_blob_params", ) @@ -110,7 +110,6 @@ def input_parser(plan, input_args): result["tx_spammer_params"] = get_default_tx_spammer_params() result["custom_flood_params"] = get_default_custom_flood_params() result["disable_peer_scoring"] = False - result["goomy_blob_params"] = get_default_goomy_blob_params() result["grafana_params"] = get_default_grafana_params() result["assertoor_params"] = get_default_assertoor_params() result["prometheus_params"] = get_default_prometheus_params() @@ -121,6 +120,7 @@ def input_parser(plan, input_args): result["global_node_selectors"] = {} result["port_publisher"] = get_port_publisher_params("default") result["spamoor_params"] = get_default_spamoor_params() + result["spamoor_blob_params"] = get_default_spamoor_blob_params() if constants.NETWORK_NAME.shadowfork in result["network_params"]["network"]: shadow_base = result["network_params"]["network"].split("-shadowfork")[0] @@ -164,10 +164,6 @@ def input_parser(plan, input_args): for sub_attr in input_args["custom_flood_params"]: sub_value = input_args["custom_flood_params"][sub_attr] result["custom_flood_params"][sub_attr] = sub_value - elif attr == "goomy_blob_params": - for sub_attr in input_args["goomy_blob_params"]: - sub_value = input_args["goomy_blob_params"][sub_attr] - result["goomy_blob_params"][sub_attr] = sub_value elif attr == "assertoor_params": for sub_attr in input_args["assertoor_params"]: sub_value = input_args["assertoor_params"][sub_attr] @@ -190,6 +186,10 @@ def input_parser(plan, input_args): for sub_attr in input_args["spamoor_params"]: sub_value = input_args["spamoor_params"][sub_attr] result["spamoor_params"][sub_attr] = sub_value + elif attr == "spamoor_blob_params": + for sub_attr in input_args["spamoor_blob_params"]: + sub_value = input_args["spamoor_blob_params"][sub_attr] + result["spamoor_blob_params"][sub_attr] = sub_value elif attr == "ethereum_genesis_generator_params": for sub_attr in input_args["ethereum_genesis_generator_params"]: sub_value = input_args["ethereum_genesis_generator_params"][sub_attr] @@ -403,10 +403,6 @@ def input_parser(plan, input_args): image=result["tx_spammer_params"]["image"], tx_spammer_extra_args=result["tx_spammer_params"]["tx_spammer_extra_args"], ), - goomy_blob_params=struct( - image=result["goomy_blob_params"]["image"], - goomy_blob_args=result["goomy_blob_params"]["goomy_blob_args"], - ), prometheus_params=struct( storage_tsdb_retention_time=result["prometheus_params"][ "storage_tsdb_retention_time" @@ -452,12 +448,21 @@ def input_parser(plan, input_args): ), spamoor_params=struct( image=result["spamoor_params"]["image"], - tx_type=result["spamoor_params"]["tx_type"], + scenario=result["spamoor_params"]["scenario"], throughput=result["spamoor_params"]["throughput"], max_pending=result["spamoor_params"]["max_pending"], max_wallets=result["spamoor_params"]["max_wallets"], spamoor_extra_args=result["spamoor_params"]["spamoor_extra_args"], ), + spamoor_blob_params=struct( + image=result["spamoor_blob_params"]["image"], + scenario=result["spamoor_blob_params"]["scenario"], + throughput=result["spamoor_blob_params"]["throughput"], + max_blobs=result["spamoor_blob_params"]["max_blobs"], + max_pending=result["spamoor_blob_params"]["max_pending"], + max_wallets=result["spamoor_blob_params"]["max_wallets"], + spamoor_extra_args=result["spamoor_blob_params"]["spamoor_extra_args"], + ), additional_services=result["additional_services"], wait_for_finalization=result["wait_for_finalization"], global_log_level=result["global_log_level"], @@ -1129,10 +1134,6 @@ def get_default_tx_spammer_params(): } -def get_default_goomy_blob_params(): - return {"image": "ethpandaops/goomy-blob:master", "goomy_blob_args": []} - - def get_default_assertoor_params(): return { "image": constants.DEFAULT_ASSERTOOR_IMAGE, @@ -1191,7 +1192,7 @@ def get_default_xatu_sentry_params(): def get_default_spamoor_params(): return { "image": "ethpandaops/spamoor:latest", - "tx_type": "eoatx", + "scenario": "eoatx", "throughput": 1000, "max_pending": 1000, "max_wallets": 500, @@ -1199,6 +1200,18 @@ def get_default_spamoor_params(): } +def get_default_spamoor_blob_params(): + return { + "image": "ethpandaops/spamoor:latest", + "scenario": "blob-combined", + "throughput": 3, + "max_blobs": 2, + "max_pending": 6, + "max_wallets": 29, + "spamoor_extra_args": [], + } + + def get_default_custom_flood_params(): # this is a simple script that increases the balance of the coinbase address at a cadence return {"interval_between_transactions": 1} @@ -1391,10 +1404,10 @@ def docker_cache_image_override(plan, result): "mev_params.mev_flood_image", "xatu_sentry_params.xatu_sentry_image", "tx_spammer_params.image", - "goomy_blob_params.image", "prometheus_params.image", "grafana_params.image", "spamoor_params.image", + "spamoor_blob_params.image", "ethereum_genesis_generator_params.image", ] diff --git a/src/package_io/sanity_check.star b/src/package_io/sanity_check.star index 2dcafff8d..ea574a97f 100644 --- a/src/package_io/sanity_check.star +++ b/src/package_io/sanity_check.star @@ -193,9 +193,6 @@ SUBCATEGORY_PARAMS = { "image", "tx_spammer_extra_args", ], - "goomy_blob_params": [ - "goomy_blob_args", - ], "prometheus_params": [ "min_cpu", "max_cpu", @@ -248,8 +245,17 @@ SUBCATEGORY_PARAMS = { ], "spamoor_params": [ "image", - "tx_type", + "scenario", + "throughput", + "max_pending", + "max_wallets", + "spamoor_extra_args", + ], + "spamoor_blob_params": [ + "image", + "scenario", "throughput", + "max_blobs", "max_pending", "max_wallets", "spamoor_extra_args", @@ -273,7 +279,6 @@ ADDITIONAL_SERVICES_PARAMS = [ "tx_spammer", "blob_spammer", "custom_flood", - "goomy_blob", "el_forkmon", "blockscout", "beacon_metrics_gazer", @@ -287,6 +292,7 @@ ADDITIONAL_SERVICES_PARAMS = [ "apache", "tracoor", "spamoor", + "spamoor_blob", ] ADDITIONAL_CATEGORY_PARAMS = { diff --git a/src/spamoor/spamoor.star b/src/spamoor/spamoor.star index 1f3dd2fc4..afe24b32e 100644 --- a/src/spamoor/spamoor.star +++ b/src/spamoor/spamoor.star @@ -31,16 +31,22 @@ def get_config( node_selectors, ): cmd = [ - "{}".format(spamoor_params.tx_type), + "{}".format(spamoor_params.scenario), "--privkey={}".format(prefunded_addresses[13].private_key), "--rpchost={}".format( ",".join([el_context.rpc_http_url for el_context in all_el_contexts]) ), - "--throughput={}".format(spamoor_params.throughput), - "--max-pending={}".format(spamoor_params.max_pending), - "--max-wallets={}".format(spamoor_params.max_wallets), ] + if spamoor_params.throughput != None: + cmd.append("--throughput={}".format(spamoor_params.throughput)) + + if spamoor_params.max_pending != None: + cmd.append("--max-pending={}".format(spamoor_params.max_pending)) + + if spamoor_params.max_wallets != None: + cmd.append("--max-wallets={}".format(spamoor_params.max_wallets)) + if len(spamoor_params.spamoor_extra_args) > 0: cmd.extend([param for param in spamoor_params.spamoor_extra_args]) diff --git a/src/spamoor_blob/spamoor_blob.star b/src/spamoor_blob/spamoor_blob.star new file mode 100644 index 000000000..a90ad9d15 --- /dev/null +++ b/src/spamoor_blob/spamoor_blob.star @@ -0,0 +1,64 @@ +shared_utils = import_module("../shared_utils/shared_utils.star") +SERVICE_NAME = "spamoor-blob" + +# The min/max CPU/memory that spamoor can use +MIN_CPU = 100 +MAX_CPU = 1000 +MIN_MEMORY = 20 +MAX_MEMORY = 300 + + +def launch_spamoor_blob( + plan, + prefunded_addresses, + all_el_contexts, + spamoor_params, + global_node_selectors, +): + config = get_config( + prefunded_addresses, + all_el_contexts, + spamoor_params, + global_node_selectors, + ) + plan.add_service(SERVICE_NAME, config) + + +def get_config( + prefunded_addresses, + all_el_contexts, + spamoor_params, + node_selectors, +): + cmd = [ + "{}".format(spamoor_params.scenario), + "--privkey={}".format(prefunded_addresses[4].private_key), + "--rpchost={}".format( + ",".join([el_context.rpc_http_url for el_context in all_el_contexts]) + ), + ] + + if spamoor_params.throughput != None: + cmd.append("--throughput={}".format(spamoor_params.throughput)) + + if spamoor_params.max_blobs != None: + cmd.append("--sidecars={}".format(spamoor_params.max_blobs)) + + if spamoor_params.max_pending != None: + cmd.append("--max-pending={}".format(spamoor_params.max_pending)) + + if spamoor_params.max_wallets != None: + cmd.append("--max-wallets={}".format(spamoor_params.max_wallets)) + + if len(spamoor_params.spamoor_extra_args) > 0: + cmd.extend([param for param in spamoor_params.spamoor_extra_args]) + + return ServiceConfig( + image=spamoor_params.image, + cmd=cmd, + min_cpu=MIN_CPU, + max_cpu=MAX_CPU, + min_memory=MIN_MEMORY, + max_memory=MAX_MEMORY, + node_selectors=node_selectors, + )