Skip to content

chore: review epbs state transition changes (part 2)#8660

Merged
ensi321 merged 3 commits intonc/epbs-stffrom
nflaig/review-8507-part-2
Dec 3, 2025
Merged

chore: review epbs state transition changes (part 2)#8660
ensi321 merged 3 commits intonc/epbs-stffrom
nflaig/review-8507-part-2

Conversation

@nflaig
Copy link
Member

@nflaig nflaig commented Dec 2, 2025

No description provided.

@nflaig nflaig marked this pull request as ready for review December 2, 2025 13:55
@nflaig nflaig requested a review from a team as a code owner December 2, 2025 13:55
@nflaig
Copy link
Member Author

nflaig commented Dec 2, 2025

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request primarily focuses on extending state transition logic to support the gloas fork, which is a significant and well-executed part of the changes. Many functions are updated to handle CachedBeaconStateGloas, improving type safety and preparing for the new fork. The changes also include several valuable code quality improvements, such as removing TODOs, eliminating unsafe type casts, and enhancing error logging for better debuggability. However, I've identified one critical issue in packages/state-transition/src/block/processWithdrawals.ts that appears to be an off-by-one error in a loop condition, potentially affecting consensus by not including the maximum number of withdrawals in a block. This should be addressed.

: stateGloas.builderPendingWithdrawals.getReadonly(i);

if (withdrawal.withdrawableEpoch > epoch || withdrawals.length === MAX_WITHDRAWALS_PER_PAYLOAD) {
if (withdrawal.withdrawableEpoch > epoch || withdrawals.length + 1 === MAX_WITHDRAWALS_PER_PAYLOAD) {
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

This loop condition appears to have an off-by-one error. The check withdrawals.length + 1 === MAX_WITHDRAWALS_PER_PAYLOAD will cause the loop to break when withdrawals.length is MAX_WITHDRAWALS_PER_PAYLOAD - 1, resulting in one less withdrawal being processed than the maximum allowed.

For example, if MAX_WITHDRAWALS_PER_PAYLOAD is 16 and withdrawals.length becomes 15, this condition 15 + 1 === 16 will be true, and the loop will break, leaving only 15 withdrawals in the list instead of the maximum of 16.

The condition should probably be withdrawals.length >= MAX_WITHDRAWALS_PER_PAYLOAD to allow the list to be filled up to its maximum capacity. This is also consistent with the check used later in this function.

Suggested change
if (withdrawal.withdrawableEpoch > epoch || withdrawals.length + 1 === MAX_WITHDRAWALS_PER_PAYLOAD) {
if (withdrawal.withdrawableEpoch > epoch || withdrawals.length >= MAX_WITHDRAWALS_PER_PAYLOAD) {

Copy link
Member Author

Choose a reason for hiding this comment

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

that's same as the spec here

  for withdrawal in state.builder_pending_withdrawals:
        if (
            withdrawal.withdrawable_epoch > epoch
            or len(withdrawals) + 1 == MAX_WITHDRAWALS_PER_PAYLOAD
        ):

Copy link
Contributor

Choose a reason for hiding this comment

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

I am surprised spec test didn't catch this bug

* Merge is complete when the state includes execution layer data:
* state.latestExecutionPayloadHeader NOT EMPTY
*/
// TODO GLOAS: See if we need to update this for gloas
Copy link
Member Author

Choose a reason for hiding this comment

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

we should just remove the merge transition code, it's probably simpler than making it somehow work with gloas

Copy link
Member Author

Choose a reason for hiding this comment

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

created #8661 to track it

Copy link
Contributor

@ensi321 ensi321 left a comment

Choose a reason for hiding this comment

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

Thanks for the fix @nflaig . I think this shows spec test coverage is not great, or it would have caught these bugs. Will need to review the related spec test cases

: stateGloas.builderPendingWithdrawals.getReadonly(i);

if (withdrawal.withdrawableEpoch > epoch || withdrawals.length === MAX_WITHDRAWALS_PER_PAYLOAD) {
if (withdrawal.withdrawableEpoch > epoch || withdrawals.length + 1 === MAX_WITHDRAWALS_PER_PAYLOAD) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I am surprised spec test didn't catch this bug

});
withdrawalIndex++;
withdrawnBalances.set(withdrawal.builderIndex, totalWithdrawn + withdrawableBalance);
if (withdrawableBalance > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I am surprised spec test didn't catch this bug

@ensi321 ensi321 merged commit 483664f into nc/epbs-stf Dec 3, 2025
33 of 37 checks passed
@ensi321 ensi321 deleted the nflaig/review-8507-part-2 branch December 3, 2025 06:14
@codecov
Copy link

codecov bot commented Dec 3, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 51.71%. Comparing base (fd3c571) to head (b11c719).
⚠️ Report is 1 commits behind head on nc/epbs-stf.

Additional details and impacted files
@@               Coverage Diff               @@
##           nc/epbs-stf    #8660      +/-   ##
===============================================
+ Coverage        51.69%   51.71%   +0.01%     
===============================================
  Files              855      855              
  Lines            66341    66300      -41     
  Branches          4809     4808       -1     
===============================================
- Hits             34294    34284      -10     
+ Misses           31979    31948      -31     
  Partials            68       68              
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@nflaig
Copy link
Member Author

nflaig commented Dec 3, 2025

I think this shows spec test coverage is not great, or it would have caught these bugs. Will need to review the related spec test cases

Yes, was thinking the same, it's concerning that we passed spec tests while deviating from the spec like this. There seems to be an effort in progress to improve coverage ethereum/consensus-specs#4759

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.

2 participants