Skip to content

spectest alpha 12 compliance (spec pin bump and assorted fix commits) - #17310

Open
kasey wants to merge 14 commits into
local-spectest-refactorsfrom
spectest-alpha-12-compliance
Open

spectest alpha 12 compliance (spec pin bump and assorted fix commits)#17310
kasey wants to merge 14 commits into
local-spectest-refactorsfrom
spectest-alpha-12-compliance

Conversation

@kasey

@kasey kasey commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Gloas devnet-7 spec update: progressive merkleization on by default, builder config alignment, attestation parent-slot fixes

Part of the gloas-devnet-7 stacked series; based on local-spectest-refactors, diff shown against it.

This PR moves the consensus spec test pin from v1.7.0-alpha.11 to v1.7.0-alpha.12 and lands everything needed to pass against those fixtures. Two spec changes drive the bulk of the diff. First, the alpha.13 fixtures merkleize Gloas containers per EIP-7688, so progressive merkleization can no longer be an off-by-default experiment: the annotations are added to the Gloas types and the codegen/runtime defaults are inverted so that progressive is what you get unless you explicitly opt out. The rest is Gloas builder work: three config/preset values move to their current spec values, the builder withdrawal credential prefix is corrected and then actually enforced on deposit requests, and a builder could previously defer its own withdrawal indefinitely by topping itself up.

Spec test pin

WORKSPACE: consensus_spec_version v1.7.0-alpha.11v1.7.0-alpha.12, with new fixture hashes for the general/minimal/mainnet flavors and a new integrity hash for the consensus-specs source tarball.

Progressive merkleization (EIP-7688) becomes the default

Type annotations

proto/prysm/v1alpha1/gloas.yaml and proto/engine/v1/engine.yaml mark the containers and collections that EIP-7688 makes progressive:

  • Progressive containers with progressive field lists: BeaconStateGloas (validators, balances, both participation lists, inactivity scores, pending deposits/partial withdrawals/consolidations, builders, builder pending withdrawals, payload expected withdrawals), BeaconBlockBodyGloas (all operation lists plus payload attestations), AttestationGloas (AggregationBits as ProgressiveBitlist), IndexedAttestationGloas (AttestingIndices), ExecutionPayloadBid (BlobKzgCommitments), ExecutionPayloadGloas (transactions as a progressive list of progressive byte lists, withdrawals, block access list), and ExecutionRequestsGloas (all five request lists).
  • Progressive containers with no list fields: ExecutionPayloadEnvelope, PayloadAttestation.
  • DataColumnSidecarGloas gets progressive Column and KzgProofs lists but stays a standard container.
  • The base ExecutionRequests message is deliberately left alone, with a comment explaining why: it is the electra/fulu type, and annotating it would leak progressive merkleization into pre-Gloas forks. Gloas uses the separate ExecutionRequestsGloas message.

Default flip: codegen, Bazel, feature flag

  • build/gen/ssz.go: progressive generation now defaults to on. SSZ_PROGRESSIVE=0 generates the bounded form (previously the default was off and SSZ_PROGRESSIVE=1 opted in).
  • .bazelrc: comment documenting that progressive is the build default and that --//tools:disable_progressive_merkleization switches to the bounded form. The bool_flag default in //tools already had progressive enabled; no rule change was needed.
  • Flag inversion: the hidden --enable-progressive-ssz flag becomes --disable-progressive-ssz, and features.Flags.EnableProgressiveSSZ becomes DisableProgressiveSSZ. features.ProgressiveSSZEnabled(version) is now version >= Gloas && !DisableProgressiveSSZ. The flag usage string calls it an escape hatch for debugging, since Gloas mandates progressive merkleization.
  • Two call sites that read the raw flag now go through features.ProgressiveSSZEnabled so the version gate is applied consistently: beacon-chain/light-client/lightclient.go (progressiveExecutionPayloadSSZEnabled) and consensus-types/blocks/proofs.go (blockBodyListRoot).

Regenerated SSZ

proto/prysm/v1alpha1/gloas{,.minimal}.ssz.go and proto/engine/v1/engine{,.minimal}.ssz.go are regenerated: annotated types now expose ProgressiveHashTreeRoot/ProgressiveHashTreeRootWith (with HashTreeRoot delegating to them), merkleize via MerkleizeProgressiveWithActiveFields / MerkleizeProgressiveWithMixin, and use PutProgressiveBitlist / ValidateProgressiveBitlist. The bounded ErrListTooBig and ValidateBitlist checks are dropped from marshal, unmarshal, and hashing.

Note the commit split: deb157079c inverts the config and tests, and 8cf24656ad commits the regenerated output, so the generated code does not match the toolchain at the intermediate commit.

Length checks SSZ no longer provides

Because the progressive types no longer carry list limits, ApplyParentExecutionPayload now asserts the per-payload maxima explicitly via a new validateExecutionRequestLengths (withdrawal requests, consolidations, builder deposits, builder exits), matching apply_parent_execution_payload in the spec.

Config and preset changes

Applied to both config/params/mainnet_config.go and, where relevant, config/params/minimal_config.go:

Value Before After
BUILDER_WITHDRAWAL_PREFIX 0x03 0xB0 (mainnet and minimal)
MIN_BUILDER_WITHDRAWABILITY_DELAY 8192 epochs 64 epochs
MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD 256 (2**8) 64 (2**6)
PAYLOAD_DUE_BPS 7500 5000 (mainnet and minimal)

0x03 collided with the range reserved for future credential types. The withdrawability delay change keeps an exiting builder's funds from being locked for an impractically long window. PAYLOAD_DUE_BPS at 5000 moves the payload deadline to the slot midpoint so builders reveal earlier and the PTC has more time to attest to timeliness; that commit notes config/params TestLoadConfigFile depends on the pinned consensus-spec config fixture, which is why it needs the spec test pin bump that is included in this same PR.

Builder deposit and withdrawal handling

  • Prefix enforcement (beacon-chain/core/gloas/builder_deposit_request.go): builder deposit requests whose withdrawal credentials lack BUILDER_WITHDRAWAL_PREFIX are now ignored, both when batching new registrations in ProcessBuilderDepositRequests and in processBuilderDepositRequest. Such deposits are dropped and the funds are lost, per spec.
  • Builder version (beacon-chain/state/state-native/setters_gloas.go): AddBuilderFromDeposit registers new builders with PAYLOAD_BUILDER_VERSION instead of echoing withdrawalCredentials[0], so a depositor can no longer influence the stored version.
  • Top-up no longer defers withdrawal: an exited builder's WithdrawableEpoch was pushed out on every top-up, letting a builder with a pending balance defer its own withdrawal indefinitely. The reset now requires Balance == 0 (actually swept) in addition to being exited, and is evaluated before the top-up is credited so the new deposit cannot mask a zero balance. A nil builder at a known index now returns an error rather than being dereferenced.
  • Deposit request bound removed (proto/engine/v1/electra.go): Gloas drops MAX_DEPOSIT_REQUESTS_PER_PAYLOAD — the execution layer bounds deposit requests through the block gas limit — so decodeExecutionRequestListGloas raises limits.Deposits to the size-derived maximum. Covered by the new TestGetDecodedExecutionRequestsGloas_NoDepositLimit; TestEmptyExecutionRequestsGloasHashTreeRoot is also added.

Spec test runner changes

  • testing/spectest/shared/gloas/ssz_static/ssz_static.go: the PROGRESSIVE_SSZ env override now clears DisableProgressiveSSZ rather than setting the old enable flag; the comment is updated for the inverted default.
  • execution_payload_bid.go adapts to the new ProcessExecutionPayloadBid signature.
  • New forkchoice tests: TestForkChoice_InsertNode_LateBlockNotRecorded covers the new gate, and TestForkChoice_InsertNode_RecordsFirstSeen now sets a genesis time so the inserted block lands in the current slot.

Behavior notes

  • The alpha.12 process_operations pseudocode adds EIP-7688 length asserts on the block body's operation lists (proposer slashings, attester slashings, attestations, voluntary exits, BLS-to-execution changes, payload attestations). Those asserts are recorded in the spec comment but not yet mirrored in gloasOperations; the analogous checks for the execution request lists are implemented here in ApplyParentExecutionPayload. Worth a follow-up now that the progressive SSZ types no longer bound those lists.
  • Running Gloas ssz_static against progressive fixtures still needs PROGRESSIVE_SSZ=1 to align the native-state root with the generated one; the runtime feature gate and the codegen flag remain independent.

Commits

  • 37b4e29a5d Move spectests to v1.7.0-alpha.13
  • 72766adaf8 Annotate gloas types for progressive container and field merkleization
  • deb157079c Invert config and tests to expect progressive merkleization on by default
  • 8cf24656ad Commit updated methodical codegen with progressive merkleization flipped to default-on
  • 56542829cb Enforce BUILDER_WITHDRAWAL_PREFIX on builder deposit requests
  • c7adc00b9d Reset builder withdrawable epoch on top-up only once swept
  • a9ad3dff90 Remove the deposit request bound on Gloas request decoding
  • 4f17def149 Set BUILDER_WITHDRAWAL_PREFIX to 0xB0
  • 2afb3af875 Reduce Gloas builder config bounds
  • 1c2bd3af27 Set PAYLOAD_DUE_BPS to 5000
  • 126cc7d308 Pass the parent slot to Gloas attestation processing
  • ca26f14da7 Only record early blocks as Gloas equivocation candidates

Acknowledgements

  • I have read CONTRIBUTING.md.
  • I have included a uniquely named changelog fragment file.
  • I have added a description with sufficient context for reviewers to understand this PR.
  • I have tested that my changes work as expected and I added a testing plan to the PR description (if applicable).

Stack created with GitHub Stacks CLIGive Feedback 💬

@kasey kasey changed the title spectest alpha 12 compliance (spec bin bump and assorted fix commits) spectest alpha 12 compliance (spec pin bump and assorted fix commits) Aug 5, 2026
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from 65b033a to c753de8 Compare August 5, 2026 20:57
@kasey
kasey force-pushed the local-spectest-refactors branch from e6f59b0 to 0bb7aa1 Compare August 5, 2026 20:57
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from c753de8 to a719bf5 Compare August 5, 2026 21:08
@kasey
kasey force-pushed the local-spectest-refactors branch from 0bb7aa1 to 7c3e3c2 Compare August 5, 2026 21:08
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from a719bf5 to d38b15f Compare August 5, 2026 21:13
@kasey
kasey force-pushed the local-spectest-refactors branch 2 times, most recently from 68dcf4b to 9de1e3f Compare August 5, 2026 21:16
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch 2 times, most recently from 50ebff4 to 6309ceb Compare August 5, 2026 21:18
@kasey
kasey force-pushed the local-spectest-refactors branch from 9de1e3f to 5ef6291 Compare August 5, 2026 21:18
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from 6309ceb to 5fb8e30 Compare August 5, 2026 22:00
@kasey
kasey force-pushed the local-spectest-refactors branch from 5ef6291 to bc34380 Compare August 5, 2026 22:00
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from 5fb8e30 to 0bcbabb Compare August 6, 2026 01:12
@kasey
kasey force-pushed the local-spectest-refactors branch 2 times, most recently from 66c0cfa to e77427a Compare August 6, 2026 01:31
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from 0bcbabb to f389084 Compare August 6, 2026 01:31
@kasey
kasey force-pushed the local-spectest-refactors branch from e77427a to 159e1ac Compare August 6, 2026 05:25
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch 2 times, most recently from d4f6ac6 to 81641a7 Compare August 6, 2026 05:41
@kasey
kasey force-pushed the local-spectest-refactors branch from 159e1ac to 1b96281 Compare August 6, 2026 05:41
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from 81641a7 to 7bdbab9 Compare August 6, 2026 05:49
@kasey
kasey force-pushed the local-spectest-refactors branch from 1b96281 to 33833a1 Compare August 6, 2026 05:49
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch 3 times, most recently from 821840a to fbb1b4c Compare August 6, 2026 08:32
@kasey
kasey force-pushed the local-spectest-refactors branch from 4a6e4ef to c592869 Compare August 6, 2026 13:27
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from fbb1b4c to 34579ea Compare August 6, 2026 13:27
@kasey
kasey force-pushed the local-spectest-refactors branch from c592869 to 49ac6e9 Compare August 6, 2026 17:25
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from 34579ea to d8319b2 Compare August 6, 2026 17:26
set.Bool(DisableProgressiveSSZ.Name, false, "test")
require.NoError(t, set.Set(DisableProgressiveSSZ.Name, "true"))
require.NoError(t, ConfigureBeaconChain(ctx))
assert.Equal(t, true, Get().DisableProgressiveSSZ)

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.

the old test had defer Init(&Flags{}) w/o it this leaves DisableProgressiveSSZ=true in the package global config for whatever test runs after this one

Comment on lines +31 to +37
// # [New in Gloas:EIP7688]
// assert len(body.proposer_slashings) <= MAX_PROPOSER_SLASHINGS
// assert len(body.attester_slashings) <= MAX_ATTESTER_SLASHINGS_ELECTRA
// assert len(body.attestations) <= MAX_ATTESTATIONS_ELECTRA
// assert len(body.voluntary_exits) <= MAX_VOLUNTARY_EXITS
// assert len(body.bls_to_execution_changes) <= MAX_BLS_TO_EXECUTION_CHANGES
// assert len(body.payload_attestations) <= MAX_PAYLOAD_ATTESTATIONS

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.

we dont need these assertions because ssz unmarshal would have failed earlier right?

@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from d8319b2 to 1e7be40 Compare August 7, 2026 20:00
@kasey
kasey force-pushed the local-spectest-refactors branch from 49ac6e9 to 0d8a5ee Compare August 7, 2026 20:00
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from 1e7be40 to 8ca31d6 Compare August 11, 2026 14:29
@kasey
kasey force-pushed the local-spectest-refactors branch from 0d8a5ee to a10e16d Compare August 11, 2026 14:29
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from 8ca31d6 to 730446a Compare August 11, 2026 19:34
@kasey
kasey force-pushed the local-spectest-refactors branch from a10e16d to 71436f8 Compare August 11, 2026 19:34
kasey and others added 14 commits August 12, 2026 15:31
Marks the Gloas containers and collections that EIP-7688 makes
progressive: the beacon state, block body, attestation and its aggregate
wrappers, the payload bid and envelope, the Gloas execution payload and
execution requests, and the data column sidecar.

Generation stays gated off by default, so this commit changes no generated
code: the emitted hash tree roots still match the pinned spectest
fixtures. Building with --//tools:disable_progressive_merkleization=false,
or regenerating with SSZ_PROGRESSIVE=1, switches the annotated types over
to ProgressiveHashTreeRoot and the progressive collection validators.
…ault

Note: the generated code is modified in the following commit, so at this commit
the generated code does not match the output of the build toolchain.
Ignore builder deposit requests whose withdrawal credentials do not
carry BUILDER_WITHDRAWAL_PREFIX, both when batching new registrations
and when processing an individual request. Such deposits are dropped and
the funds are lost, matching the spec.

Register new builders with PAYLOAD_BUILDER_VERSION rather than echoing
the first credential byte, so the stored version cannot be influenced by
the depositor.
An exited builder's withdrawable epoch was pushed out on every top-up,
which let a builder with a pending balance defer its own withdrawal
indefinitely. Only reset when the builder has actually been swept, and
evaluate that before crediting the top-up so the new deposit does not
mask a zero balance.

Also guard against a nil builder at a known index rather than
dereferencing it.
Gloas drops MAX_DEPOSIT_REQUESTS_PER_PAYLOAD; the execution layer bounds
deposit requests through the block gas limit instead. Lift the cap in the
Gloas request list decoder.

The remaining per-payload maxima (withdrawals, consolidations, builder
deposits and builder exits) are still consensus checks, so assert them
explicitly in ApplyParentExecutionPayload rather than relying on the SSZ
list limits, which no longer bound the progressive types.
Align the builder withdrawal credential prefix with the Gloas spec value
of 0xB0 in both the mainnet and minimal configs. It was previously 0x03,
which collided with the range reserved for future credential types.
Lower MIN_BUILDER_WITHDRAWABILITY_DELAY from 8192 to 64 epochs so an
exiting builder's funds are not locked for an impractically long window,
and lower MAX_BUILDER_DEPOSIT_REQUESTS_PER_PAYLOAD from 2**8 to 2**6 to
match the current Gloas spec.
Move the payload deadline to the midpoint of the slot so builders have
to reveal earlier, giving the PTC more time to attest to timeliness.

Note: config/params TestLoadConfigFile now diverges from the pinned
consensus-spec fixture, which still carries PAYLOAD_DUE_BPS 7500. This
needs the spec test pin to advance before it can merge to develop.
@kasey
kasey force-pushed the local-spectest-refactors branch from 71436f8 to a676232 Compare August 12, 2026 20:32
@kasey
kasey force-pushed the spectest-alpha-12-compliance branch from 730446a to 9a4debc Compare August 12, 2026 20:32
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