Skip to content

Conversation

@jtraglia
Copy link
Member

@jtraglia jtraglia commented Dec 13, 2025

This PR makes a new Builder type, tracked in state.builders.

Some key improvements:

  • The minimum builder balance is 1 ETH.
  • There is no activation queue for builders.
  • Top-up deposits are instant, as soon as they hit the CL.
  • Builders will not be able to perform partial withdrawals; only do full exits.
  • Builders must wait 4096 epochs (~18 days) to exit and cannot submit bids during this process.
  • Builders cannot be slashed nor penalized.
  • Builder payments do not go through the exit queue.
  • Builder indices are re-usable.

Note: This PR does not fully test everything. We can handle that in separate PRs.

@jtraglia jtraglia force-pushed the builders-no-updated-withdrawal-types branch from 2e93bc6 to f709f7d Compare December 15, 2025 18:49
jtraglia added a commit that referenced this pull request Dec 15, 2025
…4789)

I should have done this in the previous refactoring PR.

* Rename `get_sweep_withdrawals` to `get_validators_sweep_withdrawals`.
* Remove `validator_index` parameter from function.
* Update comments & variables to reflect this change.

If/when we merge #4788 which adds a builders sweep, this distinction
will be necessary.
@jtraglia jtraglia marked this pull request as ready for review December 15, 2025 21:09
@jtraglia jtraglia requested a review from jihoonsong December 15, 2025 21:09
pubkey: BLSPubkey
withdrawal_credentials: Bytes32
balance: Gwei
exit_epoch: Epoch
Copy link
Contributor

Choose a reason for hiding this comment

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

I think builder should also have a withdrawable_epoch. Once the exit_epoch is reached the builder becomes inactive, i.e. it cannot bid, and then until withdrawable_epoch the balance is frozen on the beacon chain. Without that freeze the DoS protection isn’t as strong as it can be

Copy link
Member Author

Choose a reason for hiding this comment

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

Right now, builders cannot submit bids after initiating their exit. So there is a freeze. I chatted with @fradamt about this some and he has some concerns with not allowing builders to submit bids during this period. So maybe we'll change it & add a withdrawable_epoch field.

# Verify that the builder has not initiated an exit
assert builder.exit_epoch == FAR_FUTURE_EPOCH

@jtraglia jtraglia changed the title Make builders non-validating staked actors (option 2) Make builders non-validating staked actors Dec 16, 2025
Comment on lines +516 to +518
if builder_balance < min_balance:
return False
return builder_balance - min_balance >= bid_amount
Copy link
Contributor

Choose a reason for hiding this comment

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

oh you're modifying p2p as well, alright it makes sense, but it's a bit confusing to interleave p2p validation with core functions because of this. It also ties p2p validation to having a particular state, the balance of the builder can change state by state and typically when validating p2p objects we are a little lax into which state you use to validate them otherwise it could lead to peering issues. I think that even if you insist in having this validation here, the p2p one should be more lax and be about the builder's balance (in whatever state the node is using to validate it) to be less than the min balance + bid_amount, regardless of pending payments in the pipeline.

def get_expected_withdrawals(
state: BeaconState,
) -> Tuple[Sequence[Withdrawal], uint64, uint64, uint64]:
) -> Tuple[Sequence[Withdrawal], uint64, uint64, uint64, uint64]:
Copy link
Contributor

Choose a reason for hiding this comment

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

At this stage the return object of this function probably needs to be a named type

###### New `get_index_for_new_builder`

```python
def get_index_for_new_builder(state: BeaconState) -> BuilderIndex:
Copy link
Contributor

Choose a reason for hiding this comment

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

Flagging this function as a possible problem. Don't have it clear yet but it's something that clients may want to discuss in the breakout. We typically have a global pubkey -> index (or inverse) cache for signature validation and this type of reusage would make this cache a little more sensitive to be in sync with the head view.

Not against this, but just flagging as a possible shot in our feet.

current_epoch = compute_epoch_at_slot(state.slot)
return not builder.slashed or current_epoch >= builder.withdrawable_epoch
```
def get_builder_withdrawals(
Copy link
Member

Choose a reason for hiding this comment

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

Not sure if it is just me but I've found get_builder_withdrawals a bit confusing as it sounds like general withdrawals although it's actually builder payments. Perhaps we could use something like get_builder_payment_withdrawals.

This comment also applies to state.builder_pending_withdrawals as well. It's a pair of builder_pending_withdrawals and builder_pending_payments, but perhaps it's better to distinguish it via something like payment withdrawals as we now introduce sweep withdrawals for builders.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I also find this confusing. Let's rename this in a separate PR though.

@jtraglia jtraglia merged commit 601829f into master Jan 5, 2026
16 checks passed
@jtraglia jtraglia deleted the builders-no-updated-withdrawal-types branch January 5, 2026 17:04
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.

10 participants