Skip to content

[r3.6] docs(site): Caplin v3.6 block production, and correct the disk-storage claim - #23587

Merged
bloxster merged 5 commits into
release/3.6from
docs/v36-caplin-staking
Aug 27, 2026
Merged

[r3.6] docs(site): Caplin v3.6 block production, and correct the disk-storage claim#23587
bloxster merged 5 commits into
release/3.6from
docs/v36-caplin-staking

Conversation

@bloxster

@bloxster bloxster commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Two Caplin doc fixes for v3.6, both traced to code on release/3.6.

Block production (/staking/caplin) — the page had nothing on the v3.6 proposal path. Adds the three operator-visible changes:

  • Payload preparation one slot early, with its three preconditions, since the feature is silent when any is missing: the Beacon API validator namespace, a registered fee recipient, and Caplin driving the in-process execution layer. --caplin.use-engine-api switches Caplin to the Engine API, where StartPayloadBuild is unimplemented and preparation is skipped.
  • Fork-choice head published before the head-state copy, distinguishing endpoints that read the head block from those that read the head state.
  • Default graffiti. It names the proposing node's own connected execution and consensus clients — the value is written into the beacon body before the payload is chosen, so a winning external bid replaces only the execution side and leaves it unchanged. Also covers the two cases a staker hits: the execution half is absent while engine_getClientVersionV1 is still uncached, and a validator client that sets its own graffiti overrides the default. There is no graffiti CLI flag; the only override is the Beacon API graffiti query parameter, listed against all three validator block endpoints.

Disk storage (/fundamentals/caplin) — corrects the storage claim.

Bloxster added 2 commits August 26, 2026 11:03
The intro said Caplin "eliminates the need for separate disk storage",
while the same page documents <datadir>/caplin/indexing and Caplin
snapshots. Caplin does write to disk; every one of its directories is
built under the single Erigon datadir (db/datadir/dirs.go:119-128,
SnapDir = "snapshots" at :95). What it removes is a second client
process and a second datadir, not the storage.
Adds a "Block Production Behaviour" section to the Caplin staking page
for the three v3.6 changes an operator can see or act on.

