|
| 1 | +# Project Context |
| 2 | + |
| 3 | +## Domain Glossary |
| 4 | + |
| 5 | +**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.). |
| 6 | + |
| 7 | +**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. |
| 8 | + |
| 9 | +**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. |
| 10 | + |
| 11 | +**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. |
| 12 | + |
| 13 | +**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]`. |
| 14 | + |
| 15 | +**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. |
| 16 | + |
| 17 | +**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). |
| 18 | + |
| 19 | +**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. |
| 20 | + |
| 21 | +**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). |
| 22 | + |
| 23 | +**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. |
| 24 | + |
| 25 | +**Proxy Store** — Persistence for proxy key delegations. Ensures proxy keys survive restarts. Supports ERC-2335 keystore format or raw file. |
| 26 | + |
| 27 | +**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. |
| 28 | + |
| 29 | +**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. |
| 30 | + |
| 31 | +**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. |
| 32 | + |
| 33 | +**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. |
| 34 | + |
| 35 | +**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/`. |
| 36 | + |
| 37 | +## Architecture Map |
| 38 | + |
| 39 | +``` |
| 40 | +┌─────────────────────────────────────────────────────────────────┐ |
| 41 | +│ commit-boost binary │ |
| 42 | +│ Subcommands: pbs | signer | init │ |
| 43 | +├─────────────────────────────────────────────────────────────────┤ |
| 44 | +│ │ |
| 45 | +│ ┌──────────────────────┐ ┌──────────────────────┐ │ |
| 46 | +│ │ PBS Service │ │ Signer Service │ │ |
| 47 | +│ │ (cb-pbs crate) │ │ (cb-signer crate) │ │ |
| 48 | +│ │ │ │ │ │ |
| 49 | +│ │ Routes: │ │ Routes: │ │ |
| 50 | +│ │ GET get_header ─────│───▶│ POST request_sig_bls │ │ |
| 51 | +│ │ GET get_status │ │ POST request_sig_* │ │ |
| 52 | +│ │ POST register_val │ │ GET get_pubkeys │ │ |
| 53 | +│ │ POST submit_block │ │ POST generate_proxy │ │ |
| 54 | +│ │ POST reload │ │ POST reload │ │ |
| 55 | +│ │ │ │ POST revoke_module │ │ |
| 56 | +│ │ State: │ │ GET status │ │ |
| 57 | +│ │ ┌─────────────────┐ │ │ │ │ |
| 58 | +│ │ │ PbsState<S> │ │ │ State: │ │ |
| 59 | +│ │ │ config: PbsModCfg│ │ │ ┌───────────────┐ │ │ |
| 60 | +│ │ │ mux_lookup: K→V │ │ │ │ SigningState │ │ │ |
| 61 | +│ │ │ relays: vec │ │ │ │ manager: Mgr │ │ │ |
| 62 | +│ │ │ data: S (ext) │ │ │ │ jwts: K→V │ │ │ |
| 63 | +│ │ └─────────────────┘ │ │ │ admin_secret │ │ │ |
| 64 | +│ │ │ │ └───────────────┘ │ │ |
| 65 | +│ │ BuilderApi trait: │ │ │ │ |
| 66 | +│ │ ┌─────────────────┐ │ │ SigningManager enum: │ │ |
| 67 | +│ │ │ get_header │ │ │ ┌── LocalManager │ │ |
| 68 | +│ │ │ get_status │ │ │ └── DirkManager │ │ |
| 69 | +│ │ │ submit_block │ │ │ │ │ |
| 70 | +│ │ │ register_val │ │ │ LocalManager: │ │ |
| 71 | +│ │ │ reload │ │ │ ┌── consensus keys │ │ |
| 72 | +│ │ │ extra_routes() │ │ │ └── proxy keys │ │ |
| 73 | +│ │ └─────────────────┘ │ │ │ │ |
| 74 | +│ │ │ │ Proxy store: │ │ |
| 75 | +│ │ Fan-out to N relays │ │ ┌── ERC2335 keystore │ │ |
| 76 | +│ │ Best bid selection │ │ └── raw file │ │ |
| 77 | +│ └───────────────────────┘ └───────────────────────┘ │ |
| 78 | +│ │ │ │ |
| 79 | +│ │ SignerClient │ JWT auth middleware │ |
| 80 | +│ │ (cb-common) │ rate limiter │ |
| 81 | +│ ▼ ▼ │ |
| 82 | +│ ┌────────────────────────────────────────────────────────┐ │ |
| 83 | +│ │ cb-common crate │ │ |
| 84 | +│ │ ┌──────────┬──────────┬──────────┬──────────────────┐ │ │ |
| 85 | +│ │ │ config/ │ pbs/ │ commit/ │ signer/ │ │ │ |
| 86 | +│ │ │ Config │ types │ client │ schemes (BLS/ECD) │ │ │ |
| 87 | +│ │ │ Mux │ relay │ request │ loader │ │ │ |
| 88 | +│ │ │ Module │ builder │ response │ store (ERC2335) │ │ │ |
| 89 | +│ │ │ Signer │ constants│ error │ types │ │ │ |
| 90 | +│ │ ├──────────┼──────────┼──────────┼──────────────────┤ │ │ |
| 91 | +│ │ │ interop/ │ types │ utils │ signature │ │ │ |
| 92 | +│ │ │ lido/ssv │ Chain │ JWT │ verify_signed_msg │ │ │ |
| 93 | +│ │ └──────────┴──────────┴──────────┴──────────────────┘ │ │ |
| 94 | +│ └────────────────────────────────────────────────────────┘ │ |
| 95 | +└─────────────────────────────────────────────────────────────────┘ |
| 96 | +
|
| 97 | +External: |
| 98 | + Beacon Node ──Builder API──▶ PBS Service |
| 99 | + PBS Service ──Builder API──▶ Relays (MEV-Boost) |
| 100 | + PBS Service ──Commit API───▶ Commit Modules (sidecars) |
| 101 | + Commit Modules ──Signer API─▶ Signer Service |
| 102 | + Signer Service ──gRPC──────▶ Dirk (optional remote signer) |
| 103 | +``` |
| 104 | + |
| 105 | +## Crate Responsibilities |
| 106 | + |
| 107 | +| Crate | Purpose | Key Public API | |
| 108 | +|-------|---------|---------------| |
| 109 | +| `cb-common` | Shared types, config, PBS types, signer types, commit client, interop | `Chain`, `PbsConfig`, `RelayClient`, `SignerClient`, `ModuleId`, `Jwt`, `get_header`, `submit_block` | |
| 110 | +| `cb-pbs` | PBS service: routes, MEV-Boost relay fan-out, state management | `PbsService`, `PbsState`, `BuilderApi` trait, `DefaultBuilderApi` | |
| 111 | +| `cb-signer` | Signer service: key management, signing endpoints, JWT auth | `SigningService`, `SigningManager`, `LocalSigningManager`, `DirkManager` | |
| 112 | +| `cb-metrics` | Prometheus metrics provider | `MetricsProvider` | |
| 113 | +| `cb-cli` | Docker compose init helper | `handle_docker_init` | |
| 114 | + |
| 115 | +## Data Flow: get_header Request |
| 116 | + |
| 117 | +``` |
| 118 | +Beacon Node |
| 119 | + │ GET /eth/v1/builder/header/{slot}/{parent_hash}/{pubkey} |
| 120 | + ▼ |
| 121 | +create_app_router (routes/router.rs) |
| 122 | + │ Match GET_HEADER_PATH → handle_get_header |
| 123 | + ▼ |
| 124 | +handle_get_header (routes/get_header.rs) |
| 125 | + │ Extract GetHeaderParams, req headers |
| 126 | + │ Look up state.mux_config_and_relays(pubkey) |
| 127 | + │ → returns (PbsConfig, &[RelayClient], Option<mux_id>) |
| 128 | + ▼ |
| 129 | +mev_boost::get_header (mev_boost/get_header.rs) |
| 130 | + │ For each relay: |
| 131 | + │ If timing_games: delay then poll at frequency |
| 132 | + │ If not: immediate request |
| 133 | + │ Track best bid by value |
| 134 | + │ Optional extra validation: check EL block validity |
| 135 | + │ Return best GetHeaderResponse or None (204) |
| 136 | + ▼ |
| 137 | +Response to Beacon Node |
| 138 | +``` |
| 139 | + |
| 140 | +## Key Configuration Flow |
| 141 | + |
| 142 | +``` |
| 143 | +config.example.toml / CB_CONFIG env |
| 144 | + │ |
| 145 | + ├── [chain] → Chain (Mainnet/Holesky/Sepolia/Hoodi/Custom) |
| 146 | + ├── [[relays]] → Vec<RelayConfig> → Vec<RelayClient> |
| 147 | + ├── [pbs] → StaticPbsConfig → PbsConfig |
| 148 | + ├── [[mux]] → PbsMuxes → HashMap<BlsPublicKey, RuntimeMuxConfig> |
| 149 | + ├── [[modules]] → Vec<StaticModuleConfig> → module Docker containers |
| 150 | + └── [signer] → SignerConfig → StartSignerConfig |
| 151 | +``` |
| 152 | + |
| 153 | +## Relationships |
| 154 | + |
| 155 | +- **PBS Service → Signer Service**: Uses `SignerClient` (from `cb-common`) to request signatures. Only when `with_signer = true` in PBS config. |
| 156 | +- **Commit Module → Signer Service**: Each module gets its own JWT. Calls signer endpoints for consensus/proxy BLS/ECDSA signatures. |
| 157 | +- **PBS Service → Relays**: Fans out Builder API calls. One HTTP client per relay. Timing games per relay. Mux routing per validator pubkey. |
| 158 | +- **Signer Service → Dirk**: Delegates consensus signing to Dirk gRPC backend. Proxy key generation still local. |
| 159 | +- **PBS Mux → Registry**: Lido CSM/module or SSV operator registries queried for validator pubkey lists. Auto-refresh for dynamic sets. |
| 160 | + |
| 161 | +## Flagged Ambiguities |
| 162 | + |
| 163 | +- **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. |
| 164 | +- **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. |
| 165 | +- **Custom chain support**: `Chain::Custom` allows any chain with genesis params. Some interop features (SSV) only support Mainnet/Holesky/Hoodi. |
| 166 | + |
| 167 | +## Example Dialogue |
| 168 | + |
| 169 | +**"How does a validator use Commit-Boost with MEV-Boost?"** |
| 170 | +→ 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. |
| 171 | + |
| 172 | +**"How do I add a preconfirmation module?"** |
| 173 | +→ 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. |
| 174 | + |
| 175 | +**"What is a mux and when do I need it?"** |
| 176 | +→ 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. |
0 commit comments