v0.11.0
v0.11.0 brings SSZ encoding to the Builder API path and adds opt-in WebSocket bid streaming
from relays. It bundles v0.11.0-rc1 to rc3 and includes everything shipped in v0.10.0 and
v0.10.1. Existing configs load unchanged, but read Behaviour changes before upgrading.
Highlights
SSZ for get_header and submit_blinded_block (#466, #467, #468, #481)
- PBS negotiates the response encoding with the beacon node through
Accept(q-values
respected) onget_headerand v1submit_blinded_block. With no preference it returns
JSON, and it returns406when neither SSZ nor JSON is acceptable. v2
submit_blinded_blockreturns an empty202, soAcceptis not enforced there. - Towards relays, PBS asks for SSZ first with JSON as the fallback. What the beacon node
receives is unaffected, because PBS validates every bid and re-encodes the winner to the
beacon node's preference. submit_blinded_blockis sent to relays as SSZ withEth-Consensus-Version, and is retried
as JSON only when a relay answers406or415.
WebSocket bid streaming (#483, #499)
- New per-relay option
get_header = "stream"(default"http") on[[relays]]and
[[mux.relays]]. PBS opens
ws(s)://<relay>/eth/v1/builder/header_stream/{slot}/{parent_hash}/{pubkey}, keeps the
latest bid until the request deadline or the stream closes, then validates it exactly like
an HTTP bid. - If the handshake fails with time left, PBS falls back to a normal HTTP
get_header. - Streaming relays typically require an
X-Api-Key(v4 UUID), set in the relay'sheaders.
Use the same key consistently for a given relay, since it is sent on every request to
that relay, includingregister_validator. - Stream attempts are recorded under
endpoint="get_header_stream", so slots served by the
HTTP fallback stay distinguishable. There are four new series:
relay_stream_connect_latency,relay_stream_updates,relay_stream_invalid_frames_total
andrelay_stream_fallback_total. - Docs: https://commit-boost.github.io/commit-boost-client/ (configuration, "Bid streaming").
Example config:
https://github.com/Commit-Boost/commit-boost-client/blob/main/examples/configs/pbs_bid_stream.toml
Relay headers from secret files or env vars (#498)
- Relay header values, such as API keys, can be loaded from a file or an environment variable:
headers = { X-Api-Key = { file = "/run/secrets/relay-key" } }or
headers = { X-Api-Key = { env = "RELAY_API_KEY" } }. Literal strings still work. - Values are re-read on every config reload, so a rotated secret is picked up without a
restart. Header values are marked sensitive and kept out of debug output. A secret-sourced
value logs only its source and a short fingerprint. commit-boost initmountsfilepaths read-only into the PBS container and passesenv
variables through. A relative or missing path failsinitup front.
Behaviour changes
- No more v2 → v1 fallback on
submit_blinded_block. A relay that returns 404 on the v2
endpoint now fails that submission instead of being retried on v1. It is logged and
counted incb_pbs_pbs_submit_block_v2_unsupported_total{relay_id}, and other relays can
still serve it (#468). - Error responses to the beacon node now use the Builder API JSON
ErrorMessageschema
instead of plain text (#482; fixes OffchainLabs/prysm#17136). - Relays now receive SSZ-first requests (see above). Relays without SSZ support get JSON as
before. - If dashboards or alerts filter on
endpoint="get_header", note that streaming relays now
report underendpoint="get_header_stream". HTTP relays and the HTTP fallback are
unchanged.
Fixes
- Custom chains now use their configured
fulu_fork_slot. v0.10.x used the slot duration in
its place, which could label a submitted block with the wrong fork when the beacon node
omittedEth-Consensus-Version. The fork of a submitted block is now always derived from
its slot (#487). - Relay refusals on
submit_blinded_blocklog the relay's own explanation, and the retry
count is logged on both the v1 and v2 paths (#502).
Security and dependencies
Also included (shipped in v0.10.0 / v0.10.1)
- Stader validator registry support for mux key loading (#465)
- Lido Curated Module v2 support (#489)
- Dirk signer TLS-provider panic fix (#480)
- SSV node operator ID sent as a numeric
uint64(#474) - Publish-age cooldown for dependency resolution and
--lockedbuilds (#492)
Credits
The SSZ work builds on the original SSZ builder flow by @eserilev (#252) and its port by
@jclapis (#403).