Skip to content

Commit 903fd99

Browse files
pk910barnabasbusa
andauthored
feat: add buildoor as separate mev stack (#1309)
## Summary - Add `buildoor` as a new MEV type - a self-contained builder+relay service that integrates with standard flashbots mev-boost - Unlike flashbots/helix/mev-rs, buildoor doesn't require separate relay infrastructure or a dedicated builder participant - Configurable via `buildoor_params` with support for legacy builder API (`--builder-api-enabled`) and ePBS (`--epbs-enabled`) ## Settings `mev_type: buildoor` | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `buildoor_params.image` | string | `ethpandaops/buildoor:main` | Docker image for the buildoor service | | `buildoor_params.builder_api` | bool | `true` | Enable the traditional Builder API (`--builder-api-enabled`) | | `buildoor_params.epbs_builder` | bool | `true` | Enable ePBS bidding and revealing (`--epbs-enabled`) | | `buildoor_params.extra_args` | list | `[]` | Additional CLI flags passed to the buildoor service | ## Example Run `kurtosis run . --args-file .github/tests/mev-buildoor.yaml` and see buildoor url in services ## Buildoor Screenshot <img width="1861" height="1005" alt="image" src="https://github.com/user-attachments/assets/9a3b2c1b-11bd-4711-9ff9-2b6481213223" /> --------- Co-authored-by: Barnabas Busa <barnabas.busa@ethereum.org>
1 parent f117b94 commit 903fd99

File tree

8 files changed

+196
-3
lines changed

8 files changed

+196
-3
lines changed

.github/tests/mev-buildoor.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
participants:
2+
- el_type: geth
3+
cl_type: lighthouse
4+
count: 2
5+
mev_type: buildoor
6+
buildoor_params:
7+
builder_api: true
8+
epbs_builder: true
9+
additional_services:
10+
- dora
11+
- spamoor

README.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1272,14 +1272,16 @@ mempool_bridge_params:
12721272
# Default: "30s"
12731273
retry_interval: "30s"
12741274

1275-
# Supports six values
1275+
# Supports seven values
12761276
# Default: "null" - no mev boost, mev builder, mev flood or relays are spun up
12771277
# "mock" - mock-builder & mev-boost are spun up
12781278
# "flashbots" - mev-boost, relays, flooder and builder are all spun up, powered by [flashbots](https://github.com/flashbots)
12791279
# "mev-rs" - mev-boost, relays and builder are all spun up, powered by [mev-rs](https://github.com/ralexstokes/mev-rs/)
12801280
# "commit-boost" - mev-boost, relays and builder are all spun up, powered by [commit-boost](https://github.com/Commit-Boost/commit-boost-client)
12811281
# "helix" - helix relay, flashbots builder and mev-boost are spun up, powered by [helix](https://github.com/gattaca-com/helix)
12821282
# Note: Helix uses TimescaleDB (PostgreSQL with time-series extension) for data storage
1283+
# "buildoor" - a self-contained builder+relay service & mev-boost are spun up, powered by [buildoor](https://github.com/ethpandaops/buildoor)
1284+
# Supports both legacy builder API and ePBS bidding. No separate relay infrastructure or builder participant needed.
12831285
# We have seen instances of multibuilder instances failing to start mev-relay-api with non zero epochs
12841286
mev_type: null
12851287

@@ -1331,6 +1333,17 @@ mev_params:
13311333
# The image to use for helix relay (used when run_multiple_relays is true or mev_type is helix)
13321334
helix_relay_image: ghcr.io/gattaca-com/helix-relay:main
13331335

1336+
# Parameters for the buildoor builder+relay service (used when mev_type is "buildoor")
1337+
buildoor_params:
1338+
# The image to use for buildoor
1339+
image: ethpandaops/buildoor:main
1340+
# Enable the legacy builder API (traditional block building via relay)
1341+
builder_api: true
1342+
# Enable ePBS bidding and revealing
1343+
epbs_builder: true
1344+
# Extra parameters to pass to the buildoor service
1345+
extra_args: []
1346+
13341347
# Enables Xatu Sentry for all participants
13351348
# Defaults to false
13361349
xatu_sentry_enabled: false
@@ -1662,6 +1675,25 @@ network_params:
16621675
16631676
</details>
16641677
1678+
<details>
1679+
<summary>A 2-node Ethereum network with buildoor (self-contained builder+relay)</summary>
1680+
1681+
```yaml
1682+
participants:
1683+
- el_type: geth
1684+
cl_type: lighthouse
1685+
count: 2
1686+
mev_type: buildoor
1687+
buildoor_params:
1688+
builder_api: true
1689+
epbs_builder: true
1690+
additional_services:
1691+
- dora
1692+
- spamoor
1693+
```
1694+
1695+
</details>
1696+
16651697
<details>
16661698
<summary>A 3-node Ethereum network with Helix relay for MEV-boost infrastructure</summary>
16671699
@@ -1865,6 +1897,7 @@ The package also supports other MEV implementations:
18651897
- `"mev_type": "helix"` - Uses the high-performance [Helix relay](https://github.com/gattaca-com/helix) with TimescaleDB backend for data storage
18661898
- `"mev_type": "mev-rs"` - Alternative relay implementation powered by [mev-rs](https://github.com/ralexstokes/mev-rs/)
18671899
- `"mev_type": "commit-boost"` - Infrastructure powered by [commit-boost](https://github.com/Commit-Boost/commit-boost-client)
1900+
- `"mev_type": "buildoor"` - A self-contained builder+relay service powered by [buildoor](https://github.com/ethpandaops/buildoor). Supports both legacy builder API and ePBS bidding without requiring separate relay infrastructure or a dedicated builder participant.
18681901

18691902
Each implementation provides different features and performance characteristics suitable for various testing and development scenarios.
18701903

main.star

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ flashbots_mev_relay = import_module(
5252
)
5353
helix_relay = import_module("./src/mev/helix/helix_relay_launcher.star")
5454
mock_mev = import_module("./src/mev/flashbots/mock_mev/mock_mev_launcher.star")
55+
buildoor = import_module("./src/mev/buildoor/buildoor_launcher.star")
5556
mev_custom_flood = import_module(
5657
"./src/mev/flashbots/mev_custom_flood/mev_custom_flood_launcher.star"
5758
)
@@ -367,6 +368,35 @@ def run(plan, args={}):
367368
)
368369
mev_endpoints.append(endpoint)
369370
mev_endpoint_names.append(constants.MOCK_MEV_TYPE)
371+
elif (
372+
args_with_right_defaults.mev_type
373+
and args_with_right_defaults.mev_type == constants.BUILDOOR_MEV_TYPE
374+
):
375+
beacon_uri = "http://{0}:{1}".format(
376+
all_cl_contexts[0].ip_address,
377+
all_cl_contexts[0].http_port,
378+
)
379+
el_rpc_uri = "http://{0}:{1}".format(
380+
all_el_contexts[0].ip_addr,
381+
all_el_contexts[0].rpc_port_num,
382+
)
383+
engine_rpc_uri = "http://{0}:{1}".format(
384+
all_el_contexts[0].ip_addr,
385+
all_el_contexts[0].engine_rpc_port_num,
386+
)
387+
endpoint = buildoor.launch_buildoor(
388+
plan,
389+
beacon_uri,
390+
el_rpc_uri,
391+
engine_rpc_uri,
392+
jwt_file,
393+
prefunded_accounts[0].private_key,
394+
args_with_right_defaults.buildoor_params,
395+
global_node_selectors,
396+
global_tolerations,
397+
)
398+
mev_endpoints.append(endpoint)
399+
mev_endpoint_names.append(constants.BUILDOOR_MEV_TYPE)
370400
elif args_with_right_defaults.mev_type and (
371401
args_with_right_defaults.mev_type == constants.FLASHBOTS_MEV_TYPE
372402
or args_with_right_defaults.mev_type == constants.MEV_RS_MEV_TYPE
@@ -496,6 +526,7 @@ def run(plan, args={}):
496526
args_with_right_defaults.mev_type == constants.FLASHBOTS_MEV_TYPE
497527
or args_with_right_defaults.mev_type == constants.MOCK_MEV_TYPE
498528
or args_with_right_defaults.mev_type == constants.HELIX_MEV_TYPE
529+
or args_with_right_defaults.mev_type == constants.BUILDOOR_MEV_TYPE
499530
):
500531
mev_boost_launcher = flashbots_mev_boost.new_mev_boost_launcher(
501532
MEV_BOOST_SHOULD_CHECK_RELAY,

network_params.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ ethereum_metrics_exporter_enabled: false
190190
parallel_keystore_generation: false
191191
disable_peer_scoring: false
192192
persistent: false
193-
# Supports: null, mock, flashbots, mev-rs, commit-boost, helix
193+
# Supports: null, mock, flashbots, mev-rs, commit-boost, helix, buildoor
194194
mev_type: null
195195
mev_params:
196196
mev_relay_image: ethpandaops/mev-boost-relay:main
@@ -213,6 +213,11 @@ mev_params:
213213
helix_relay_image: ghcr.io/gattaca-com/helix-relay:main
214214
custom_flood_params:
215215
interval_between_transactions: 1
216+
buildoor_params:
217+
image: ethpandaops/buildoor:main
218+
builder_api: true
219+
epbs_builder: true
220+
extra_args: []
216221
bootnodoor_params:
217222
image: ethpandaops/bootnodoor:latest
218223
min_cpu: 100
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
constants = import_module("../../package_io/constants.star")
2+
shared_utils = import_module("../../shared_utils/shared_utils.star")
3+
4+
BUILDOOR_SERVICE_NAME = "buildoor"
5+
BUILDOOR_API_PORT = 8080
6+
BUILDOOR_BUILDER_API_PORT = 9000
7+
8+
MIN_CPU = 100
9+
MAX_CPU = 1000
10+
MIN_MEMORY = 128
11+
MAX_MEMORY = 1024
12+
13+
14+
def launch_buildoor(
15+
plan,
16+
beacon_uri,
17+
el_rpc_uri,
18+
engine_rpc_uri,
19+
jwt_file,
20+
prefunded_key,
21+
buildoor_params,
22+
global_node_selectors,
23+
global_tolerations,
24+
):
25+
tolerations = shared_utils.get_tolerations(global_tolerations=global_tolerations)
26+
27+
# Strip 0x prefix if present since keys are expected as hex-only
28+
wallet_key = prefunded_key
29+
if wallet_key.startswith("0x"):
30+
wallet_key = wallet_key[2:]
31+
32+
# Use the existing BLS keypair from constants for builder identity
33+
builder_bls_key = constants.DEFAULT_MEV_SECRET_KEY[2:]
34+
35+
cmd = [
36+
"run",
37+
"--cl-client={0}".format(beacon_uri),
38+
"--el-rpc={0}".format(el_rpc_uri),
39+
"--el-engine-api={0}".format(engine_rpc_uri),
40+
"--el-jwt-secret=" + constants.JWT_MOUNT_PATH_ON_CONTAINER,
41+
"--builder-privkey={0}".format(builder_bls_key),
42+
"--wallet-privkey={0}".format(wallet_key),
43+
"--api-port={0}".format(BUILDOOR_API_PORT),
44+
"--builder-api-port={0}".format(BUILDOOR_BUILDER_API_PORT),
45+
]
46+
47+
if buildoor_params.builder_api:
48+
cmd.append("--builder-api-enabled")
49+
50+
if buildoor_params.epbs_builder:
51+
cmd.append("--epbs-enabled")
52+
53+
cmd += buildoor_params.extra_args
54+
55+
buildoor_service = plan.add_service(
56+
name=BUILDOOR_SERVICE_NAME,
57+
config=ServiceConfig(
58+
image=buildoor_params.image,
59+
ports={
60+
"api": PortSpec(
61+
number=BUILDOOR_API_PORT,
62+
transport_protocol="TCP",
63+
application_protocol="http",
64+
),
65+
"builder-api": PortSpec(
66+
number=BUILDOOR_BUILDER_API_PORT, transport_protocol="TCP"
67+
),
68+
},
69+
cmd=cmd,
70+
files={
71+
constants.JWT_MOUNTPOINT_ON_CLIENTS: jwt_file,
72+
},
73+
min_cpu=MIN_CPU,
74+
max_cpu=MAX_CPU,
75+
min_memory=MIN_MEMORY,
76+
max_memory=MAX_MEMORY,
77+
node_selectors=global_node_selectors,
78+
tolerations=tolerations,
79+
),
80+
)
81+
return "http://{0}@{1}:{2}".format(
82+
constants.DEFAULT_MEV_PUBKEY, BUILDOOR_SERVICE_NAME, BUILDOOR_BUILDER_API_PORT
83+
)

src/package_io/constants.star

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ FLASHBOTS_MEV_TYPE = "flashbots"
9797
MEV_RS_MEV_TYPE = "mev-rs"
9898
COMMIT_BOOST_MEV_TYPE = "commit-boost"
9999
HELIX_MEV_TYPE = "helix"
100+
BUILDOOR_MEV_TYPE = "buildoor"
100101
DEFAULT_DORA_IMAGE = "ethpandaops/dora:latest"
101102
DEFAULT_CHECKPOINTZ_IMAGE = "ethpandaops/checkpointz:latest"
102103
DEFAULT_SPAMOOR_IMAGE = "ethpandaops/spamoor:latest"
@@ -114,6 +115,7 @@ DEFAULT_MEV_RS_IMAGE = "ethpandaops/mev-rs:main"
114115
DEFAULT_MEV_RS_IMAGE_MINIMAL = "ethpandaops/mev-rs:main-minimal"
115116
DEFAULT_COMMIT_BOOST_MEV_BOOST_IMAGE = "ghcr.io/commit-boost/pbs:latest"
116117
DEFAULT_MOCK_MEV_IMAGE = "ethpandaops/rustic-builder:main"
118+
DEFAULT_BUILDOOR_IMAGE = "ethpandaops/buildoor:main"
117119
DEFAULT_HELIX_RELAY_IMAGE = "ghcr.io/gattaca-com/helix-relay:main"
118120
DEFAULT_EWS_IMAGE = "ghcr.io/eth-act/zkboost/execution-witness-sentry:latest"
119121
DEFAULT_MEV_PUBKEY = "0xa55c1285d84ba83a5ad26420cd5ad3091e49c55a813eee651cd467db38a8c8e63192f47955e9376f6b42f6d190571cb5"

src/package_io/input_parser.star

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ ATTR_TO_BE_SKIPPED_AT_ROOT = (
9090
"bootnodoor_params",
9191
"mempool_bridge_params",
9292
"ews_params",
93+
"buildoor_params",
9394
"ethereum_genesis_generator_params",
9495
)
9596

@@ -129,6 +130,7 @@ def input_parser(plan, input_args):
129130
result["spamoor_params"] = get_default_spamoor_params()
130131
result["mempool_bridge_params"] = get_default_mempool_bridge_params()
131132
result["ews_params"] = get_default_ews_params()
133+
result["buildoor_params"] = get_default_buildoor_params()
132134

133135
if constants.NETWORK_NAME.shadowfork in result["network_params"]["network"]:
134136
shadow_base = result["network_params"]["network"].split("-shadowfork")[0]
@@ -222,6 +224,10 @@ def input_parser(plan, input_args):
222224
for sub_attr in input_args["ews_params"]:
223225
sub_value = input_args["ews_params"][sub_attr]
224226
result["ews_params"][sub_attr] = sub_value
227+
elif attr == "buildoor_params":
228+
for sub_attr in input_args["buildoor_params"]:
229+
sub_value = input_args["buildoor_params"][sub_attr]
230+
result["buildoor_params"][sub_attr] = sub_value
225231

226232
if result.get("disable_peer_scoring"):
227233
result = enrich_disable_peer_scoring(result)
@@ -232,6 +238,7 @@ def input_parser(plan, input_args):
232238
constants.MEV_RS_MEV_TYPE,
233239
constants.COMMIT_BOOST_MEV_TYPE,
234240
constants.HELIX_MEV_TYPE,
241+
constants.BUILDOOR_MEV_TYPE,
235242
):
236243
result = enrich_mev_extra_params(
237244
result,
@@ -243,7 +250,7 @@ def input_parser(plan, input_args):
243250
pass
244251
else:
245252
fail(
246-
"Unsupported MEV type: {0}, please use 'mock', 'flashbots', 'mev-rs', 'commit-boost' or 'helix' type".format(
253+
"Unsupported MEV type: {0}, please use 'mock', 'flashbots', 'mev-rs', 'commit-boost', 'helix' or 'buildoor' type".format(
247254
result.get("mev_type")
248255
)
249256
)
@@ -932,6 +939,12 @@ def input_parser(plan, input_args):
932939
num_proofs=result["ews_params"]["num_proofs"],
933940
env=result["ews_params"]["env"],
934941
),
942+
buildoor_params=struct(
943+
image=result["buildoor_params"]["image"],
944+
extra_args=result["buildoor_params"]["extra_args"],
945+
builder_api=result["buildoor_params"]["builder_api"],
946+
epbs_builder=result["buildoor_params"]["epbs_builder"],
947+
),
935948
)
936949

937950

@@ -1900,6 +1913,15 @@ def get_default_ews_params():
19001913
}
19011914

19021915

1916+
def get_default_buildoor_params():
1917+
return {
1918+
"image": constants.DEFAULT_BUILDOOR_IMAGE,
1919+
"extra_args": [],
1920+
"builder_api": True,
1921+
"epbs_builder": True,
1922+
}
1923+
1924+
19031925
def get_port_publisher_params(parameter_type, input_args=None):
19041926
port_publisher_parameters = {
19051927
"nat_exit_ip": "KURTOSIS_IP_ADDR_PLACEHOLDER",

src/package_io/sanity_check.star

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,12 @@ SUBCATEGORY_PARAMS = {
427427
"num_proofs",
428428
"env",
429429
],
430+
"buildoor_params": [
431+
"image",
432+
"extra_args",
433+
"builder_api",
434+
"epbs_builder",
435+
],
430436
}
431437

432438
ADDITIONAL_SERVICES_PARAMS = [

0 commit comments

Comments
 (0)