Skip to content

Conversation

@StefanBratanov
Copy link
Contributor

@StefanBratanov StefanBratanov commented Jan 6, 2026

PR Description

As per ethereum/consensus-specs#4788

Also enabling back al the Gloas consensus-specs reference tests from: https://github.com/ethereum/consensus-specs/releases/tag/v1.7.0-alpha.1

The major change TLDR is that we track builders in the state separate from validators and process their deposits/withdrawals separate

Fixed Issue(s)

N/A

Documentation

  • I thought about documentation and added the doc-change-required label to this PR if updates are required.

Changelog

  • I thought about adding a changelog entry, and added one if I deemed necessary.

Note

Implements builders as non-validating staked actors and aligns with consensus-specs v1.7.0-alpha.1.

  • Add Builder SSZ container and registry in BeaconState with caches (buildersPubKeys, builderIndexCache); add next_withdrawal_builder_index and payload_expected_withdrawals
  • Replace validator-based builder fields with BuilderIndex (incl. BUILDER_INDEX_SELF_BUILD), update ExecutionPayloadBid/Envelope and signature checks to use builder pubkeys; special handling for self-builds
  • Rework withdrawals: queue/process builder pending withdrawals and a builders sweep; apply withdrawals to builder balances; advance next_withdrawal_* indices; extend ExpectedWithdrawals
  • Handle deposits for builders immediately and add builder exits (initiateBuilderExit); map builder/validator indices via new helpers
  • Update predicates/accessors/mutators for builders (balance checks, active status, index/pubkey lookups); adjust SSZ schemas (Builder.version uint8; remove withdrawable_epoch from BuilderPendingWithdrawal)
  • Enable Gloas ssz_*, fork-choice tests; update test fixtures/utilities to use BUILDER_INDEX_SELF_BUILD; bump specrefs to v1.7.0-alpha.1

Written by Cursor Bugbot for commit cbd4670. This will update automatically on new commits. Configure here.

@StefanBratanov StefanBratanov marked this pull request as ready for review January 6, 2026 15:27
@StefanBratanov StefanBratanov marked this pull request as draft January 6, 2026 15:27
@StefanBratanov
Copy link
Contributor Author

StefanBratanov commented Jan 7, 2026

Thanks a lot @jtraglia actually all reference tests should be passing now after the last 3 commits (apart from few minimal failing tests)

@StefanBratanov StefanBratanov marked this pull request as ready for review January 7, 2026 08:27
Copy link
Contributor

@zilm13 zilm13 left a comment

Choose a reason for hiding this comment

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

LGTM, just few nits

@StefanBratanov StefanBratanov force-pushed the builders-non-validating-staked-actors branch from 31349a2 to 61f8099 Compare January 13, 2026 14:09
stateGloas.getNextWithdrawalBuilderIndex().plus(processedBuildersSweepCount);
final UInt64 nextBuilderIndex = nextIndex.mod(stateGloas.getBuilders().size());
stateGloas.setNextWithdrawalBuilderIndex(nextBuilderIndex);
}
Copy link

Choose a reason for hiding this comment

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

Builder index corrupts next withdrawal validator index calculation

High Severity

WithdrawalsHelpersGloas does not override updateNextWithdrawalValidatorIndex, inheriting the Capella implementation that assumes all withdrawals have real validator indices. In Gloas, builder withdrawals use convertBuilderIndexToValidatorIndex which sets BUILDER_INDEX_FLAG (2^40). When the withdrawal list is full and the last withdrawal is from a builder, withdrawals.getLast().getValidatorIndex() returns a large value (e.g., 2^40 + builderIndex). Computing .mod(state.getValidators().size()) on this produces an arbitrary position, causing validators to be skipped or processed out of order in subsequent withdrawal sweeps.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Contributor

Choose a reason for hiding this comment

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

@StefanBratanov StefanBratanov force-pushed the builders-non-validating-staked-actors branch from 8676609 to a138da7 Compare January 14, 2026 16:47
@StefanBratanov StefanBratanov force-pushed the builders-non-validating-staked-actors branch 2 times, most recently from b04c2a7 to 12d53e7 Compare January 19, 2026 10:00
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

@StefanBratanov StefanBratanov force-pushed the builders-non-validating-staked-actors branch from 9ed3f94 to fe759c4 Compare January 21, 2026 09:02
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

stateGloas.getNextWithdrawalBuilderIndex().plus(processedBuildersSweepCount);
final UInt64 nextBuilderIndex = nextIndex.mod(stateGloas.getBuilders().size());
stateGloas.setNextWithdrawalBuilderIndex(nextBuilderIndex);
}
Copy link

Choose a reason for hiding this comment

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

Missing override for validator sweep index with builder withdrawals

High Severity

WithdrawalsHelpersGloas inherits updateNextWithdrawalValidatorIndex from Capella without override. When the withdrawal limit is reached during builder withdrawals (before validator sweep), the last withdrawal has a validatorIndex with BUILDER_INDEX_FLAG (2^40) set. The inherited method computes withdrawals.getLast().getValidatorIndex().plus(1).mod(validators.size()), producing an incorrect next validator sweep index since the builder index is astronomically larger than the validator count.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Contributor

@mehdi-aouadi mehdi-aouadi left a comment

Choose a reason for hiding this comment

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

LGTM
Just few nits

@StefanBratanov StefanBratanov enabled auto-merge (squash) January 21, 2026 17:42
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

final UInt64 amount) {
return new Builder(
pubkey,
withdrawalCredentials.get(0),
Copy link

Choose a reason for hiding this comment

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

Signed byte to int conversion fails for values >= 128

Low Severity

In getBuilderFromDeposit, withdrawalCredentials.get(0) returns a Java signed byte which is automatically promoted to a signed int when passed to the Builder constructor. For byte values >= 0x80 (128), this produces a negative int (e.g., 0x80 → -128), which will fail the checkArgument(value >= 0 && value <= 255) validation in SszByte.asUInt8. The getter Builder.getVersion() already uses ByteUtil.toUnsignedInt for correct unsigned conversion, but the setter path doesn't.

Fix in Cursor Fix in Web

protected int processBuilderWithdrawals(
final BeaconState state, final List<Withdrawal> withdrawals) {
UInt64 withdrawalIndex = getNextWithdrawalIndex(state, withdrawals);

Copy link

Choose a reason for hiding this comment

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

Missing override causes wrong next validator index with builder withdrawals

Medium Severity

WithdrawalsHelpersGloas doesn't override updateNextWithdrawalValidatorIndex. The inherited Capella implementation assumes when withdrawals.size() == maxWithdrawals, the last withdrawal is from validator sweep and uses withdrawals.getLast().getValidatorIndex() to set the next index. In Gloas, if builder withdrawals fill the list first, the last withdrawal has BUILDER_INDEX_FLAG set (a value around 2^40), causing getValidatorIndex().plus(1).mod(validatorCount) to produce an essentially arbitrary validator index for the next sweep.

Additional Locations (1)

Fix in Cursor Fix in Web

@StefanBratanov StefanBratanov merged commit f878142 into Consensys:master Jan 21, 2026
59 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Jan 21, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants