Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
3a2c7d5
Add builder ssz flow
eserilev Feb 5, 2025
5059593
Integration tests, fixes, and clippy/linting
eserilev Feb 18, 2025
35b8542
resolve merge conflicts
eserilev Feb 19, 2025
4acddbe
resolve merge conflictds
eserilev Feb 23, 2025
7005422
fix tests
eserilev Feb 23, 2025
5935659
CBST2-04: Update JWT secrets on reload and revoke module endpoint (#295)
ManuelBilbao Jul 27, 2025
91f2cb4
Merge branch 'main' into sigp-audit-fixes
jclapis Jul 30, 2025
46e6f94
Merge branch 'main' into sigp-audit-fixes
jclapis Jul 31, 2025
b802fec
Merge branch 'main' into sigp-audit-fixes
jclapis Aug 12, 2025
151e811
Merge branch 'main' into sigp-audit-fixes
jclapis Aug 13, 2025
498eed9
CBST2-02: Make proposer commitment signatures unique to modules (#329)
jclapis Aug 19, 2025
af13089
Split `request_signature` into separate paths that return JSON (#350)
jclapis Aug 19, 2025
0ef8787
Add nonce and chain ID to signature requests (#354)
jclapis Aug 19, 2025
ee18aa1
Merge branch 'main' into sigp-audit-fixes
jclapis Aug 19, 2025
6988444
Merge `main` to `sigp-audit-fixes` (#361)
jclapis Aug 26, 2025
25bd5a6
Merge branch 'sigp-audit-fixes' of github.com:Commit-Boost/commit-boo…
jclapis Aug 26, 2025
52aec57
Add payload hash to signer JWT claims (#356)
jclapis Sep 2, 2025
f2a275b
Merge branch 'main' into sigp-audit-fixes
jclapis Sep 2, 2025
6b14d77
Add TLS to signer (#357)
jclapis Sep 3, 2025
eb61667
Removed old dependency (#370)
jclapis Sep 8, 2025
2dfe96b
Merge main to sigp audit fixes (#371)
jclapis Sep 9, 2025
06c207f
Started porting #252 back to main
jclapis Sep 9, 2025
24fabca
Finished porting, successful tests
jclapis Sep 9, 2025
f0875cd
Merge remote-tracking branch 'eserilev/add-builder-ssz-flow' into add…
jclapis Sep 9, 2025
bad5675
Cleaned up merge
jclapis Sep 9, 2025
50fccb5
Fixed clippy
jclapis Sep 9, 2025
86fa858
Swapped to LH's ForkName enum
jclapis Sep 15, 2025
e7335f6
Refactored encoding type support based on feedback
jclapis Sep 16, 2025
8c82b84
Fixed clippy
jclapis Sep 16, 2025
d566dea
Fix misc findings from reaudit (#376)
jclapis Sep 30, 2025
8ddb055
Added make to the build file
jclapis Sep 30, 2025
9103b51
Merge branch 'main' into sigp-audit-fixes
jclapis Oct 6, 2025
9a58c07
Merge branch 'main' into add-ssz-to-pbs
jclapis Oct 14, 2025
a3f8d9d
fix(signer): Mark a JWT failure if payload conversion fail (#387)
ManuelBilbao Oct 20, 2025
7bf2589
Merge branch 'sigp-audit-fixes' of github.com:Commit-Boost/commit-boo…
jclapis Oct 20, 2025
b66f411
Removed a test that was deleted in main
jclapis Oct 20, 2025
b541ffa
Merge branch 'main' into sigp-audit-fixes
jclapis Oct 20, 2025
01f6b04
Merge branch 'main' into add-ssz-to-pbs
jclapis Oct 21, 2025
58b4eb9
Merge branch 'main' into sigp-audit-fixes
jclapis Oct 21, 2025
a287e96
Merge branch 'main' into add-ssz-to-pbs
jclapis Oct 21, 2025
e58d67e
refactor(signer): Use config-based header to extract IP from (#388)
ManuelBilbao Oct 21, 2025
de99bb9
spawn
ltitanb Oct 23, 2025
06a3092
Merge branch 'lt/get-payload-v2-on-all' into add-ssz-to-pbs
jclapis Oct 27, 2025
a556aa9
Merge branch 'main' into add-ssz-to-pbs
jclapis Nov 3, 2025
3e4a7da
Changed get_accept_type() to allow multiple types
jclapis Nov 4, 2025
7ab1f7e
get_header()'s impl now works with multiple types
jclapis Nov 6, 2025
bfbcfe4
Added retry-different-accept-types thing to get_header
jclapis Nov 7, 2025
adfec62
Refactored and added some unit tests
jclapis Nov 10, 2025
b22eed8
Added explicit lowercase matching to EncodingType
jclapis Nov 10, 2025
0155533
Added the Fulu fork slot for Mainnet
jclapis Nov 10, 2025
a975048
Merge branch 'update-fulu-slot' into ssz-update-v2
jclapis Nov 10, 2025
d64adbb
Merge branch 'main' into ssz-update-v2
jclapis Nov 10, 2025
8ebfbd0
Cleaned up some error handling
jclapis Nov 10, 2025
2499bd5
Made some strings static
jclapis Nov 10, 2025
41d879e
PbsClientError can noe be created from BodyDeserializeError
jclapis Nov 10, 2025
42b8060
Fix clippy
jclapis Nov 11, 2025
a9680f7
Removed consensus-version-header from submit_block response
jclapis Nov 11, 2025
d7bde7f
Added multi-type support to submit_block
jclapis Nov 11, 2025
ad3f019
Updated the mock relay with multi-type support on submit_block
jclapis Nov 11, 2025
aaa0967
Updated the submit_block unit tests
jclapis Nov 11, 2025
83ca8f8
Added more multitype tests to submit_block, not done yet though
jclapis Nov 12, 2025
d36ef3b
Switched relay response handling to switch to JSON on any 4xx
jclapis Nov 17, 2025
58b63db
Merge branch 'main' into ssz-update-v2
jclapis Dec 9, 2025
85382a5
fix(signer): introduce config to set the amount of trusted proxies in…
ManuelBilbao Dec 10, 2025
d2b8226
Optimized get_header
jclapis Dec 10, 2025
fcd7425
Some refactoring of send_get_header_impl to process the payload
jclapis Dec 10, 2025
1a50d7d
Refactored get_header and submit_block based on feedback
jclapis Dec 17, 2025
19121f3
fix(signer): rightmost header fixes (#420)
ManuelBilbao Dec 23, 2025
d4d5260
Merge branch 'main' into sigp-audit-fixes
jclapis Jan 6, 2026
3dcc47c
Merge branch 'main' into ssz-update-v2
jclapis Feb 9, 2026
e30cbde
Merge branch 'main' into ssz-update-v2
jclapis Feb 9, 2026
ff0b3ef
Merge branch 'main' into ssz-update-v2
jclapis Mar 2, 2026
02364f3
Merge branch 'main' into sigp-audit-fixes
jclapis Mar 2, 2026
a5d444d
Merge branch 'main' into ssz-update-v2
jclapis Mar 2, 2026
533e4c0
Merge branch 'main' into sigp-audit-fixes
jclapis Mar 2, 2026
4681103
Merge remote-tracking branch 'upstream/main' into sigp-audit-fixes
JasonVranek Mar 17, 2026
9782d22
improve tls/cert config testing
JasonVranek Mar 17, 2026
bb28eb0
more util test coverage and remove duplicate env read from docker_ini…
JasonVranek Mar 20, 2026
511d07d
Bump lh from v8.0.0-rc.0 to stable v8.0.0, and bump rust from 1.89 to…
JasonVranek Mar 22, 2026
4afbf35
bump rust toolchain to nightly-2026-01-01
JasonVranek Mar 22, 2026
48e1eec
Add support for validation bypassing (#422)
jclapis Mar 23, 2026
7ddda6d
Merge remote-tracking branch 'upstream/sigp-audit-fixes' into ssz-upd…
JasonVranek Mar 23, 2026
717390e
address review comments
JasonVranek Mar 24, 2026
a949c83
Merge remote-tracking branch 'upstream/sigp-audit-fixes' into ssz-upd…
JasonVranek Mar 24, 2026
5daf7f9
Improve testing around SSZ/validation bypassing. Fix issue where bypa…
JasonVranek Mar 24, 2026
788c1fc
Merge branch 'main' into ssz-update-v2
JasonVranek Apr 17, 2026
ed6ead5
fix deploy docs
JasonVranek Apr 17, 2026
a59bd19
Lighthouse v8.0.0 → v8.1.3 migration for security
JasonVranek Apr 18, 2026
e562003
just fmt
JasonVranek Apr 18, 2026
8edbc5a
remove all hardcoded ports from tests
JasonVranek Apr 20, 2026
36d604c
local audit fix: forward v1 payload to BN when submit_block v2 falls
JasonVranek Apr 20, 2026
f4f1b2f
local audit fix: tolerate Content-Type MIME params on relay responses
JasonVranek Apr 20, 2026
1927bce
local audit fix: restrict SSZ→JSON retry to 406/415 per builder-spec
JasonVranek Apr 20, 2026
0fcf9bc
local audit fix: honor Accept q-value ordering for deterministic content
JasonVranek Apr 20, 2026
6007fe5
fix warnings + add more integration tests
JasonVranek Apr 20, 2026
0e8f686
review - nits pass one
JasonVranek Apr 21, 2026
c95d39e
clippy and CI will catch dead code
JasonVranek Apr 21, 2026
7c591f0
nits + remove dead code
JasonVranek Apr 21, 2026
9b93474
remove `RawRequest` wrapper + remove Arc from HeaderMap + replace
JasonVranek Apr 21, 2026
df80d1b
make SubmitBlockResponseInfo.content_type an Option
JasonVranek Apr 21, 2026
8db7220
Wildcard now routes through `NO_PREFERENCE_DEFAULT`
JasonVranek Apr 21, 2026
7959cb1
missing Content-Type once again falls back to JSON via the shared
JasonVranek Apr 21, 2026
6a4f28b
handle_get_header, collapse redundant if/else into more legible match
JasonVranek Apr 21, 2026
29c2a83
reuse shared content_type_header
JasonVranek Apr 21, 2026
8ae1f0c
drop hashmap and inline get_ssz_value_offset_for_fork
JasonVranek Apr 21, 2026
fdaa06e
consolidate duplicate code in *_light and *_full into
JasonVranek Apr 21, 2026
4bc807b
make "accepts_ssz" and "accepts_json" inside handle_submit_block_impl
JasonVranek Apr 21, 2026
ad040cb
Merge branch 'main' into ssz-update-v2
JasonVranek May 12, 2026
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
176 changes: 176 additions & 0 deletions .agent/CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# Project Context

## Domain Glossary

**Commit-Boost** — A modular sidecar for Ethereum validators. Runs alongside the beacon node, standardizing the last mile of communication between validators and third-party protocols (MEV-Boost relays, preconfirmation services, inclusion list services, etc.).

**Proposer-Builder Separation (PBS)** — The Ethereum protocol split where validators propose blocks but builders construct them. Commit-Boost acts as middleware between the beacon node's Builder API calls and external relays/builders.

**PBS Service** — The core service (`cb-pbs` crate) that implements the [Builder API](https://ethereum.github.io/builder-specs/). Receives `get_header`, `submit_block`, `register_validator`, and `get_status` calls from the beacon node, fans them out to configured relays, selects the best bid, and returns it.

**Signer Service** — A separate HTTP service (`cb-signer` crate) that holds validator consensus keys and creates signatures. Modules request signatures (BLS or ECDSA, via consensus keys or proxy keys) using JWT-authenticated HTTP calls. The signer *never* exposes private keys to modules.

**Commit Module** — A plugin (Docker container) that implements a specific proposer commitment protocol (e.g., preconfirmations, inclusion lists). Communicates with the Signer via the Signer Client (`SignerClient` in `cb-common`). Loaded as a separate process; configured in the main TOML config under `[modules]`.

**Builder API Module** — Like a commit module but plugs into the PBS request pipeline. Can add custom routes and override the default MEV-Boost behavior via the `BuilderApi` trait.

**Mux (Multiplexer)** — A configuration construct that routes different validator pubkeys to different sets of relays with different timing/config overrides. A "pubkey → mux" mapping. Supports loading pubkeys from: static file, HTTP endpoint, or Registry (Lido/SSV operator registries, with optional auto-refresh).

**Relay** — An external MEV-Boost relay that receives builder API calls. Defined by `scheme://pubkey@host` URL format. Supports timing games (delayed header requests), custom headers, GET params, and retry limits.

**Consensus Signer** — A BLS keypair loaded into the Signer (from keystore, Dirk, or other loader). Used to sign consensus-layer messages (e.g., preconfirmation commitments).

**Proxy Key** — A derived key (BLS or ECDSA) that a commit module generates via the Signer. The Signer creates a proxy delegation from a consensus key, allowing the module to sign messages without holding the consensus key. Proxy delegations can be persisted via a Proxy Store.

**Proxy Store** — Persistence for proxy key delegations. Ensures proxy keys survive restarts. Supports ERC-2335 keystore format or raw file.

**Dirk** — A remote signer backend (Attestant's Dirk). The Signer can delegate to Dirk for consensus signing, while still generating proxy keys locally. Note: ECDSA proxy signing is not supported with Dirk.

**Timing Games** — A relay-specific setting where the PBS service delays `get_header` requests until a specific time in the slot, then polls at a configured frequency. Used to give late builders an advantage.

**Registry Mux** — A mux whose pubkey list comes from a live operator registry (Lido CSM, Lido curated module, SSV network). The pubkey list auto-refreshes at a configurable interval.

**Fork-Versioned Response** — The pattern used for `get_header` and `submit_block` responses. Responses are wrapped in `ForkVersionedResponse<T>` (from lighthouse) which carries a fork version discriminator. The PBS service multiplexes across Electra and Fulu fork request/response shapes.

**Builder API Version** — `V1` for the standard Builder API, `V2` for the extended API (supports execution requests). Routes are nested under `/eth/v1/builder/` and `/eth/v2/builder/`.

## Architecture Map

```
┌─────────────────────────────────────────────────────────────────┐
│ commit-boost binary │
│ Subcommands: pbs | signer | init │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ PBS Service │ │ Signer Service │ │
│ │ (cb-pbs crate) │ │ (cb-signer crate) │ │
│ │ │ │ │ │
│ │ Routes: │ │ Routes: │ │
│ │ GET get_header ─────│───▶│ POST request_sig_bls │ │
│ │ GET get_status │ │ POST request_sig_* │ │
│ │ POST register_val │ │ GET get_pubkeys │ │
│ │ POST submit_block │ │ POST generate_proxy │ │
│ │ POST reload │ │ POST reload │ │
│ │ │ │ POST revoke_module │ │
│ │ State: │ │ GET status │ │
│ │ ┌─────────────────┐ │ │ │ │
│ │ │ PbsState<S> │ │ │ State: │ │
│ │ │ config: PbsModCfg│ │ │ ┌───────────────┐ │ │
│ │ │ mux_lookup: K→V │ │ │ │ SigningState │ │ │
│ │ │ relays: vec │ │ │ │ manager: Mgr │ │ │
│ │ │ data: S (ext) │ │ │ │ jwts: K→V │ │ │
│ │ └─────────────────┘ │ │ │ admin_secret │ │ │
│ │ │ │ └───────────────┘ │ │
│ │ BuilderApi trait: │ │ │ │
│ │ ┌─────────────────┐ │ │ SigningManager enum: │ │
│ │ │ get_header │ │ │ ┌── LocalManager │ │
│ │ │ get_status │ │ │ └── DirkManager │ │
│ │ │ submit_block │ │ │ │ │
│ │ │ register_val │ │ │ LocalManager: │ │
│ │ │ reload │ │ │ ┌── consensus keys │ │
│ │ │ extra_routes() │ │ │ └── proxy keys │ │
│ │ └─────────────────┘ │ │ │ │
│ │ │ │ Proxy store: │ │
│ │ Fan-out to N relays │ │ ┌── ERC2335 keystore │ │
│ │ Best bid selection │ │ └── raw file │ │
│ └───────────────────────┘ └───────────────────────┘ │
│ │ │ │
│ │ SignerClient │ JWT auth middleware │
│ │ (cb-common) │ rate limiter │
│ ▼ ▼ │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ cb-common crate │ │
│ │ ┌──────────┬──────────┬──────────┬──────────────────┐ │ │
│ │ │ config/ │ pbs/ │ commit/ │ signer/ │ │ │
│ │ │ Config │ types │ client │ schemes (BLS/ECD) │ │ │
│ │ │ Mux │ relay │ request │ loader │ │ │
│ │ │ Module │ builder │ response │ store (ERC2335) │ │ │
│ │ │ Signer │ constants│ error │ types │ │ │
│ │ ├──────────┼──────────┼──────────┼──────────────────┤ │ │
│ │ │ interop/ │ types │ utils │ signature │ │ │
│ │ │ lido/ssv │ Chain │ JWT │ verify_signed_msg │ │ │
│ │ └──────────┴──────────┴──────────┴──────────────────┘ │ │
│ └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

External:
Beacon Node ──Builder API──▶ PBS Service
PBS Service ──Builder API──▶ Relays (MEV-Boost)
PBS Service ──Commit API───▶ Commit Modules (sidecars)
Commit Modules ──Signer API─▶ Signer Service
Signer Service ──gRPC──────▶ Dirk (optional remote signer)
```

## Crate Responsibilities

| Crate | Purpose | Key Public API |
|-------|---------|---------------|
| `cb-common` | Shared types, config, PBS types, signer types, commit client, interop | `Chain`, `PbsConfig`, `RelayClient`, `SignerClient`, `ModuleId`, `Jwt`, `get_header`, `submit_block` |
| `cb-pbs` | PBS service: routes, MEV-Boost relay fan-out, state management | `PbsService`, `PbsState`, `BuilderApi` trait, `DefaultBuilderApi` |
| `cb-signer` | Signer service: key management, signing endpoints, JWT auth | `SigningService`, `SigningManager`, `LocalSigningManager`, `DirkManager` |
| `cb-metrics` | Prometheus metrics provider | `MetricsProvider` |
| `cb-cli` | Docker compose init helper | `handle_docker_init` |

## Data Flow: get_header Request

```
Beacon Node
│ GET /eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}
create_app_router (routes/router.rs)
│ Match GET_HEADER_PATH → handle_get_header
handle_get_header (routes/get_header.rs)
│ Extract GetHeaderParams, req headers
│ Look up state.mux_config_and_relays(pubkey)
│ → returns (PbsConfig, &[RelayClient], Option<mux_id>)
mev_boost::get_header (mev_boost/get_header.rs)
│ For each relay:
│ If timing_games: delay then poll at frequency
│ If not: immediate request
│ Track best bid by value
│ Optional extra validation: check EL block validity
│ Return best GetHeaderResponse or None (204)
Response to Beacon Node
```

## Key Configuration Flow

```
config.example.toml / CB_CONFIG env
├── [chain] → Chain (Mainnet/Holesky/Sepolia/Hoodi/Custom)
├── [[relays]] → Vec<RelayConfig> → Vec<RelayClient>
├── [pbs] → StaticPbsConfig → PbsConfig
├── [[mux]] → PbsMuxes → HashMap<BlsPublicKey, RuntimeMuxConfig>
├── [[modules]] → Vec<StaticModuleConfig> → module Docker containers
└── [signer] → SignerConfig → StartSignerConfig
```

## Relationships

- **PBS Service → Signer Service**: Uses `SignerClient` (from `cb-common`) to request signatures. Only when `with_signer = true` in PBS config.
- **Commit Module → Signer Service**: Each module gets its own JWT. Calls signer endpoints for consensus/proxy BLS/ECDSA signatures.
- **PBS Service → Relays**: Fans out Builder API calls. One HTTP client per relay. Timing games per relay. Mux routing per validator pubkey.
- **Signer Service → Dirk**: Delegates consensus signing to Dirk gRPC backend. Proxy key generation still local.
- **PBS Mux → Registry**: Lido CSM/module or SSV operator registries queried for validator pubkey lists. Auto-refresh for dynamic sets.

## Flagged Ambiguities

- **Module vs sidecar vs plugin**: The codebase uses "module" for the signer auth system (`ModuleId`, `ModuleSigningConfig`), but the PBS service also refers to "modules" (builder API plugins like preconfirmations). These are different concepts sharing one term.
- **PBS Config reload**: The PBS service watches the config file and hot-reloads on change. The signer also supports reload via admin API. These are independent mechanisms.
- **Custom chain support**: `Chain::Custom` allows any chain with genesis params. Some interop features (SSV) only support Mainnet/Holesky/Hoodi.

## Example Dialogue

**"How does a validator use Commit-Boost with MEV-Boost?"**
→ Configure relays in `[[relays]]`, set `[pbs]` options, run `commit-boost pbs`. Beacon node points Builder API at Commit-Boost. Commit-Boost fans out to relays, returns best bid. Optional: add timing games per relay.

**"How do I add a preconfirmation module?"**
→ Add `[[modules]]` entry with `type = "commit"`, `id`, `docker_image`, and `signing_id`. The module container gets `MODULE_JWT` and `SIGNER_URL` env vars. It calls `SignerClient` to request consensus/proxy signatures. Add `jwt_secret` to JWT secrets file.

**"What is a mux and when do I need it?"**
→ A mux routes specific validator pubkeys to specific relay sets with custom timeouts. Use when different validators under the same node operator need different relay configurations, or when integrating with SSV/Lido operator registries for automatic pubkey discovery.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
id: 0001
title: "Signer as separate service with JWT-auth and proxy key model"
status: "accepted" # proposed | accepted | deprecated | superseded
date: 2026-05-11T20:08:58.555Z
---

# ADR-0001: Signer as separate service with JWT-auth and proxy key model

Signer runs as a separate service holding consensus keys. Modules authenticate via per-module JWT secrets. Signer exposes HTTP endpoints for: BLS consensus signing, BLS proxy signing, ECDSA proxy signing, proxy key generation. Proxy keys are derived from consensus keys using a signing ID + module ID. Optional Dirk backend for remote signing with local proxy key generation fallback.

## Context

Commit-Boost modules (preconfirmations, inclusion lists, etc.) need to sign messages with validator consensus keys. Giving modules direct access to keys is insecure — modules are third-party Docker containers. Need a way to sign without key exposure, and to derive per-module keys for non-consensus signing.

## Consequences

Modules never hold or see consensus private keys. Signer can be a separate process with its own security boundary. JWT auth per module enables access control and revocation. Rate limiting on JWT failure prevents brute-force. Proxy key model allows modules to generate delegated keys without exposing consensus keys. Trade-off: extra network hop for every signature request, operational complexity of running signer sidecar.

## Alternatives considered

- Embed signing in each module (each module holds its own keys)
- Use a shared in-process signing library
- Use an external Web3Signer-compatible service only
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
id: 0002
title: "Mux-based relay routing with pubkey-to-config HashMap"
status: "accepted" # proposed | accepted | deprecated | superseded
date: 2026-05-11T20:09:15.478Z
---

# ADR-0002: Mux-based relay routing with pubkey-to-config HashMap

PBS Mux system: each mux has an id, a list of validator pubkeys, a relay list, and optional timeout overrides. `PbsState::mux_config_and_relays(pubkey)` does O(1) HashMap lookup to find the mux for a given validator. Mux pubkeys loaded from: static JSON file, HTTP endpoint, or Registry (Lido CSM/curated, SSV operator). Registry muxes support auto-refresh on a configurable interval. Default relay list used for pubkeys not in any mux.

## Context

Node operators run validators with different needs: some need fast relay response, others run timing games, some belong to SSV clusters or Lido curated modules. A single relay configuration for all validators is too coarse. Need to route different validator pubkeys to different relay sets with different timing/config.

## Consequences

Validators can be grouped into different relay/timing configurations without running multiple sidecars. Registry-based muxes (Lido, SSV) auto-discover pubkeys, reducing config maintenance. Mux pubkey sets must be disjoint (validated at config load). Config reload updates mux mappings live. Trade-off: config complexity increases with mux count; mux config is eagerly loaded at startup (blocking).

## Alternatives considered

- Single flat relay list for all validators
- Per-validator config file with all relay settings
- Dynamic relay selection based on bid history/performance
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
id: 0003
title: "Lighthouse types as canonical Ethereum data model"
status: "accepted" # proposed | accepted | deprecated | superseded
date: 2026-05-11T20:09:30.453Z
---

# ADR-0003: Lighthouse types as canonical Ethereum data model

Use Lighthouse (`lh_types`, `lh_eth2`) as the canonical source for Ethereum beacon chain types. Types are aliased through `cb-common::pbs::types` (e.g., `SignedBlindedBeaconBlock = lh_types::SignedBlindedBeaconBlock<MainnetEthSpec>`). This ensures wire-format compatibility with Lighthouse beacon nodes and benefits from Lighthouse's fork-aware dispatch.

## Context

Commit-Boost implements the Ethereum Builder API which uses SSZ-serialized beacon chain types (blinded blocks, execution payloads, builder bids). Need canonical type definitions that match the beacon node's encoding. Types must handle fork transitions (Electra → Fulu) where block body shape changes.

## Consequences

All Beacon API types (SignedBlindedBeaconBlock, ExecutionPayloadHeader, etc.) are lighthouse type aliases. Fork-aware types like ForkVersionedResponse come from lighthouse. SSZ serialization, tree-hash derivation, and fork dispatch all use lighthouse infrastructure. Trade-off: lighthouse dependency is heavyweight; version coupling means lighthouse upgrades may force Commit-Boost upgrades even if Builder API didn't change.

## Alternatives considered

- Define own Ethereum types from spec
- Use alloy/ethereum-consensus crate
- Use reth primitives
Loading
Loading