Skip to content

Conversation

@jtraglia
Copy link
Member

@jtraglia jtraglia commented Dec 1, 2025

The get_expected_withdrawals is a long, complex function.

This PR splits get_expected_withdrawals into smaller functions:

  • get_sweep_withdrawals
  • get_pending_partial_withdrawals
  • get_builder_withdrawals

Associated with:

Note: I decided to include prior_withdrawals in all functions so that we don't need create a modified function which makes such a simple change. I didn't include many comments; we can look into making that better. Open to suggestions on other simplifications.

@leolara
Copy link
Member

leolara commented Dec 4, 2025

I think this type of change that improves the readability of the specs are very good.

@leolara
Copy link
Member

leolara commented Dec 4, 2025

I didn't include many comments; we can look into making that better. Open to suggestions on other simplifications.

Splitting the code in more functions make them more self-explanatory

@0xMushow
Copy link
Contributor

0xMushow commented Dec 4, 2025

LGTM!

Comment on lines +554 to +564
def is_eligible_for_partial_withdrawals(validator: Validator, balance: Gwei) -> bool:
"""
Check if ``validator`` can process a pending partial withdrawal.
"""
has_sufficient_effective_balance = validator.effective_balance >= MIN_ACTIVATION_BALANCE
has_excess_balance = balance > MIN_ACTIVATION_BALANCE
return (
validator.exit_epoch == FAR_FUTURE_EPOCH
and has_sufficient_effective_balance
and has_excess_balance
)
Copy link
Member Author

Choose a reason for hiding this comment

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

In a follow up PR, I would like to rename:

  • is_partially_withdrawable_validator -> has_withdrawable_excess_balance
  • is_eligible_for_partial_withdrawals -> is_partially_withdrawable_validator

The "partially withdrawable" function is very misleading now.

Copy link
Member

@jihoonsong jihoonsong left a comment

Choose a reason for hiding this comment

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

Great refactors.

@jtraglia
Copy link
Member Author

jtraglia commented Dec 7, 2025

@jihoonsong Thanks for the review! All good suggestions, I'll fix these on Monday 👍

epoch = get_current_epoch(state)
withdrawal_index = state.next_withdrawal_index
validator_index = state.next_withdrawal_validator_index
def get_balance_minus_withdrawals(
Copy link
Contributor

@ensi321 ensi321 Dec 8, 2025

Choose a reason for hiding this comment

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

This function name sounds odd. It only explains the calculation part but doesn't explain what this returned value is for. Maybe get_withdrawable_balance() or get_available_balance_to_withdraw()?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hey @ensi321. Yeah I agree the name is odd. I'm not sure that your two suggestions are accurate though. They don't return the "withdrawable" or "available" amount; given a validator with 32.50 ETH and 0.30 ETH of withdrawals, I would expect that to return 0.20 ETH. Instead, they return the validator's balance after the given withdrawals; 32.20 ETH. Maybe get_balance_after_withdrawals() would be more clear? I'm open to other suggestions too.

Copy link
Member Author

Choose a reason for hiding this comment

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

Another option is get_remaining_balance(), though it feels a little ambiguous.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm.. isn't it a balance at the point after previous withdrawals and before applying further withdrawals? Then, it can viewed as a temporal withdrawable balance. Maybe get_current_withdrawable_balance() is more straightforward at the cost of a bit verbosity? What do others think?

Copy link
Member Author

Choose a reason for hiding this comment

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

@jihoonsong get_current_withdrawable_balance still has the same issue 😢

I think calling it "withdrawable" is misleading.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, not the whole amount is withdrawable.

Copy link
Member Author

@jtraglia jtraglia Dec 10, 2025

Choose a reason for hiding this comment

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

Yes. I've renamed the function to get_balance_after_withdrawals. I think this is marginally better than the original. Still open to other suggestions.

Copy link
Member

@jihoonsong jihoonsong left a comment

Choose a reason for hiding this comment

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

The refactor of processed sweep count looks neat. It will affect on #4765's update_next_withdrawal_indices so we probably want to merge this PR first.

I've left some comments but please excuse that I wore the bikeshedder's hat 😅

@jtraglia jtraglia force-pushed the refactor-get-expected-withdrawals branch from 1b8a0d4 to 92c34c7 Compare December 13, 2025 15:24
@jtraglia
Copy link
Member Author

jtraglia commented Dec 13, 2025

Rebased to pull in changes from master (need to resolve some conflicts).

@jihoonsong I've fixed 3/4 of your comments. How does it look now?

(Also, I'm a fan of nit picky comments, keep em coming!)

Copy link
Member

@jihoonsong jihoonsong left a comment

Choose a reason for hiding this comment

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

Looks good! Looking forward to #4765 and builder sweep one. Great work!

@jtraglia jtraglia merged commit 226c173 into ethereum:master Dec 15, 2025
16 checks passed
@jtraglia jtraglia deleted the refactor-get-expected-withdrawals branch December 15, 2025 16:09
jtraglia added a commit that referenced this pull request Dec 17, 2025
In #4766, we added `processed_validators_sweep_count` to the return but
forgot to update the return type.
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.

7 participants