Skip to content

Rewrite get_header relay communication to support SSZ and JSON#467

Open
JasonVranek wants to merge 7 commits into
mainfrom
pr/ssz-routes
Open

Rewrite get_header relay communication to support SSZ and JSON#467
JasonVranek wants to merge 7 commits into
mainfrom
pr/ssz-routes

Conversation

@JasonVranek

Copy link
Copy Markdown
Collaborator

Summary

Rewrites get_header relay communication to support both SSZ and JSON content negotiation.

What's in this PR

  • SSZ and JSON encoding/decoding for relay get_header responses
  • Content-Type and Eth-Consensus-Version header parsing on relay responses
  • Accept header forwarding to relays with q-value ordering
  • MIME parameter tolerance on relay response Content-Type
  • Fork-aware response decoding for all supported forks
  • Updated mock relay and mock validator with SSZ support
  • Dynamic port allocation in tests via get_free_listener (eliminates flaky CI from port collisions)
  • Get_header integration tests covering both encodings
  • Per-fork JSON fixture files for test data

Review notes

The route handler always takes the standard validation path in this PR. Configurable validation modes come in PR 4.

The test infrastructure changes (mock relay SSZ support, dynamic ports) are shared by both get_header and submit_block tests.

Part 2 of 4: SSZ types → get_header → submit_block → validation bypassing

Attribution

This work builds on the SSZ builder flow originally implemented by @eserilev
in #252 and ported to the current codebase by @jclapis in #403.

Co-authored-by: Eitan Seri-Levi eserilev@ucsc.edu
Co-authored-by: Joe Clapis jclapis@outlook.com

Base automatically changed from pr/ssz-core to main June 1, 2026 17:26
@JasonVranek JasonVranek requested a review from a team June 1, 2026 17:26
@JasonVranek JasonVranek force-pushed the pr/ssz-routes branch 2 times, most recently from c800921 to cbf451d Compare June 2, 2026 03:30
Comment thread crates/pbs/src/mev_boost/get_header.rs Outdated
Comment thread crates/pbs/src/mev_boost/get_header.rs Outdated
Comment thread crates/pbs/src/mev_boost/get_header.rs Outdated
Comment thread crates/pbs/src/mev_boost/get_header.rs Outdated
Comment thread tests/src/mock_relay.rs
Comment thread crates/pbs/src/mev_boost/get_header.rs Outdated
Comment thread crates/pbs/src/mev_boost/get_header.rs Outdated
Comment thread crates/pbs/src/mev_boost/get_header.rs Outdated
Comment thread crates/common/src/wire.rs Outdated
Comment thread crates/common/src/wire.rs
Comment thread crates/pbs/src/mev_boost/get_header.rs Outdated
Comment thread crates/common/src/wire.rs
Comment thread crates/pbs/src/mev_boost/get_header.rs Outdated
Comment thread crates/pbs/src/error.rs Outdated
PbsClientError::NoPayload => StatusCode::BAD_GATEWAY,
PbsClientError::Internal => StatusCode::INTERNAL_SERVER_ERROR,
PbsClientError::DecodeError(_) => StatusCode::BAD_REQUEST,
PbsClientError::HeaderError(_) => StatusCode::BAD_REQUEST,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a test saying that it can return 406. I'd change either of them to match

/// An Accept header containing only q=0 for every supported type is a
/// deliberate "I accept nothing" and must error (so the route can return
/// 406 Not Acceptable per RFC 7231 §5.3.1 and §6.5.6).

Comment thread crates/pbs/src/mev_boost/get_header.rs Outdated
// Create the Accept headers for requests
// Use the documented, deterministic preference:
// SSZ first (wire-efficient), JSON fallback.
send_headers.insert(ACCEPT, HeaderValue::from_static(OUTBOUND_ACCEPT));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make sure, in the description you mention that headers are forwarded to the relay but here we are hardcoding the accept. Is this behaviour expected?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Furthermore, we have this function that seems to do the job, but it's never used anywhere

/// Build an `Accept` header string that mirrors the caller's preference order
/// so the relay sees the same priority the beacon node asked us for. Each
/// subsequent entry receives a q-value 0.1 lower than the previous one,
/// starting at 1.0.
pub fn build_outbound_accept(preferred: AcceptedEncodings) -> String {

Introduce EncodingType, AcceptedEncodings, and content negotiation
primitives for SSZ support in the PBS pipeline. Includes:

- EncodingType enum with FromStr/Display and MIME param tolerance
- AcceptedEncodings with q-value aware Accept header parsing
- SSZ bid value extraction from SignedBuilderBid by fork
- deserialize_body and parse_response_encoding_and_fork helpers
- Per-fork type aliases for BuilderBid and ExecutionPayloadHeader
- SszValueError, PbsError::GeneralRequest, PbsClientError variants
- Comprehensive unit tests for all new types and helpers
- New deps: headers-accept, mediatype
content negotiation. Includes:

- SSZ and JSON encoding/decoding for relay get_header responses
- Content-Type and Eth-Consensus-Version header parsing
- Accept header forwarding to relays with q-value ordering
- MIME parameter tolerance on relay response Content-Type
- Fork-aware SSZ bid value extraction for all supported forks
- Mock relay and validator SSZ support in test infrastructure
- get_header integration tests for both encodings
- Dynamic port allocation in tests via get_free_listener
responses often carry text/plain; charset=utf-8 Content-Type,
which failed parse_response_encoding_and_fork with "unsupported encoding
type".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants