Skip to content

Honour the configured timeout when submitting validator registrations. - #432

Open
ThomasDalla wants to merge 1 commit into
attestantio:masterfrom
ThomasDalla:registration-timeout-honour-config
Open

Honour the configured timeout when submitting validator registrations.#432
ThomasDalla wants to merge 1 commit into
attestantio:masterfrom
ThomasDalla:registration-timeout-honour-config

Conversation

@ThomasDalla

Copy link
Copy Markdown

Validator registrations are submitted with a per-call timeout of one second per registration:

Common: builderapi.CommonOpts{
    Timeout: time.Second * time.Duration(len(providerRegistrations)),
},

The comment above it says the intent is to wait longer than usual, because some relays process
registrations sequentially. The per-call timeout cannot do that. go-builder-client builds each
relay's http.Client with Timeout: parameters.timeout — the value resolved from
builderclient.submitvalidatorregistrations, optionally overridden per relay — and
http.Client.Timeout is an absolute ceiling on the whole request, independent of any context
deadline. The per-call value is applied on top of that as a context deadline, so the effective
budget is min(configured, 1s × count). The formula can only ever shorten the deadline.

Two consequences:

  • builderclient.submitvalidatorregistrations.timeout is honoured for every other builder call
    and ignored for this one.
  • Any batch smaller than the configured timeout in seconds is capped below it. A single
    registration gets one second.

Measured against a httptest server that sleeps 4s, to confirm the direction of the clamp:

client timeout (configured) per-call Common.Timeout outcome
2s 10s aborted at 2.00s — the per-call value cannot raise the ceiling
10s 1s aborted at 1.00s — today's single-registration behaviour
10s 0 (unset) succeeded at 4.00s — the configured value applies

The case where this actually bites is the shared MEV-boost passthrough: registrations arriving at
/eth/v1/builder/validators are forwarded a handful at a time, so each submission gets 1–4
seconds. On a mainnet node forwarding for an SSV cluster I see a steady ~1% of submissions fail
with context deadline exceeded across five relays, concentrated on the slower ones — with the
configured timeout at 10s, which is never reached. The failures are invisible to the caller
(ValidatorRegistrations returns nil, nil regardless), so the only symptom is the log line.

This change leaves the per-call timeout unset so the configured timeout applies. Batches large
enough for the formula to exceed the configured value are unaffected — the client's own timeout
already clamped them — so the crossover is count == configured timeout in seconds, and the
periodic full-registration sweep keeps exactly the budget it has today.

The options construction is extracted into registrationOpts so the absence of a per-call
timeout can be asserted in a test; a future reinstatement of the formula then fails CI rather than
silently restoring a one-second deadline.

Validator registrations are submitted with a per-call timeout of one second
per registration.  The intent, per the comment, is to wait longer than usual
for large batches, but the per-call timeout cannot do this: go-builder-client
sets http.Client.Timeout from the configured timeout, which is a hard ceiling
on the request regardless of any context deadline, so the effective budget is
min(configured, 1s x count).  The formula can only ever shorten the deadline.

As a result builderclient.submitvalidatorregistrations.timeout, optionally
overridden per relay, is honoured for every other builder call and ignored
for this one.  Submissions of fewer registrations than the configured timeout
in seconds are capped below it: a single registration is given one second.
This is most visible to operators who share a relay setup through the
validator registrations endpoint, where registrations are forwarded a handful
at a time and relays that are slow to respond routinely miss the deadline.

Leave the per-call timeout unset so that the configured timeout applies.
Batches large enough for the formula to exceed the configured timeout are
unaffected, as the client's own timeout already clamped them.
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.

1 participant