From 82b38708133332b67a3d2aa776fb8ef4ea88b15b Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 12 Jan 2026 11:34:20 -0600 Subject: [PATCH 1/3] Reserve space for one validator sweep withdrawal --- specs/gloas/beacon-chain.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/gloas/beacon-chain.md b/specs/gloas/beacon-chain.md index 5614592b77..0f09436914 100644 --- a/specs/gloas/beacon-chain.md +++ b/specs/gloas/beacon-chain.md @@ -861,7 +861,7 @@ def get_builder_withdrawals( withdrawal_index: WithdrawalIndex, prior_withdrawals: Sequence[Withdrawal], ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]: - withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD + withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD - 1 processed_count: uint64 = 0 withdrawals: List[Withdrawal] = [] @@ -896,7 +896,7 @@ def get_builders_sweep_withdrawals( ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]: epoch = get_current_epoch(state) builders_limit = min(len(state.builders), MAX_BUILDERS_PER_WITHDRAWALS_SWEEP) - withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD + withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD - 1 processed_count: uint64 = 0 withdrawals: List[Withdrawal] = [] From 8fe57d106fb344fc766451014e30abdc90746ed8 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 12 Jan 2026 12:50:03 -0600 Subject: [PATCH 2/3] Change withdrawals_limit check to >= --- specs/capella/beacon-chain.md | 2 +- specs/electra/beacon-chain.md | 4 ++-- specs/gloas/beacon-chain.md | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/specs/capella/beacon-chain.md b/specs/capella/beacon-chain.md index 5d169dbcd2..dea18cc16c 100644 --- a/specs/capella/beacon-chain.md +++ b/specs/capella/beacon-chain.md @@ -390,7 +390,7 @@ def get_validators_sweep_withdrawals( validator_index = state.next_withdrawal_validator_index for _ in range(validators_limit): all_withdrawals = prior_withdrawals + withdrawals - has_reached_limit = len(all_withdrawals) == withdrawals_limit + has_reached_limit = len(all_withdrawals) >= withdrawals_limit if has_reached_limit: break diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index f523d5f8fb..c99a48ee03 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -1240,7 +1240,7 @@ def get_pending_partial_withdrawals( for withdrawal in state.pending_partial_withdrawals: all_withdrawals = prior_withdrawals + withdrawals is_withdrawable = withdrawal.withdrawable_epoch <= epoch - has_reached_limit = len(all_withdrawals) == withdrawals_limit + has_reached_limit = len(all_withdrawals) >= withdrawals_limit if not is_withdrawable or has_reached_limit: break @@ -1284,7 +1284,7 @@ def get_validators_sweep_withdrawals( validator_index = state.next_withdrawal_validator_index for _ in range(validators_limit): all_withdrawals = prior_withdrawals + withdrawals - has_reached_limit = len(all_withdrawals) == withdrawals_limit + has_reached_limit = len(all_withdrawals) >= withdrawals_limit if has_reached_limit: break diff --git a/specs/gloas/beacon-chain.md b/specs/gloas/beacon-chain.md index 0f09436914..a329c44645 100644 --- a/specs/gloas/beacon-chain.md +++ b/specs/gloas/beacon-chain.md @@ -867,7 +867,7 @@ def get_builder_withdrawals( withdrawals: List[Withdrawal] = [] for withdrawal in state.builder_pending_withdrawals: all_withdrawals = prior_withdrawals + withdrawals - has_reached_limit = len(all_withdrawals) == withdrawals_limit + has_reached_limit = len(all_withdrawals) >= withdrawals_limit if has_reached_limit: break @@ -903,7 +903,7 @@ def get_builders_sweep_withdrawals( builder_index = state.next_withdrawal_builder_index for _ in range(builders_limit): all_withdrawals = prior_withdrawals + withdrawals - has_reached_limit = len(all_withdrawals) == withdrawals_limit + has_reached_limit = len(all_withdrawals) >= withdrawals_limit if has_reached_limit: break From 2c810f4ecac7b9e958c1433103541d4b5e3a79a5 Mon Sep 17 00:00:00 2001 From: Justin Traglia Date: Mon, 12 Jan 2026 12:55:41 -0600 Subject: [PATCH 3/3] Add asserts --- specs/capella/beacon-chain.md | 2 ++ specs/electra/beacon-chain.md | 3 +++ specs/gloas/beacon-chain.md | 2 ++ 3 files changed, 7 insertions(+) diff --git a/specs/capella/beacon-chain.md b/specs/capella/beacon-chain.md index dea18cc16c..d75225e970 100644 --- a/specs/capella/beacon-chain.md +++ b/specs/capella/beacon-chain.md @@ -384,6 +384,8 @@ def get_validators_sweep_withdrawals( epoch = get_current_epoch(state) validators_limit = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD + # There must be at least one space reserved for validator sweep withdrawals + assert len(prior_withdrawals) < withdrawals_limit processed_count: uint64 = 0 withdrawals: List[Withdrawal] = [] diff --git a/specs/electra/beacon-chain.md b/specs/electra/beacon-chain.md index c99a48ee03..d3d54d1825 100644 --- a/specs/electra/beacon-chain.md +++ b/specs/electra/beacon-chain.md @@ -1234,6 +1234,7 @@ def get_pending_partial_withdrawals( len(prior_withdrawals) + MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP, MAX_WITHDRAWALS_PER_PAYLOAD - 1, ) + assert len(prior_withdrawals) <= withdrawals_limit processed_count: uint64 = 0 withdrawals: List[Withdrawal] = [] @@ -1278,6 +1279,8 @@ def get_validators_sweep_withdrawals( epoch = get_current_epoch(state) validators_limit = min(len(state.validators), MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP) withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD + # There must be at least one space reserved for validator sweep withdrawals + assert len(prior_withdrawals) < withdrawals_limit processed_count: uint64 = 0 withdrawals: List[Withdrawal] = [] diff --git a/specs/gloas/beacon-chain.md b/specs/gloas/beacon-chain.md index a329c44645..3810d015ae 100644 --- a/specs/gloas/beacon-chain.md +++ b/specs/gloas/beacon-chain.md @@ -862,6 +862,7 @@ def get_builder_withdrawals( prior_withdrawals: Sequence[Withdrawal], ) -> Tuple[Sequence[Withdrawal], WithdrawalIndex, uint64]: withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD - 1 + assert len(prior_withdrawals) <= withdrawals_limit processed_count: uint64 = 0 withdrawals: List[Withdrawal] = [] @@ -897,6 +898,7 @@ def get_builders_sweep_withdrawals( epoch = get_current_epoch(state) builders_limit = min(len(state.builders), MAX_BUILDERS_PER_WITHDRAWALS_SWEEP) withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD - 1 + assert len(prior_withdrawals) <= withdrawals_limit processed_count: uint64 = 0 withdrawals: List[Withdrawal] = []