Skip to content

[r3.6] cl/beacon: resolve payload withdrawals in one place - #23339

Merged
lystopad merged 1 commit into
release/3.6from
feature/lystopad/cp-23280-to-3.6
Aug 17, 2026
Merged

[r3.6] cl/beacon: resolve payload withdrawals in one place#23339
lystopad merged 1 commit into
release/3.6from
feature/lystopad/cp-23280-to-3.6

Conversation

@lystopad

Copy link
Copy Markdown
Member

Cherry-pick of #23280 to release/3.6. Depends on #23320, which is already on this branch.

r3.6-specific adaptations

One conflict, of the same shape as the earlier backports in this series: produceBeaconBody selects the withdrawal source with an if/else if/else chain here, where main uses a switch. The change replaces that block with the new resolver either way, so the resolution was to take it.

I verified the result by diffing the change this branch introduces against the change #23280 introduces: the only differences are in the removed lines, which are the two shapes of the same inline block. Every added line is identical.

Behaviour change carried over

The refactor is behaviour-neutral, but the version-aware attributes constructor also fixes two cases where the old inline construction built a request the chosen wire version cannot express:

  • the parent beacon block root is not populated below Deneb, where forkchoiceUpdatedV1/V2 reject it;
  • withdrawals are not populated below Capella, where forkchoiceUpdatedV1 has no such field.

Both only bite on the engine transport, and both made the request fail rather than be ignored.

Part of backporting the series that split #23105.

Split out of #23105, which grew too large to review in one piece.

`produceBeaconBody` chose between three withdrawal sources inline — a
Gloas head whose payload was revealed, a Gloas head whose payload was
not, and everything before Gloas — each with its own hand-written
conversion loop, and then assembled the payload attributes around
whichever it picked.

The choice is now a method that names what it selects between, and the
attributes come from a single version-aware constructor. What is left
inline is the genuinely fork-specific part: the two fields only Gloas
sends. The three conversion loops go through the shared converter from
hand-written when reviewing that PR.

The refactor itself is behaviour-neutral, but the constructor also fixes
two cases where the old inline construction built a request the chosen
wire version cannot express:

- **the parent beacon block root is omitted below Deneb** — Capella and
Bellatrix dispatch to `forkchoiceUpdatedV2`/`V1`, and
`validatePayloadAttributesPreFCU` rejects a non-nil parent root there
with `InvalidPayloadAttributesErr`;
- **withdrawals are omitted below Capella** — Bellatrix dispatches to
`forkchoiceUpdatedV1`, which has no withdrawals field, and the
expectation is a non-nil empty slice, so one was being sent.

Both only bite on the engine transport, and both made the request fail
rather than be ignored.

The routing is otherwise unchanged, including the details that are easy
to lose in a refactor:

- a FULL Gloas head reads from the state copy with the parent payload
applied, not from the head state;
- an EMPTY Gloas head reads the expectation the state already cached,
and does not compute a fresh one;
- before Gloas the expectation is computed from the head state;
- the resulting slice keeps its nil-ness in every case.

`TestExpectedWithdrawalsReadsTheRightSourcePerFork` gives the two Gloas
states different withdrawal outcomes, so it fails if the source
selection is removed rather than passing either way.
`TestPayloadAttributesOmitFieldsTheChosenVersionCannotCarry` pins the
two gates across every fork.

Part of a series splitting #23105.

(cherry picked from commit af897d9)
@lystopad lystopad self-assigned this Aug 17, 2026
@lystopad
lystopad enabled auto-merge August 17, 2026 10:32
@lystopad
lystopad requested a review from yperbasis August 17, 2026 10:33
@lystopad lystopad added this to the 3.6.0 milestone Aug 17, 2026
@lystopad
lystopad added this pull request to the merge queue Aug 17, 2026
Merged via the queue into release/3.6 with commit 74e8ebd Aug 17, 2026
94 checks passed
@lystopad
lystopad deleted the feature/lystopad/cp-23280-to-3.6 branch August 17, 2026 12:30
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.

2 participants