@@ -3,7 +3,7 @@ use crate::{
33 decrease_balance, increase_balance,
44 update_progressive_balances_cache:: initialize_progressive_balances_cache,
55 } ,
6- epoch_cache:: { PreEpochCache , initialize_epoch_cache } ,
6+ epoch_cache:: { initialize_epoch_cache , PreEpochCache } ,
77 per_block_processing:: is_valid_deposit_signature,
88 per_epoch_processing:: { Delta , Error , ParticipationEpochSummary } ,
99} ;
@@ -13,14 +13,14 @@ 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 ,
18- ProgressiveBalancesCache , RelativeEpoch , Unsigned , Validator , Vector ,
1916 consts:: altair:: {
2017 NUM_FLAG_INDICES , PARTICIPATION_FLAG_WEIGHTS , TIMELY_HEAD_FLAG_INDEX ,
2118 TIMELY_TARGET_FLAG_INDEX , WEIGHT_DENOMINATOR ,
2219 } ,
2320 milhouse:: Cow ,
21+ ActivationQueue , BeaconState , BeaconStateError , ChainSpec , Checkpoint , DepositData , Epoch ,
22+ EthSpec , ExitCache , ForkName , List , ParticipationFlags , PendingDeposit ,
23+ ProgressiveBalancesCache , RelativeEpoch , Unsigned , Validator , Vector ,
2424} ;
2525
2626pub struct SinglePassConfig {
@@ -32,6 +32,7 @@ pub struct SinglePassConfig {
3232 pub pending_consolidations : bool ,
3333 pub effective_balance_updates : bool ,
3434 pub proposer_lookahead : bool ,
35+ pub builder_pending_payments : bool ,
3536}
3637
3738impl Default for SinglePassConfig {
@@ -51,6 +52,7 @@ impl SinglePassConfig {
5152 pending_consolidations : true ,
5253 effective_balance_updates : true ,
5354 proposer_lookahead : true ,
55+ builder_pending_payments : true ,
5456 }
5557 }
5658
@@ -64,6 +66,7 @@ impl SinglePassConfig {
6466 pending_consolidations : false ,
6567 effective_balance_updates : false ,
6668 proposer_lookahead : false ,
69+ builder_pending_payments : false ,
6770 }
6871 }
6972}
@@ -469,10 +472,14 @@ pub fn process_epoch_single_pass<E: EthSpec>(
469472 process_proposer_lookahead ( state, spec) ?;
470473 }
471474
475+ if conf. builder_pending_payments && fork_name. gloas_enabled ( ) {
476+ process_builder_pending_payments ( state, spec) ?;
477+ }
478+
472479 Ok ( summary)
473480}
474481
475- // TOOO (EIP-7917): use balances cache
482+ // TODO (EIP-7917): use balances cache
476483pub fn process_proposer_lookahead < E : EthSpec > (
477484 state : & mut BeaconState < E > ,
478485 spec : & ChainSpec ,
@@ -502,6 +509,69 @@ pub fn process_proposer_lookahead<E: EthSpec>(
502509 Ok ( ( ) )
503510}
504511
512+ /// 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+ spec : & ChainSpec ,
516+ ) -> 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+
523+ quorum
524+ . safe_div ( spec. builder_payment_threshold_denominator )
525+ . map_err ( Error :: from)
526+ }
527+
528+ /// Process builder pending payments, moving qualifying payments to withdrawals.
529+ /// TODO(EIP-7732): Add EF consensus-spec tests for `process_builder_pending_payments`
530+ /// Currently blocked by EF consensus-spec-tests for Gloas not yet integrated.
531+ pub fn process_builder_pending_payments < E : EthSpec > (
532+ state : & mut BeaconState < E > ,
533+ spec : & ChainSpec ,
534+ ) -> Result < ( ) , Error > {
535+ let quorum = get_builder_payment_quorum_threshold ( state, spec) ?;
536+
537+ // Collect qualifying payments
538+ let qualifying_payments = state
539+ . builder_pending_payments ( ) ?
540+ . iter ( )
541+ . take ( E :: slots_per_epoch ( ) as usize )
542+ . filter ( |payment| payment. weight > quorum)
543+ . cloned ( )
544+ . collect :: < Vec < _ > > ( ) ;
545+
546+ // Update `builder_pending_withdrawals` with qualifying `builder_pending_payments`
547+ qualifying_payments
548+ . into_iter ( )
549+ . try_for_each ( |payment| -> Result < ( ) , Error > {
550+ let exit_queue_epoch =
551+ state. compute_exit_epoch_and_update_churn ( payment. withdrawal . amount , spec) ?;
552+ let withdrawable_epoch =
553+ exit_queue_epoch. safe_add ( spec. min_validator_withdrawability_delay ) ?;
554+
555+ let mut withdrawal = payment. withdrawal . clone ( ) ;
556+ withdrawal. withdrawable_epoch = withdrawable_epoch;
557+ state. builder_pending_withdrawals_mut ( ) ?. push ( withdrawal) ?;
558+ Ok ( ( ) )
559+ } ) ?;
560+
561+ // Move remaining `builder_pending_payments` to start of list and set the rest to default
562+ let new_payments = state
563+ . builder_pending_payments ( ) ?
564+ . iter ( )
565+ . skip ( E :: slots_per_epoch ( ) as usize )
566+ . cloned ( )
567+ . chain ( ( 0 ..E :: slots_per_epoch ( ) as usize ) . map ( |_| types:: BuilderPendingPayment :: default ( ) ) )
568+ . collect :: < Vec < _ > > ( ) ;
569+
570+ * state. builder_pending_payments_mut ( ) ? = Vector :: new ( new_payments) ?;
571+
572+ Ok ( ( ) )
573+ }
574+
505575fn process_single_inactivity_update (
506576 inactivity_score : & mut Cow < u64 > ,
507577 validator_info : & ValidatorInfo ,
0 commit comments