Skip to content

Commit

Permalink
feat: Add configurable spamming frequency to custom flood (#283)
Browse files Browse the repository at this point in the history
The PR aims to make custom flood more usable and configuration more
consistent:
* Add `delay` parameter to custom flood to control frequency of
transactions
* Remove `launch_custom_flood` parameter
* Add custom_flood to `additional_services`
  • Loading branch information
piwonskp committed Oct 16, 2023
1 parent b0ee145 commit f1e18ca
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 54 deletions.
10 changes: 9 additions & 1 deletion .circleci/tests/mev.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
{
"mev_type": "full",
"additional_services": [
"tx_spammer",
"blob_spammer",
"custom_flood",
"el_forkmon",
"beacon_metrics_gazer",
"dora",
"prometheus_grafana"
],
"mev_params": {
"launch_custom_flood": true,
"mev_relay_image": "flashbots/mev-boost-relay:0.27"
},
"network_params": {
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ To configure the package behaviour, you can modify your `network_params.json` fi
"additional_services": [
"tx_spammer",
"blob_spammer",
"goomy_blob"
"custom_flood",
"goomy_blob",
"el_forkmon",
"beacon_metrics_gazer",
"dora",
Expand Down Expand Up @@ -307,9 +308,10 @@ To configure the package behaviour, you can modify your `network_params.json` fi
"mev_flood_extra_args": [],
// Number of seconds between bundles for mev-flood
"mev_flood_seconds_per_bundle": 15,
// A custom flood script that increases the balance of the coinbase addresss leading to more reliable
// payload delivery
"launch_custom_flood": false
// Optional parameters to send to the custom_flood script that sends reliable payloads
"custom_flood_params": {
"interval_between_transactions": 1
}
},
// A list of locators for grafana dashboards to be loaded be the grafana service
"grafana_additional_dashboards": []
Expand Down
1 change: 0 additions & 1 deletion examples/capella-mev.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
},
"mev_params": {
"mev_flood_seconds_per_bundle": 12,
"launch_custom_flood": false,
"mev_flood_extra_args": [ "--txsPerBundle=300" ],
"mev_flood_image": "flashbots/mev-flood:0.0.9",
"mev_relay_image": "flashbots/mev-boost-relay:0.27.0"
Expand Down
15 changes: 8 additions & 7 deletions main.star
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,6 @@ def run(plan, 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
Expand Down Expand Up @@ -313,6 +306,14 @@ def run(plan, args={}):
elif additional_service == "prometheus_grafana":
# Allow prometheus to be launched last so is able to collect metrics from other services
launch_prometheus_grafana = True
elif additional_service == "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,
args_with_right_defaults.custom_flood_params,
)
else:
fail("Invalid additional service %s" % (additional_service))
if launch_prometheus_grafana:
Expand Down
3 changes: 1 addition & 2 deletions network_params.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@
"mev_builder_extra_args": [],
"mev_flood_image": "flashbots/mev-flood",
"mev_flood_extra_args": [],
"mev_flood_seconds_per_bundle": 15,
"launch_custom_flood": false
"mev_flood_seconds_per_bundle": 15
},
"grafana_additional_dashboards": []
}
12 changes: 9 additions & 3 deletions src/mev_custom_flood/mev_custom_flood_launcher.star
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ PYTHON_IMAGE = "python:3.11-alpine"
CUSTOM_FLOOD_SERVICE_NAME = "mev-custom-flood"


def spam_in_background(plan, sender_key, receiver_key, el_uri):
def spam_in_background(plan, sender_key, receiver_key, el_uri, params):
sender_script = plan.upload_files("./sender.py")

plan.add_service(
Expand All @@ -21,12 +21,18 @@ def spam_in_background(plan, sender_key, receiver_key, el_uri):

plan.exec(
service_name=CUSTOM_FLOOD_SERVICE_NAME,
recipe=ExecRecipe(["pip", "install", "web3"]),
recipe=ExecRecipe(["pip", "install", "web3", "click"]),
)

plan.exec(
service_name=CUSTOM_FLOOD_SERVICE_NAME,
recipe=ExecRecipe(
["/bin/sh", "-c", "nohup python /tmp/sender.py > /dev/null 2>&1 &"]
[
"/bin/sh",
"-c",
"nohup python /tmp/sender.py --interval_between_transactions {} > /dev/null 2>&1 &".format(
params.interval_between_transactions
),
]
),
)
68 changes: 36 additions & 32 deletions src/mev_custom_flood/sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
this is s a really dumb script that sends tokens to the receiver from the sender every 3 seconds
this is being used as of 2023-09-06 to guarantee that payloads are delivered
"""
from functools import partial

from web3 import Web3
from web3.middleware import construct_sign_and_send_raw_middleware
import os
import time
import logging
import click


VALUE_TO_SEND = 0x9184

Expand All @@ -17,49 +20,50 @@
datefmt='%H:%M:%S',
level=logging.DEBUG)

# this is the last prefunded address
SENDER = os.getenv("SENDER_PRIVATE_KEY", "17fdf89989597e8bcac6cdfcc001b6241c64cece2c358ffc818b72ca70f5e1ce")
# this is the first prefunded address
RECEIVER = os.getenv("RECEIVER_PUBLIC_KEY", "0x878705ba3f8Bc32FCf7F4CAa1A35E72AF65CF766")
EL_URI = os.getenv("EL_RPC_URI", 'http://0.0.0.0:53913')

def flood():
# this is the last prefunded address
sender = os.getenv("SENDER_PRIVATE_KEY", "17fdf89989597e8bcac6cdfcc001b6241c64cece2c358ffc818b72ca70f5e1ce")
# this is the first prefunded address
receiver = os.getenv("RECEIVER_PUBLIC_KEY", "0x878705ba3f8Bc32FCf7F4CAa1A35E72AF65CF766")
el_uri = os.getenv("EL_RPC_URI", 'http://0.0.0.0:53913')

logging.info(f"Using sender {sender} receiver {receiver} and el_uri {el_uri}")

w3 = Web3(Web3.HTTPProvider(el_uri))

sender_account = w3.eth.account.from_key(sender)

while True:
time.sleep(3)
def send_transaction():
# Setting w3 as constant causes recursion exceeded error after ~500 transactions
# Thus it's created everytime a transaction is sent
w3 = Web3(Web3.HTTPProvider(EL_URI))

w3.middleware_onion.add(construct_sign_and_send_raw_middleware(sender_account))
sender_account = w3.eth.account.from_key(SENDER)
w3.middleware_onion.add(construct_sign_and_send_raw_middleware(sender_account))

transaction = {
"from": sender_account.address,
"value": VALUE_TO_SEND,
"to": receiver,
"data": "0xabcd",
"gasPrice": w3.eth.gas_price,
"nonce": w3.eth.get_transaction_count(sender_account.address)
}
transaction = {
"from": sender_account.address,
"value": VALUE_TO_SEND,
"to": RECEIVER,
"data": "0xabcd",
"gasPrice": w3.eth.gas_price,
"nonce": w3.eth.get_transaction_count(sender_account.address)
}

estimated_gas = w3.eth.estimate_gas(transaction)
transaction["gas"] = estimated_gas

transaction["gas"] = estimated_gas
tx_hash = w3.eth.send_transaction(transaction)

tx_hash = w3.eth.send_transaction(transaction)
tx = w3.eth.get_transaction(tx_hash)
logging.info(tx_hash.hex())
assert tx["from"] == sender_account.address

tx = w3.eth.get_transaction(tx_hash)
logging.info(tx_hash.hex())
assert tx["from"] == sender_account.address
def delayed_send(interval_between_transactions):
send_transaction()
time.sleep(interval_between_transactions)


def run_infinitely():
@click.command()
@click.option('--interval_between_transactions', default=0.5, help='Interval between successive transaction sends (in seconds). The value may be an integer or decimal')
def run_infinitely(interval_between_transactions):
logging.info(f"Using sender {SENDER} receiver {RECEIVER} and el_uri {EL_URI}")
spam = send_transaction if interval_between_transactions == 0 else partial(delayed_send, interval_between_transactions)
while True:
try:
flood()
spam()
except Exception as e:
print("e")
print("restarting flood as previous one failed")
Expand Down
20 changes: 16 additions & 4 deletions src/package_io/parse_input.star
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ ATTR_TO_BE_SKIPPED_AT_ROOT = (
"mev_params",
"goomy_blob_params",
"tx_spammer_params",
"custom_flood_params",
)

package_io_constants = import_module("../package_io/constants.star")
Expand All @@ -65,6 +66,7 @@ def parse_input(plan, input_args):
result["additional_services"] = DEFAULT_ADDITIONAL_SERVICES
result["grafana_additional_dashboards"] = []
result["tx_spammer_params"] = get_default_tx_spammer_params()
result["custom_flood_params"] = get_default_custom_flood_params()

for attr in input_args:
value = input_args[attr]
Expand All @@ -80,6 +82,10 @@ def parse_input(plan, input_args):
for sub_attr in input_args["tx_spammer_params"]:
sub_value = input_args["tx_spammer_params"][sub_attr]
result["tx_spammer_params"][sub_attr] = sub_value
elif attr == "custom_flood_params":
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

if result.get("mev_type") in ("mock", "full"):
result = enrich_mev_extra_params(
Expand All @@ -101,7 +107,6 @@ def parse_input(plan, input_args):
)

result["goomy_blob_params"] = get_default_goomy_blob_params()

return struct(
participants=[
struct(
Expand Down Expand Up @@ -168,14 +173,18 @@ 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"],
),
goomy_blob_params=struct(
goomy_blob_args=result["goomy_blob_params"]["goomy_blob_args"],
),
custom_flood_params=struct(
interval_between_transactions=result["custom_flood_params"][
"interval_between_transactions"
],
),
launch_additional_services=result["launch_additional_services"],
additional_services=result["additional_services"],
wait_for_finalization=result["wait_for_finalization"],
Expand Down Expand Up @@ -399,8 +408,6 @@ def get_default_mev_params():
"mev_flood_image": "flashbots/mev-flood",
"mev_flood_extra_args": [],
"mev_flood_seconds_per_bundle": 15,
# this is a simple script that increases the balance of the coinbase address at a cadence
"launch_custom_flood": False,
}


Expand All @@ -412,6 +419,11 @@ def get_default_goomy_blob_params():
return {"goomy_blob_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}


# 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

0 comments on commit f1e18ca

Please sign in to comment.