diff --git a/.github/tests/mev-helix.yaml b/.github/tests/mev-helix.yaml
new file mode 100644
index 000000000..e749f7386
--- /dev/null
+++ b/.github/tests/mev-helix.yaml
@@ -0,0 +1,45 @@
+participants:
+ - el_type: geth
+ el_image: ethpandaops/geth:master
+ cl_type: lighthouse
+ cl_image: ethpandaops/lighthouse:unstable
+ vc_image: ethpandaops/lighthouse:unstable
+ supernode: true
+ count: 2
+ - el_type: nethermind
+ el_image: ethpandaops/nethermind:master
+ cl_type: prysm
+ cl_image: ethpandaops/prysm-beacon-chain:develop
+ supernode: true
+
+additional_services:
+ - dora
+ - spamoor
+
+mev_type: helix
+mev_params:
+ mev_relay_image: ghcr.io/gattaca-com/helix-relay:main
+ mev_builder_image: ethpandaops/reth-rbuilder:develop
+ mev_boost_image: ethpandaops/mev-boost:develop
+ mev_builder_cl_image: ethpandaops/lighthouse:unstable
+ mev_builder_subsidy: 1
+
+spamoor_params:
+ spammers:
+ - name: "Blob Spammer (Kurtosis Package)"
+ description: "3 type-4 blob transactions per slot with 1-2 sidecars each, gas/blobgas limit 20 gwei"
+ scenario: "blobs"
+ config:
+ throughput: 10
+ - name: "ERC txs"
+ description: "ERC txs"
+ scenario: "erctx"
+ config:
+ throughput: 50
+ max_pending: 400
+
+network_params:
+ min_validator_withdrawability_delay: 1
+ shard_committee_period: 1
+ churn_limit_quotient: 16
+ prefunded_accounts: '{"0xb9e79d19f651a941757b35830232e7efc77e1c79": {"balance": "100000ETH"}}'
diff --git a/README.md b/README.md
index 5b4f5a24c..084459792 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,13 @@ Specifically, this [package][package-reference] will:
Optional features (enabled via flags or parameter files at runtime):
- Block until the Beacon nodes finalize an epoch (i.e. finalized_epoch > 0)
-- Spin up & configure parameters for the infrastructure behind Flashbot's implementation of PBS using `mev-boost`, in either `full` or `mock` mode. [More details on PBS implementation](./README.md#proposer-builder-separation-pbs-implementation-via-flashbots-mev-boost-protocol).
+- Spin up & configure parameters for the infrastructure behind PBS (Proposer-Builder Separation) using `mev-boost`, with support for multiple relay implementations:
+ - `flashbots` - Full Flashbots MEV infrastructure
+ - `helix` - High-performance [Helix relay](https://github.com/gattaca-com/helix) with TimescaleDB backend
+ - `mev-rs` - Alternative relay implementation
+ - `commit-boost` - Commit-boost based infrastructure
+ - `mock` - Mock builder for testing
+ - [More details on PBS implementation](./README.md#proposer-builder-separation-pbs-emulation).
- Spin up & connect the network to a [beacon metrics gazer service](https://github.com/dapplion/beacon-metrics-gazer) to collect network-wide participation metrics.
- Spin up and connect a [JSON RPC Snooper](https://github.com/ethDreamer/json_rpc_snoop) to the network log responses & requests between the EL engine API and the CL client.
- Specify extra parameters to be passed in for any of the: CL client Beacon, and CL client validator, and/or EL client containers
@@ -1098,12 +1104,14 @@ mempool_bridge_params:
# Default: "30s"
retry_interval: "30s"
-# Supports four values
+# Supports six values
# Default: "null" - no mev boost, mev builder, mev flood or relays are spun up
# "mock" - mock-builder & mev-boost are 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/)
# "commit-boost" - mev-boost, relays and builder are all spun up, powered by [commit-boost](https://github.com/Commit-Boost/commit-boost-client)
+# "helix" - helix relay, flashbots builder and mev-boost are spun up, powered by [helix](https://github.com/gattaca-com/helix)
+# Note: Helix uses TimescaleDB (PostgreSQL with time-series extension) for data storage
# We have seen instances of multibuilder instances failing to start mev-relay-api with non zero epochs
mev_type: null
@@ -1478,6 +1486,40 @@ network_params:
+
+ A 3-node Ethereum network with Helix relay for MEV-boost infrastructure
+
+```yaml
+participants:
+ - el_type: geth
+ el_image: ethpandaops/geth:master
+ cl_type: lighthouse
+ cl_image: ethpandaops/lighthouse:unstable
+ count: 2
+ - el_type: nethermind
+ el_image: ethpandaops/nethermind:master
+ cl_type: prysm
+ cl_image: ethpandaops/prysm-beacon-chain:develop
+
+mev_type: helix
+mev_params:
+ mev_relay_image: ghcr.io/gattaca-com/helix-relay:main
+ mev_builder_image: ethpandaops/reth-rbuilder:develop
+ mev_boost_image: ethpandaops/mev-boost:develop
+ mev_builder_cl_image: ethpandaops/lighthouse:unstable
+ mev_builder_subsidy: 1
+
+additional_services:
+ - dora
+ - spamoor
+
+network_params:
+ min_validator_withdrawability_delay: 1
+ shard_committee_period: 1
+```
+
+
+
A 2-node geth/lighthouse network with optional services (Grafana, Prometheus, tx_fuzz, EngineAPI snooper)
@@ -1605,6 +1647,14 @@ Starting your network up with `"mev_type": "flashbots"` will instantiate and con
4. `mev-relay-housekeeper` - Updates known validators, proposer duties, and more in the background. Only a single instance of this should run.
5. `mev-boost` - open-source middleware instantiated for each EL/Cl pair in the network, including the builder
+The package also supports other MEV implementations:
+
+- `"mev_type": "helix"` - Uses the high-performance [Helix relay](https://github.com/gattaca-com/helix) with TimescaleDB backend for data storage
+- `"mev_type": "mev-rs"` - Alternative relay implementation powered by [mev-rs](https://github.com/ralexstokes/mev-rs/)
+- `"mev_type": "commit-boost"` - Infrastructure powered by [commit-boost](https://github.com/Commit-Boost/commit-boost-client)
+
+Each implementation provides different features and performance characteristics suitable for various testing and development scenarios.
+
Caveats when using "mev_type": "flashbots"
diff --git a/main.star b/main.star
index c5272961e..2a6359808 100644
--- a/main.star
+++ b/main.star
@@ -49,6 +49,7 @@ flashbots_mev_boost = import_module(
flashbots_mev_relay = import_module(
"./src/mev/flashbots/mev_relay/mev_relay_launcher.star"
)
+helix_relay = import_module("./src/mev/helix/helix_relay_launcher.star")
mock_mev = import_module("./src/mev/flashbots/mock_mev/mock_mev_launcher.star")
mev_custom_flood = import_module(
"./src/mev/flashbots/mev_custom_flood/mev_custom_flood_launcher.star"
@@ -212,11 +213,12 @@ def run(plan, args={}):
elif (
args_with_right_defaults.mev_type == constants.FLASHBOTS_MEV_TYPE
or args_with_right_defaults.mev_type == constants.COMMIT_BOOST_MEV_TYPE
+ or args_with_right_defaults.mev_type == constants.HELIX_MEV_TYPE
):
plan.print("Generating flashbots builder config file")
flashbots_builder_config_file = flashbots_mev_rbuilder.new_builder_config(
plan,
- constants.FLASHBOTS_MEV_TYPE,
+ args_with_right_defaults.mev_type,
network_params,
constants.VALIDATING_REWARDS_ACCOUNT,
network_params.preregistered_validator_keys_mnemonic,
@@ -347,6 +349,7 @@ def run(plan, args={}):
args_with_right_defaults.mev_type == constants.FLASHBOTS_MEV_TYPE
or args_with_right_defaults.mev_type == constants.MEV_RS_MEV_TYPE
or args_with_right_defaults.mev_type == constants.COMMIT_BOOST_MEV_TYPE
+ or args_with_right_defaults.mev_type == constants.HELIX_MEV_TYPE
):
blocksim_uri = "http://{0}:{1}".format(
all_el_contexts[-1].ip_addr, all_el_contexts[-1].rpc_port_num
@@ -385,6 +388,22 @@ def run(plan, args={}):
global_node_selectors,
global_tolerations,
)
+ elif args_with_right_defaults.mev_type == constants.HELIX_MEV_TYPE:
+ endpoint = helix_relay.launch_helix_relay(
+ plan,
+ network_params,
+ mev_params,
+ beacon_uri,
+ genesis_validators_root,
+ final_genesis_timestamp,
+ blocksim_uri,
+ persistent,
+ args_with_right_defaults.port_publisher,
+ num_participants,
+ global_node_selectors,
+ global_tolerations,
+ el_cl_data_files_artifact_uuid,
+ )
else:
fail("Invalid MEV type")
@@ -407,6 +426,7 @@ def run(plan, args={}):
if (
args_with_right_defaults.mev_type == constants.FLASHBOTS_MEV_TYPE
or args_with_right_defaults.mev_type == constants.MOCK_MEV_TYPE
+ or args_with_right_defaults.mev_type == constants.HELIX_MEV_TYPE
):
mev_boost_launcher = flashbots_mev_boost.new_mev_boost_launcher(
MEV_BOOST_SHOULD_CHECK_RELAY,
diff --git a/network_params.yaml b/network_params.yaml
index ab7d264f8..58921e7f2 100644
--- a/network_params.yaml
+++ b/network_params.yaml
@@ -183,6 +183,7 @@ ethereum_metrics_exporter_enabled: false
parallel_keystore_generation: false
disable_peer_scoring: false
persistent: false
+# Supports: null, mock, flashbots, mev-rs, commit-boost, helix
mev_type: null
mev_params:
mev_relay_image: ethpandaops/mev-boost-relay:main
diff --git a/src/el/reth/reth_launcher.star b/src/el/reth/reth_launcher.star
index 1bba190bc..8de9b3ade 100644
--- a/src/el/reth/reth_launcher.star
+++ b/src/el/reth/reth_launcher.star
@@ -118,6 +118,7 @@ def get_config(
if (
launcher.builder_type == constants.FLASHBOTS_MEV_TYPE
or launcher.builder_type == constants.COMMIT_BOOST_MEV_TYPE
+ or launcher.builder_type == constants.HELIX_MEV_TYPE
):
additional_public_port_assignments[
constants.RBUILDER_PORT_ID
@@ -152,6 +153,7 @@ def get_config(
if (
launcher.builder_type == constants.FLASHBOTS_MEV_TYPE
or launcher.builder_type == constants.COMMIT_BOOST_MEV_TYPE
+ or launcher.builder_type == constants.HELIX_MEV_TYPE
):
used_port_assignments[constants.RBUILDER_PORT_ID] = RBUILDER_PORT_NUM
used_port_assignments[
@@ -183,6 +185,7 @@ def get_config(
",flashbots"
if launcher.builder_type == constants.FLASHBOTS_MEV_TYPE
or launcher.builder_type == constants.COMMIT_BOOST_MEV_TYPE
+ or launcher.builder_type == constants.HELIX_MEV_TYPE
else ""
),
"--ws",
@@ -273,6 +276,7 @@ def get_config(
elif (
launcher.builder_type == constants.FLASHBOTS_MEV_TYPE
or launcher.builder_type == constants.COMMIT_BOOST_MEV_TYPE
+ or launcher.builder_type == constants.HELIX_MEV_TYPE
):
image = launcher.mev_params.mev_builder_image
cl_client_name = service_name.split("-")[4]
diff --git a/src/mev/flashbots/mev_builder/mev_builder_launcher.star b/src/mev/flashbots/mev_builder/mev_builder_launcher.star
index 57779699c..49c35c2fc 100644
--- a/src/mev/flashbots/mev_builder/mev_builder_launcher.star
+++ b/src/mev/flashbots/mev_builder/mev_builder_launcher.star
@@ -3,6 +3,7 @@ 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")
flashbots_relay = import_module("../mev_relay/mev_relay_launcher.star")
+helix_relay = import_module("../../helix/helix_relay_launcher.star")
lighthouse = import_module("../../../cl/lighthouse/lighthouse_launcher.star")
# MEV Builder flags
@@ -16,7 +17,7 @@ MEV_FILE_PATH_ON_CONTAINER = (
def new_builder_config(
plan,
- service_name,
+ mev_type,
network_params,
fee_recipient,
mnemonic,
@@ -36,6 +37,7 @@ def new_builder_config(
mev_params.mev_builder_extra_data,
num_of_participants,
mev_params.mev_builder_subsidy,
+ mev_type,
)
flashbots_builder_config_template = read_file(
static_files.FLASHBOTS_RBUILDER_CONFIG_FILEPATH
@@ -70,7 +72,18 @@ def new_builder_config_template_data(
extra_data,
num_of_participants,
subsidy,
+ mev_type,
):
+ # Determine relay service name and port based on MEV type
+ if mev_type == constants.HELIX_MEV_TYPE:
+ relay_service = "helix-relay"
+ relay_port = helix_relay.HELIX_RELAY_ENDPOINT_PORT
+ relay_name = "helix"
+ else:
+ relay_service = "mev-relay-api"
+ relay_port = flashbots_relay.MEV_RELAY_ENDPOINT_PORT
+ relay_name = "flashbots"
+
return {
"Network": network_params.network
if network_params.network in constants.PUBLIC_NETWORKS
@@ -83,8 +96,9 @@ def new_builder_config_template_data(
lighthouse.BEACON_HTTP_PORT_NUM,
),
"GenesisForkVersion": constants.GENESIS_FORK_VERSION,
- "Relay": "mev-relay-api",
- "RelayPort": flashbots_relay.MEV_RELAY_ENDPOINT_PORT,
+ "Relay": relay_service,
+ "RelayPort": relay_port,
+ "RelayName": relay_name,
"PublicKey": pubkey,
"SecretKey": secret,
"Mnemonic": mnemonic,
diff --git a/src/mev/helix/helix_relay_launcher.star b/src/mev/helix/helix_relay_launcher.star
new file mode 100644
index 000000000..c4454a56e
--- /dev/null
+++ b/src/mev/helix/helix_relay_launcher.star
@@ -0,0 +1,182 @@
+postgres_module = import_module("github.com/kurtosis-tech/postgres-package/main.star")
+constants = import_module("../../package_io/constants.star")
+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")
+
+HELIX_RELAY_NAME = "helix-relay"
+
+HTTP_PORT_ID = "http"
+ENDPOINT_PORT_ID = "endpoint"
+
+HELIX_RELAY_CONFIG_FILENAME = "config.yaml"
+HELIX_RELAY_MOUNT_DIRPATH_ON_SERVICE = "/config/"
+HELIX_RELAY_FILES_ARTIFACT_NAME = "helix-relay-config"
+
+HELIX_RELAY_ENDPOINT_PORT = 4040
+HELIX_RELAY_WEBSITE_PORT = 9060
+
+USED_PORTS = {
+ ENDPOINT_PORT_ID: shared_utils.new_port_spec(
+ HELIX_RELAY_ENDPOINT_PORT,
+ shared_utils.TCP_PROTOCOL,
+ shared_utils.HTTP_APPLICATION_PROTOCOL,
+ ),
+ HTTP_PORT_ID: shared_utils.new_port_spec(
+ HELIX_RELAY_WEBSITE_PORT,
+ shared_utils.TCP_PROTOCOL,
+ shared_utils.HTTP_APPLICATION_PROTOCOL,
+ ),
+}
+
+# The min/max CPU/memory that mev-relay can use
+RELAY_MIN_CPU = 500
+RELAY_MAX_CPU = 3000
+RELAY_MIN_MEMORY = 256
+RELAY_MAX_MEMORY = 4096
+
+# The min/max CPU/memory that postgres can use
+POSTGRES_MIN_CPU = 10
+POSTGRES_MAX_CPU = 1000
+POSTGRES_MIN_MEMORY = 32
+POSTGRES_MAX_MEMORY = 1024
+
+
+def launch_helix_relay(
+ plan,
+ network_params,
+ mev_params,
+ beacon_uris,
+ genesis_validators_root,
+ genesis_timestamp,
+ blocksim_uri,
+ persistent,
+ port_publisher,
+ index,
+ global_node_selectors,
+ global_tolerations,
+ el_cl_genesis_data,
+):
+ tolerations = shared_utils.get_tolerations(global_tolerations=global_tolerations)
+ public_ports = {}
+ endpoint_public_port = shared_utils.get_mev_public_port(
+ port_publisher,
+ ENDPOINT_PORT_ID,
+ index,
+ 0,
+ )
+ public_ports.update(endpoint_public_port)
+ website_public_port = shared_utils.get_mev_public_port(
+ port_publisher,
+ HTTP_PORT_ID,
+ index,
+ 1,
+ )
+ public_ports.update(website_public_port)
+
+ node_selectors = global_node_selectors
+
+ postgres = postgres_module.run(
+ plan,
+ password="postgres",
+ user="postgres",
+ database="postgres",
+ service_name="helix-relay-postgres",
+ image="timescale/timescaledb:latest-pg15",
+ persistent=persistent,
+ launch_adminer=mev_params.launch_adminer,
+ min_cpu=POSTGRES_MIN_CPU,
+ max_cpu=POSTGRES_MAX_CPU,
+ min_memory=POSTGRES_MIN_MEMORY,
+ max_memory=POSTGRES_MAX_MEMORY,
+ node_selectors=node_selectors,
+ tolerations=tolerations,
+ )
+
+ # Generate configuration file using template
+ helix_template_data = new_helix_relay_config_template_data(
+ network_params,
+ genesis_timestamp,
+ blocksim_uri,
+ beacon_uris,
+ genesis_validators_root,
+ postgres,
+ )
+
+ # Read the helix config template
+ helix_config_template = read_file(static_files.HELIX_RELAY_CONFIG_FILEPATH)
+ template_and_data = shared_utils.new_template_and_data(
+ helix_config_template, helix_template_data
+ )
+
+ # Prepare template data for rendering
+ template_and_data_by_rel_dest_filepath = {}
+ template_and_data_by_rel_dest_filepath[
+ HELIX_RELAY_CONFIG_FILENAME
+ ] = template_and_data
+
+ # Render the configuration file
+ config_files_artifact_name = plan.render_templates(
+ template_and_data_by_rel_dest_filepath, HELIX_RELAY_FILES_ARTIFACT_NAME
+ )
+
+ # Path where config file will be mounted in container
+ config_file_path = shared_utils.path_join(
+ HELIX_RELAY_MOUNT_DIRPATH_ON_SERVICE, HELIX_RELAY_CONFIG_FILENAME
+ )
+
+ env_vars = {
+ "RELAY_KEY": constants.DEFAULT_MEV_SECRET_KEY,
+ }
+
+ endpoint = plan.add_service(
+ name=HELIX_RELAY_NAME,
+ config=ServiceConfig(
+ image=mev_params.mev_relay_image,
+ cmd=["--config", config_file_path],
+ files={
+ HELIX_RELAY_MOUNT_DIRPATH_ON_SERVICE: config_files_artifact_name,
+ constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS: el_cl_genesis_data,
+ },
+ ports=USED_PORTS,
+ public_ports=public_ports,
+ env_vars=env_vars | mev_params.mev_relay_api_extra_env_vars,
+ min_cpu=RELAY_MIN_CPU,
+ max_cpu=RELAY_MAX_CPU,
+ min_memory=RELAY_MIN_MEMORY,
+ max_memory=RELAY_MAX_MEMORY,
+ node_selectors=node_selectors,
+ tolerations=tolerations,
+ ),
+ )
+
+ return "http://{0}@{1}:{2}".format(
+ constants.DEFAULT_MEV_PUBKEY, endpoint.ip_address, HELIX_RELAY_ENDPOINT_PORT
+ )
+
+
+def new_helix_relay_config_template_data(
+ network_params,
+ genesis_timestamp,
+ blocksim_uri,
+ beacon_uris,
+ genesis_validators_root,
+ postgres,
+):
+ return {
+ "NETWORK_NAME": network_params.network,
+ "GENESIS_TIME": genesis_timestamp,
+ "BLOCKSIM_URI": blocksim_uri,
+ "BEACON_URI": beacon_uris,
+ "GENESIS_VALIDATORS_ROOT": genesis_validators_root,
+ "POSTGRES_HOST_NAME": postgres.service.name,
+ "POSTGRES_PORT": 5432,
+ "POSTGRES_DB": "postgres",
+ "POSTGRES_USER": "postgres",
+ "POSTGRES_PASS": "postgres",
+ "HELIX_RELAY_ENDPOINT_PORT": HELIX_RELAY_ENDPOINT_PORT,
+ "HELIX_RELAY_WEBSITE_PORT": HELIX_RELAY_WEBSITE_PORT,
+ "HELIX_RELAY_ENDPOINT_URL": "helix-relay:{}".format(HELIX_RELAY_ENDPOINT_PORT),
+ "HELIX_RELAY_PUBKEY": constants.DEFAULT_MEV_PUBKEY,
+ "GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER": constants.GENESIS_DATA_MOUNTPOINT_ON_CLIENTS,
+ }
diff --git a/src/package_io/constants.star b/src/package_io/constants.star
index accd1498d..0671c7f0d 100644
--- a/src/package_io/constants.star
+++ b/src/package_io/constants.star
@@ -92,6 +92,7 @@ MOCK_MEV_TYPE = "mock"
FLASHBOTS_MEV_TYPE = "flashbots"
MEV_RS_MEV_TYPE = "mev-rs"
COMMIT_BOOST_MEV_TYPE = "commit-boost"
+HELIX_MEV_TYPE = "helix"
DEFAULT_DORA_IMAGE = "ethpandaops/dora:latest"
DEFAULT_CHECKPOINTZ_IMAGE = "ethpandaops/checkpointz:latest"
DEFAULT_SPAMOOR_IMAGE = "ethpandaops/spamoor:latest"
@@ -109,6 +110,7 @@ DEFAULT_MEV_RS_IMAGE = "ethpandaops/mev-rs:main"
DEFAULT_MEV_RS_IMAGE_MINIMAL = "ethpandaops/mev-rs:main-minimal"
DEFAULT_COMMIT_BOOST_MEV_BOOST_IMAGE = "ghcr.io/commit-boost/pbs:latest"
DEFAULT_MOCK_MEV_IMAGE = "ethpandaops/rustic-builder:main"
+DEFAULT_HELIX_RELAY_IMAGE = "ghcr.io/gattaca-com/helix-relay:main"
DEFAULT_MEV_PUBKEY = "0xa55c1285d84ba83a5ad26420cd5ad3091e49c55a813eee651cd467db38a8c8e63192f47955e9376f6b42f6d190571cb5"
DEFAULT_MEV_SECRET_KEY = (
"0x607a11b45a7219cc61a3d9c5fd08c7eebd602a6a19a977f8d3771d5711a550f2"
diff --git a/src/package_io/input_parser.star b/src/package_io/input_parser.star
index 4a9bdc02d..cf27f0f7b 100644
--- a/src/package_io/input_parser.star
+++ b/src/package_io/input_parser.star
@@ -213,6 +213,7 @@ def input_parser(plan, input_args):
constants.FLASHBOTS_MEV_TYPE,
constants.MEV_RS_MEV_TYPE,
constants.COMMIT_BOOST_MEV_TYPE,
+ constants.HELIX_MEV_TYPE,
):
result = enrich_mev_extra_params(
result,
@@ -224,7 +225,7 @@ def input_parser(plan, input_args):
pass
else:
fail(
- "Unsupported MEV type: {0}, please use 'mock', 'flashbots', 'mev-rs' or 'commit-boost' type".format(
+ "Unsupported MEV type: {0}, please use 'mock', 'flashbots', 'mev-rs', 'commit-boost' or 'helix' type".format(
result.get("mev_type")
)
)
@@ -1551,6 +1552,13 @@ def get_default_mev_params(mev_type, preset):
mev_builder_image = constants.DEFAULT_MOCK_MEV_IMAGE
mev_boost_image = constants.DEFAULT_FLASHBOTS_MEV_BOOST_IMAGE
+ if mev_type == constants.HELIX_MEV_TYPE:
+ mev_relay_image = constants.DEFAULT_HELIX_RELAY_IMAGE
+ mev_builder_image = constants.DEFAULT_FLASHBOTS_BUILDER_IMAGE
+ mev_boost_image = constants.DEFAULT_FLASHBOTS_MEV_BOOST_IMAGE
+ mev_builder_cl_image = DEFAULT_CL_IMAGES[constants.CL_TYPE.lighthouse]
+ mev_builder_extra_data = "0x48656C6978" # "Helix" in hex
+
return {
"mev_relay_image": mev_relay_image,
"mev_builder_image": mev_builder_image,
@@ -1861,6 +1869,7 @@ def enrich_mev_extra_params(parsed_arguments_dict, mev_prefix, mev_port, mev_typ
if (
mev_type == constants.FLASHBOTS_MEV_TYPE
or mev_type == constants.COMMIT_BOOST_MEV_TYPE
+ or mev_type == constants.HELIX_MEV_TYPE
):
mev_participant = default_participant()
mev_participant["el_type"] = "reth-builder"
diff --git a/src/static_files/static_files.star b/src/static_files/static_files.star
index 1b4372532..00a9ef3ff 100644
--- a/src/static_files/static_files.star
+++ b/src/static_files/static_files.star
@@ -134,3 +134,4 @@ COMMIT_BOOST_CONFIG_FILEPATH = (
MEMPOOL_BRIDGE_CONFIG_TEMPLATE_FILEPATH = (
STATIC_FILES_DIRPATH + "/mempool-bridge-config/config.yaml.tmpl"
)
+HELIX_RELAY_CONFIG_FILEPATH = STATIC_FILES_DIRPATH + "/mev/helix/config.yaml.tmpl"
diff --git a/static_files/mev/flashbots/mev_builder/config.toml.tmpl b/static_files/mev/flashbots/mev_builder/config.toml.tmpl
index c8e55adf5..00b00de88 100644
--- a/static_files/mev/flashbots/mev_builder/config.toml.tmpl
+++ b/static_files/mev/flashbots/mev_builder/config.toml.tmpl
@@ -24,7 +24,7 @@ ignore_cancellable_orders = true
sbundle_mergeable_signers = []
live_builders = ["mp-ordering", "mgp-ordering"]
-enabled_relays = ["flashbots"]
+enabled_relays = ["{{ .RelayName }}"]
root_hash_use_sparse_trie=true
root_hash_compare_sparse_trie=false
@@ -35,7 +35,7 @@ subsidy = "{{ .Subsidy }}"
[[relays]]
-name = "flashbots"
+name = "{{ .RelayName }}"
url = "http://{{ .PublicKey }}@{{ .Relay }}:{{ .RelayPort }}"
priority = 0
use_ssz_for_submit = false
diff --git a/static_files/mev/helix/config.yaml.tmpl b/static_files/mev/helix/config.yaml.tmpl
new file mode 100644
index 000000000..0ea4cdfcc
--- /dev/null
+++ b/static_files/mev/helix/config.yaml.tmpl
@@ -0,0 +1,98 @@
+# Optional: Custom instance identifier for logging/monitoring
+instance_id: "kurtosis-helix-relay"
+
+network_config: !Custom
+ dir_path: "{{ .GENESIS_CONFIG_MOUNT_PATH_ON_CONTAINER }}/config.json"
+ genesis_validator_root: "{{ .GENESIS_VALIDATORS_ROOT }}"
+ genesis_time: {{ .GENESIS_TIME }}
+
+# PostgreSQL Database Configuration (with TimescaleDB)
+postgres:
+ hostname: "{{ .POSTGRES_HOST_NAME }}"
+ port: {{ .POSTGRES_PORT }}
+ db_name: "{{ .POSTGRES_DB }}"
+ user: "{{ .POSTGRES_USER }}"
+ password: "{{ .POSTGRES_PASS }}"
+ region: 0
+ region_name: "LOCAL"
+
+# Beacon Client(s) - for fetching chain data and publishing blocks
+beacon_clients:
+ - url: "{{ .BEACON_URI }}"
+
+gossip_payload_on_header: false
+
+# Simulator(s) - Execution clients for block validation
+simulators:
+ # Regular validation simulator
+ - url: "{{ .BLOCKSIM_URI }}"
+ namespace: flashbots # RPC method prefix
+ is_merging_simulator: false
+ max_concurrent_tasks: 32
+
+# API Routes Configuration
+router_config:
+ enabled_routes:
+ # Builder API routes
+ - route: GetValidators
+ - route: SubmitBlock
+ - route: GetTopBid
+
+ # Proposer API routes
+ - route: GetHeader
+ rate_limit:
+ replenish_ms: 100
+ burst_size: 10
+ - route: GetPayload
+ - route: RegisterValidators
+ - route: Status
+
+ # Data API routes
+ - route: ProposerPayloadDelivered
+ - route: BuilderBidsReceived
+ - route: ValidatorRegistration
+
+ # Graceful shutdown delay (milliseconds)
+ shutdown_delay_ms: 12000
+
+# Timing game configuration (for header delay strategy)
+timing_game_config:
+ max_header_delay_ms: 650
+ latest_header_delay_ms_in_slot: 2000
+ default_client_latency_ms: 150
+
+# Target propagation duration for get_payload
+target_get_payload_propagation_duration_ms: 1000
+
+# Instance type flags
+is_submission_instance: true # Accepts block submissions
+is_registration_instance: true # Accepts validator registrations
+
+# Admin API authentication token
+admin_token: "admin_token"
+
+# Alternative: Console logging
+logging: !Console
+
+# Optional: Website/dashboard
+website:
+ enabled: true
+ port: {{ .HELIX_RELAY_WEBSITE_PORT }}
+ listen_address: "0.0.0.0"
+ show_config_details: false
+ network_name: "Kurtosis Helix Relay" # TODO - we can configure this to show network
+ relay_url: "https://{{ .HELIX_RELAY_ENDPOINT_URL }}"
+ relay_pubkey: "{{ .HELIX_RELAY_PUBKEY }}"
+ link_beaconchain: "https://holesky.beaconcha.in"
+ link_etherscan: "https://holesky.etherscan.io"
+ link_data_api: "https://relay.example.com/relay/v1/data"
+
+# CPU Core Pinning (CRITICAL for production performance)
+cores:
+ auctioneer: 0 # Single core for main auctioneer thread
+ sub_workers: [0] # Cores for submission workers
+ reg_workers: [0] # Cores for registration workers
+ tokio: [0] # Cores for Tokio async runtime
+
+# Optional: Enable local development mode (disables some checks)
+is_local_dev: false
\ No newline at end of file