@@ -13,8 +13,8 @@ use std::cmp::{max, min};
1313use std:: collections:: { BTreeSet , HashMap } ;
1414use tracing:: instrument;
1515use types:: {
16- ActivationQueue , BeaconState , BeaconStateError , ChainSpec , Checkpoint , DepositData , Epoch ,
17- EthSpec , ExitCache , ForkName , List , ParticipationFlags , PendingDeposit ,
16+ ActivationQueue , BeaconState , BeaconStateError , BuilderPendingPayment , ChainSpec , Checkpoint ,
17+ DepositData , Epoch , EthSpec , ExitCache , ForkName , List , ParticipationFlags , PendingDeposit ,
1818 ProgressiveBalancesCache , RelativeEpoch , Unsigned , Validator , Vector ,
1919 consts:: altair:: {
2020 NUM_FLAG_INDICES , PARTICIPATION_FLAG_WEIGHTS , TIMELY_HEAD_FLAG_INDEX ,
@@ -457,6 +457,12 @@ pub fn process_epoch_single_pass<E: EthSpec>(
457457 ) ?;
458458 }
459459
460+ // Process builder pending payments outside the single-pass loop, as they depend on balances for multiple
461+ // validators and cannot be computed accurately inside the loop.
462+ if fork_name. gloas_enabled ( ) && conf. builder_pending_payments {
463+ process_builder_pending_payments ( state, state_ctxt, spec) ?;
464+ }
465+
460466 // Finally, finish updating effective balance caches. We need this to happen *after* processing
461467 // of pending consolidations, which recomputes some effective balances.
462468 if conf. effective_balance_updates {
@@ -472,10 +478,6 @@ pub fn process_epoch_single_pass<E: EthSpec>(
472478 process_proposer_lookahead ( state, spec) ?;
473479 }
474480
475- if conf. builder_pending_payments && fork_name. gloas_enabled ( ) {
476- process_builder_pending_payments ( state, spec) ?;
477- }
478-
479481 Ok ( summary)
480482}
481483
@@ -510,16 +512,14 @@ pub fn process_proposer_lookahead<E: EthSpec>(
510512}
511513
512514/// Calculate the quorum threshold for builder payments based on total active balance.
513- pub fn get_builder_payment_quorum_threshold < E : EthSpec > (
514- state : & BeaconState < E > ,
515+ fn get_builder_payment_quorum_threshold < E : EthSpec > (
516+ state_ctxt : & StateContext ,
515517 spec : & ChainSpec ,
516518) -> Result < u64 , Error > {
517- let total_active_balance = state. get_total_active_balance ( ) ?;
518-
519- let quorum = total_active_balance
520- . safe_div ( E :: slots_per_epoch ( ) ) ?
521- . safe_mul ( spec. builder_payment_threshold_numerator ) ?;
522-
519+ let per_slot_balance = state_ctxt
520+ . total_active_balance
521+ . safe_div ( E :: slots_per_epoch ( ) ) ?;
522+ let quorum = per_slot_balance. safe_mul ( spec. builder_payment_threshold_numerator ) ?;
523523 quorum
524524 . safe_div ( spec. builder_payment_threshold_denominator )
525525 . map_err ( Error :: from)
@@ -528,11 +528,12 @@ pub fn get_builder_payment_quorum_threshold<E: EthSpec>(
528528/// Process builder pending payments, moving qualifying payments to withdrawals.
529529/// TODO(EIP-7732): Add EF consensus-spec tests for `process_builder_pending_payments`
530530/// Currently blocked by EF consensus-spec-tests for Gloas not yet integrated.
531- pub fn process_builder_pending_payments < E : EthSpec > (
531+ fn process_builder_pending_payments < E : EthSpec > (
532532 state : & mut BeaconState < E > ,
533+ state_ctxt : & StateContext ,
533534 spec : & ChainSpec ,
534535) -> Result < ( ) , Error > {
535- let quorum = get_builder_payment_quorum_threshold ( state , spec) ?;
536+ let quorum = get_builder_payment_quorum_threshold :: < E > ( state_ctxt , spec) ?;
536537
537538 // Collect qualifying payments
538539 let qualifying_payments = state
@@ -564,7 +565,7 @@ pub fn process_builder_pending_payments<E: EthSpec>(
564565 . iter ( )
565566 . skip ( E :: slots_per_epoch ( ) as usize )
566567 . cloned ( )
567- . chain ( ( 0 ..E :: slots_per_epoch ( ) as usize ) . map ( |_| types :: BuilderPendingPayment :: default ( ) ) )
568+ . chain ( ( 0 ..E :: slots_per_epoch ( ) as usize ) . map ( |_| BuilderPendingPayment :: default ( ) ) )
568569 . collect :: < Vec < _ > > ( ) ;
569570
570571 * state. builder_pending_payments_mut ( ) ? = Vector :: new ( new_payments) ?;
0 commit comments