Payload preparation (#23437): cl/beacon/handler/payload_preparation.go
:158 targets current slot + 1, :230-232 caps the lead at one slot, and
:112-127 gates the whole loop on the Beacon API `validator` namespace
(cl/beacon/beacon_router_configuration/cfg.go:66-67), on a registered
fee recipient (:175-178, :278), and on an engine implementing
PayloadBuilder. Only ExecutionClientDirect does
(cl/phase1/execution_client/execution_client_direct.go:152), so
--caplin.use-engine-api (cmd/utils/flags.go:930) selects
ExecutionClientEngineLocal (node/eth/backend.go:1019) and preparation
is skipped. Gloas/pre-Capella skips at :162-167; log lines at :137,
:329.

Fork-choice head before the state copy (#23172): published at
cl/phase1/forkchoice/get_head.go:113 via cl/phase1/stages/forkchoice.go
:42; the copy happens later at forkchoice.go:345 ->
cl/beacon/synced_data/synced_data.go:152-161. Read path
cl/beacon/handler/handler.go:499-509 still 503s while syncing.

Default graffiti (#22303): cl/beacon/handler/block_production.go:95-104
builds <EL code><EL commit><CN><CL commit>; codes and prefixes at
:83-85, :168-190; expected strings pinned in
block_production_graffiti_test.go:117-160. There is no graffiti CLI
flag anywhere in the tree; the only override is the `graffiti` query
parameter at :590-595, read as a 32-byte hex value.

Left out deliberately: the txpool deadlock fix (#23360) is a pure
locking change in txnprovider/txpool/pool.go with no flag, default or
metric, so there is nothing for an operator to do; and "boundary
attestations accepted while the head state lags" is not a v3.6 change —
it shipped in v3.5.1 via #22251.

llms-full.txt regenerated by docs/site/scripts/generate-llms.py.
…aims

`--caplin.use-engine-api` does not merely skip payload preparation: it
returns early from `setBeaconAPI`, so the whole Beacon API is disabled and
Caplin cannot stake at all in that mode. Framing the cost as a skipped
optimisation invited a staker to turn it on. It is also not silent — a
warning is logged when `--beacon.api` is set alongside it.

The debug fork-choice endpoint never read head state, so it was not
delayed by the state copy and gains nothing here; the endpoint that does
is `/eth/v2/debug/beacon/heads`.

The graffiti query parameter is honoured on the v2, v3 and v4 validator
block endpoints, and it is not validated: a malformed or empty value
yields an all-zero graffiti rather than falling back to the default.
@bloxster

Copy link
Copy Markdown
Collaborator Author

Corrected in bde8111 after an adversarial re-check of the claims against release/3.6.

Two of them were wrong, one materially:

  • --caplin.use-engine-api does far more than skip payload preparation. setBeaconAPI (cmd/utils/flags.go:1803-1806) returns early when the flag is set, so the entire Beacon API is disabled — no validator namespace, no block production, no duties. Caplin cannot stake in that mode at all. Describing the cost as a silently skipped optimisation invited a staker to enable it. It is also not silent: a warning is logged when --beacon.api is passed alongside it.
  • The debug fork-choice endpoint was the wrong endpoint. /eth/v1/debug/fork_choice (cl/beacon/handler/forkchoice.go:47-59) reads the fork-choice store directly and never touches head state, so it was never delayed by the state copy and gains nothing from this change. The endpoint that does benefit is /eth/v2/debug/beacon/heads.
  • Graffiti, two omissions: the graffiti query parameter is honoured on the v2, v3 and v4 validator block endpoints (all route to the same handler), and the value is not validatedcommon.HexToHash swallows decode errors, so a malformed or empty value silently yields an all-zero graffiti instead of falling back to the default. Short values are left-padded, long ones cropped from the left.

What held up on re-check: the three Since v3.6 attributions are each genuinely new in 3.6 (the 3.5 series had a fixed "Caplin" graffiti, and neither payload_preparation.go nor publishSelectedHead exists on release/3.5); both log strings match the source character for character; the one-slot lead and the no-fork-choice-alteration claim are both correct, the latter enforced by a strict mock with no ForkChoiceUpdate expectation.

One nuance worth recording: payload preparation and the fork-choice publish are not in v3.6.0-rc.1 — an operator on rc.1 grepping for PayloadPreparation: will find nothing.

npm run build green, --check green on all four artifacts at 73 pages.

@bloxster
bloxster marked this pull request as draft August 26, 2026 11:06
@bloxster
bloxster requested a lite review from Copilot August 26, 2026 11:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Updates Caplin documentation for the v3.6 release line, focusing on operator-visible block production behavior changes and correcting an inaccurate “no disk storage” claim. This fits into the docs site’s Caplin fundamentals and staking guidance, and updates the pre-rendered llms-full.txt artifacts accordingly.

Changes:

  • Replace marketing-style Caplin intro text with an accurate description of process/datadir unification while clarifying that Caplin still writes to disk (indexing DB + snapshots + related subdirs).
  • Add a “Block Production Behaviour” section documenting v3.6 proposal-path behavior: one-slot-ahead payload preparation (with real preconditions), earlier fork-choice head publication, and default client-pair graffiti behavior/overrides.
  • Mirror these doc updates into the llms-full.txt and docs/site/static/llms-full.txt artifacts.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
llms-full.txt Updates embedded docs snapshots: Caplin fundamentals intro + new v3.6 block production behavior section.
docs/site/static/llms-full.txt Same as llms-full.txt, for the docs site’s static bundle.
docs/site/docs/staking/caplin.md Adds v3.6 block production behavior documentation (payload prep, head publication timing, default graffiti).
docs/site/docs/fundamentals/caplin.md Corrects Caplin “disk storage” claim and replaces marketing prose with accurate storage/process statements.
Suppressed comments (3)

docs/site/docs/staking/caplin.md:110

  • The endpoint list is a bit ambiguous as written (it reads like "/eth/v4 /validator/blocks/{slot}"). Spell out the full paths to avoid confusion.
There is no CLI flag for graffiti. The only way to override it is per block, through the Beacon API: a validator client that sends a `graffiti` query parameter on the validator block-production endpoints (`GET /eth/v2`, `/eth/v3` or `/eth/v4` `/validator/blocks/{slot}`) has its value used instead of the default. The parameter is read as a 32-byte hex value, as the Beacon API specification requires. It is not validated: a malformed or empty value is not rejected and does not fall back to the default — it silently produces an all-zero graffiti. A shorter hex value is left-padded with zeros, and a longer one is cropped from the left. Note that a validator client which sets graffiti by default — including its own client string — overrides Caplin's default; to get the client-pair graffiti, leave the validator client's graffiti unset.

llms-full.txt:7726

  • The endpoint list is a bit ambiguous as written (it reads like "/eth/v4 /validator/blocks/{slot}"). Spell out the full paths to avoid confusion.
There is no CLI flag for graffiti. The only way to override it is per block, through the Beacon API: a validator client that sends a `graffiti` query parameter on the validator block-production endpoints (`GET /eth/v2`, `/eth/v3` or `/eth/v4` `/validator/blocks/{slot}`) has its value used instead of the default. The parameter is read as a 32-byte hex value, as the Beacon API specification requires. It is not validated: a malformed or empty value is not rejected and does not fall back to the default — it silently produces an all-zero graffiti. A shorter hex value is left-padded with zeros, and a longer one is cropped from the left. Note that a validator client which sets graffiti by default — including its own client string — overrides Caplin's default; to get the client-pair graffiti, leave the validator client's graffiti unset.

docs/site/static/llms-full.txt:7726

  • The endpoint list is a bit ambiguous as written (it reads like "/eth/v4 /validator/blocks/{slot}"). Spell out the full paths to avoid confusion.
There is no CLI flag for graffiti. The only way to override it is per block, through the Beacon API: a validator client that sends a `graffiti` query parameter on the validator block-production endpoints (`GET /eth/v2`, `/eth/v3` or `/eth/v4` `/validator/blocks/{slot}`) has its value used instead of the default. The parameter is read as a 32-byte hex value, as the Beacon API specification requires. It is not validated: a malformed or empty value is not rejected and does not fall back to the default — it silently produces an all-zero graffiti. A shorter hex value is left-padded with zeros, and a longer one is cropped from the left. Note that a validator client which sets graffiti by default — including its own client string — overrides Caplin's default; to get the client-pair graffiti, leave the validator client's graffiti unset.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/site/docs/staking/caplin.md Outdated
Comment thread llms-full.txt Outdated
Comment thread docs/site/static/llms-full.txt Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread docs/site/docs/staking/caplin.md Outdated
…a sentence

The graffiti override listed the endpoint versions and the path separately,
which read as two paths rather than three versions of one. Each is now
written in full, and the deprecated v2 route is marked as such.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@bloxster
bloxster marked this pull request as ready for review August 26, 2026 11:50
@yperbasis
yperbasis requested review from domiwei and lystopad August 26, 2026 13:40

@yperbasis yperbasis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One attribution claim is inaccurate when an external builder wins. Please update it before merge.

Comment thread docs/site/docs/staking/caplin.md Outdated
@bloxster bloxster changed the title docs(site): Caplin v3.6 block production, and correct the disk-storage claim [r3.6] docs(site): Caplin v3.6 block production, and correct the disk-storage claim Aug 27, 2026
…ad builder

defaultGraffiti reads the locally connected execution client. When an
external builder's bid wins, produceBlock blinds the already-built beacon
body and swaps in the builder's execution header, so that graffiti still
names the proposing node's own clients.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

@bloxster
bloxster added this pull request to the merge queue Aug 27, 2026
Merged via the queue into release/3.6 with commit cc7460b Aug 27, 2026
24 checks passed
@bloxster
bloxster deleted the docs/v36-caplin-staking branch August 27, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants