diff --git a/beacon_node/beacon_chain/src/beacon_block_reward.rs b/beacon_node/beacon_chain/src/beacon_block_reward.rs index d345e6f5599..7eaaa3da702 100644 --- a/beacon_node/beacon_chain/src/beacon_block_reward.rs +++ b/beacon_node/beacon_chain/src/beacon_block_reward.rs @@ -82,7 +82,7 @@ impl BeaconChain { BeaconChainError::BlockRewardAttestationError })? } else { - self.compute_beacon_block_attestation_reward_altair_deneb(block, state) + self.compute_beacon_block_attestation_reward_altair_and_later(block, state) .map_err(|e| { error!( error = ?e, @@ -249,7 +249,7 @@ impl BeaconChain { Ok(block_reward) } - fn compute_beacon_block_attestation_reward_altair_deneb< + fn compute_beacon_block_attestation_reward_altair_and_later< Payload: AbstractExecPayload, >( &self, @@ -267,13 +267,20 @@ impl BeaconChain { let mut previous_epoch_participation = state.previous_epoch_participation()?.to_owned_list(); + let parent_slot = state + .latest_execution_payload_bid() + .ok() + .map(|bid| bid.slot); + for attestation in block.body().attestations() { let data = attestation.data(); let inclusion_delay = state.slot().safe_sub(data.slot)?.as_u64(); + // [Modified in Deneb:EIP7045] let participation_flag_indices = get_attestation_participation_flag_indices( state, data, + parent_slot, inclusion_delay, &self.spec, )?; diff --git a/beacon_node/beacon_chain/src/validator_monitor.rs b/beacon_node/beacon_chain/src/validator_monitor.rs index 294f160b821..8cca7a416ad 100644 --- a/beacon_node/beacon_chain/src/validator_monitor.rs +++ b/beacon_node/beacon_chain/src/validator_monitor.rs @@ -728,10 +728,16 @@ impl ValidatorMonitor { let data = unaggregated_attestation.data(); + let parent_slot = state + .latest_execution_payload_bid() + .ok() + .map(|bid| bid.slot); + // Get the reward indices for the unaggregated attestation or log an error match get_attestation_participation_flag_indices( state, unaggregated_attestation.data(), + parent_slot, inclusion_delay, spec, ) { diff --git a/beacon_node/operation_pool/src/attestation.rs b/beacon_node/operation_pool/src/attestation.rs index 7b6985b4c33..60bd2f2df9d 100644 --- a/beacon_node/operation_pool/src/attestation.rs +++ b/beacon_node/operation_pool/src/attestation.rs @@ -81,9 +81,19 @@ impl<'a, E: EthSpec> AttMaxCover<'a, E> { let att_data = att.attestation_data(); let inclusion_delay = state.slot().as_u64().checked_sub(att_data.slot.as_u64())?; - let att_participation_flags = - get_attestation_participation_flag_indices(state, &att_data, inclusion_delay, spec) - .ok()?; + let parent_slot = state + .latest_execution_payload_bid() + .ok() + .map(|bid| bid.slot); + + let att_participation_flags = get_attestation_participation_flag_indices( + state, + &att_data, + parent_slot, + inclusion_delay, + spec, + ) + .ok()?; let fresh_validators_rewards = att .indexed diff --git a/consensus/state_processing/src/common/get_attestation_participation.rs b/consensus/state_processing/src/common/get_attestation_participation.rs index 8f1f000f401..ac27579d058 100644 --- a/consensus/state_processing/src/common/get_attestation_participation.rs +++ b/consensus/state_processing/src/common/get_attestation_participation.rs @@ -2,7 +2,7 @@ use integer_sqrt::IntegerSquareRoot; use safe_arith::SafeArith; use smallvec::SmallVec; use types::{ - AttestationData, BeaconState, BeaconStateError as Error, ChainSpec, EthSpec, + AttestationData, BeaconState, BeaconStateError as Error, ChainSpec, EthSpec, Slot, consts::altair::{ NUM_FLAG_INDICES, TIMELY_HEAD_FLAG_INDEX, TIMELY_SOURCE_FLAG_INDEX, TIMELY_TARGET_FLAG_INDEX, @@ -21,6 +21,7 @@ use types::{ pub fn get_attestation_participation_flag_indices( state: &BeaconState, data: &AttestationData, + parent_slot: Option, inclusion_delay: u64, spec: &ChainSpec, ) -> Result, Error> { @@ -37,6 +38,8 @@ pub fn get_attestation_participation_flag_indices( // [New in Gloas:EIP7732] let payload_matches = if state.fork_name_unchecked().gloas_enabled() { + let parent_slot = parent_slot.ok_or(Error::MissingParentSlot)?; + if state.is_attestation_same_slot(data)? { // For same-slot attestations, data.index must be 0 if data.index != 0 { @@ -45,8 +48,7 @@ pub fn get_attestation_participation_flag_indices( true } else { // For non same-slot attestations, check execution payload availability - let slot_index = data - .slot + let slot_index = parent_slot .as_usize() .safe_rem(E::slots_per_historical_root())?; let payload_index = state diff --git a/consensus/state_processing/src/per_block_processing.rs b/consensus/state_processing/src/per_block_processing.rs index 22ec9a9ed47..2895ab756a9 100644 --- a/consensus/state_processing/src/per_block_processing.rs +++ b/consensus/state_processing/src/per_block_processing.rs @@ -185,6 +185,7 @@ pub fn per_block_processing>( state.build_committee_cache(RelativeEpoch::Previous, spec)?; state.build_committee_cache(RelativeEpoch::Current, spec)?; + let mut parent_slot = None; // The call to the `process_execution_payload` must happen before the call to the // `process_randao` as the former depends on the `randao_mix` computed with the reveal of the // previous block. @@ -193,6 +194,7 @@ pub fn per_block_processing>( if state.fork_name_unchecked().gloas_enabled() { withdrawals::gloas::process_withdrawals::(state, spec)?; let signed_bid = block.body().signed_execution_payload_bid()?; + parent_slot = Some(state.latest_execution_payload_bid()?.slot); process_execution_payload_bid(state, signed_bid, verify_signatures, spec)?; } else { if state.fork_name_unchecked().capella_enabled() { @@ -208,7 +210,14 @@ pub fn per_block_processing>( process_randao(state, block, verify_randao, ctxt, spec)?; process_eth1_data(state, block.body().eth1_data())?; - process_operations(state, block.body(), verify_signatures, ctxt, spec)?; + process_operations( + state, + block.body(), + verify_signatures, + parent_slot, + ctxt, + spec, + )?; if let Ok(sync_aggregate) = block.body().sync_aggregate() { process_sync_aggregate( diff --git a/consensus/state_processing/src/per_block_processing/process_operations.rs b/consensus/state_processing/src/per_block_processing/process_operations.rs index b2d2d49a83b..1b8af3d09e7 100644 --- a/consensus/state_processing/src/per_block_processing/process_operations.rs +++ b/consensus/state_processing/src/per_block_processing/process_operations.rs @@ -17,6 +17,7 @@ pub fn process_operations>( state: &mut BeaconState, block_body: BeaconBlockBodyRef, verify_signatures: VerifySignatures, + parent_slot: Option, ctxt: &mut ConsensusContext, spec: &ChainSpec, ) -> Result<(), BlockProcessingError> { @@ -40,7 +41,14 @@ pub fn process_operations>( ctxt, spec, )?; - process_attestations(state, block_body, verify_signatures, ctxt, spec)?; + process_attestations( + state, + block_body, + verify_signatures, + parent_slot, + ctxt, + spec, + )?; process_deposits(state, &block_body.deposits().to_cow_slice(), spec)?; process_exits( state, @@ -247,7 +255,7 @@ pub mod altair_deneb { let data = attestation.data(); let inclusion_delay = state.slot().safe_sub(data.slot)?.as_u64(); let participation_flag_indices = - get_attestation_participation_flag_indices(state, data, inclusion_delay, spec)?; + get_attestation_participation_flag_indices(state, data, None, inclusion_delay, spec)?; // Update epoch participation flags. let mut proposer_reward_numerator = 0; @@ -304,6 +312,7 @@ pub mod gloas { state: &mut BeaconState, attestations: I, verify_signatures: VerifySignatures, + parent_slot: Option, ctxt: &mut ConsensusContext, spec: &ChainSpec, ) -> Result<(), BlockProcessingError> @@ -311,7 +320,15 @@ pub mod gloas { I: Iterator>, { attestations.enumerate().try_for_each(|(i, attestation)| { - process_attestation(state, attestation, i, ctxt, verify_signatures, spec) + process_attestation( + state, + attestation, + i, + verify_signatures, + parent_slot, + ctxt, + spec, + ) }) } @@ -319,8 +336,9 @@ pub mod gloas { state: &mut BeaconState, attestation: AttestationRef, att_index: usize, - ctxt: &mut ConsensusContext, verify_signatures: VerifySignatures, + parent_slot: Option, + ctxt: &mut ConsensusContext, spec: &ChainSpec, ) -> Result<(), BlockProcessingError> { let proposer_index = ctxt.get_proposer_index(state, spec)?; @@ -339,8 +357,13 @@ pub mod gloas { // Matching roots, participation flag indices let data = attestation.data(); let inclusion_delay = state.slot().safe_sub(data.slot)?.as_u64(); - let participation_flag_indices = - get_attestation_participation_flag_indices(state, data, inclusion_delay, spec)?; + let participation_flag_indices = get_attestation_participation_flag_indices( + state, + data, + parent_slot, + inclusion_delay, + spec, + )?; // [New in EIP-7732] let current_epoch_target = data.target.epoch == state.current_epoch(); @@ -540,6 +563,7 @@ pub fn process_attestations>( state: &mut BeaconState, block_body: BeaconBlockBodyRef, verify_signatures: VerifySignatures, + parent_slot: Option, ctxt: &mut ConsensusContext, spec: &ChainSpec, ) -> Result<(), BlockProcessingError> { @@ -548,6 +572,7 @@ pub fn process_attestations>( state, block_body.attestations(), verify_signatures, + parent_slot, ctxt, spec, )?; diff --git a/consensus/state_processing/src/per_block_processing/tests.rs b/consensus/state_processing/src/per_block_processing/tests.rs index 63f33548fb2..4b21c108963 100644 --- a/consensus/state_processing/src/per_block_processing/tests.rs +++ b/consensus/state_processing/src/per_block_processing/tests.rs @@ -441,10 +441,15 @@ async fn invalid_attestation_no_committee_for_index() { .into_data_mut() .index += 1; let mut ctxt = ConsensusContext::new(state.slot()); + let parent_slot = state + .latest_execution_payload_bid() + .ok() + .map(|bid| bid.slot); let result = process_operations::process_attestations( &mut state, head_block.body(), VerifySignatures::True, + parent_slot, &mut ctxt, &spec, ); @@ -491,10 +496,15 @@ async fn invalid_attestation_wrong_justified_checkpoint() { .source = new_justified_checkpoint; let mut ctxt = ConsensusContext::new(state.slot()); + let parent_slot = state + .latest_execution_payload_bid() + .ok() + .map(|bid| bid.slot); let result = process_operations::process_attestations( &mut state, head_block.body(), VerifySignatures::True, + parent_slot, &mut ctxt, &spec, ); @@ -545,10 +555,15 @@ async fn invalid_attestation_bad_aggregation_bitfield_len() { } let mut ctxt = ConsensusContext::new(state.slot()); + let parent_slot = state + .latest_execution_payload_bid() + .ok() + .map(|bid| bid.slot); let result = process_operations::process_attestations( &mut state, head_block.body(), VerifySignatures::True, + parent_slot, &mut ctxt, &spec, ); @@ -585,10 +600,15 @@ async fn invalid_attestation_bad_signature() { .into_signature_mut() = AggregateSignature::empty(); let mut ctxt = ConsensusContext::new(state.slot()); + let parent_slot = state + .latest_execution_payload_bid() + .ok() + .map(|bid| bid.slot); let result = process_operations::process_attestations( &mut state, head_block.body(), VerifySignatures::True, + parent_slot, &mut ctxt, &spec, ); @@ -629,10 +649,15 @@ async fn invalid_attestation_included_too_early() { .slot = new_attesation_slot; let mut ctxt = ConsensusContext::new(state.slot()); + let parent_slot = state + .latest_execution_payload_bid() + .ok() + .map(|bid| bid.slot); let result = process_operations::process_attestations( &mut state, head_block.body(), VerifySignatures::True, + parent_slot, &mut ctxt, &spec, ); @@ -680,10 +705,15 @@ async fn invalid_attestation_target_epoch_slot_mismatch() { .epoch += Epoch::new(1); let mut ctxt = ConsensusContext::new(state.slot()); + let parent_slot = state + .latest_execution_payload_bid() + .ok() + .map(|bid| bid.slot); let result = process_operations::process_attestations( &mut state, head_block.body(), VerifySignatures::True, + parent_slot, &mut ctxt, &spec, ); diff --git a/consensus/state_processing/src/upgrade/altair.rs b/consensus/state_processing/src/upgrade/altair.rs index 66bdb1af250..887fc100022 100644 --- a/consensus/state_processing/src/upgrade/altair.rs +++ b/consensus/state_processing/src/upgrade/altair.rs @@ -25,7 +25,7 @@ pub fn translate_participation( // Translate attestation inclusion info to flag indices. let participation_flag_indices = - get_attestation_participation_flag_indices(state, data, inclusion_delay, spec)?; + get_attestation_participation_flag_indices(state, data, None, inclusion_delay, spec)?; // Apply flags to all attesting validators. let committee = state.get_beacon_committee(data.slot, data.index)?; diff --git a/consensus/types/src/state/beacon_state.rs b/consensus/types/src/state/beacon_state.rs index b70b1c5b21e..84e3b303a16 100644 --- a/consensus/types/src/state/beacon_state.rs +++ b/consensus/types/src/state/beacon_state.rs @@ -237,6 +237,7 @@ pub enum BeaconStateError { InvalidIndicesCount, InvalidBuilderPendingPaymentsIndex(usize), InvalidExecutionPayloadAvailabilityIndex(usize), + MissingParentSlot, /// Merkle proofs against the `BeaconState` and `BeaconBlockBody` use progressive-container /// generalized indices from Gloas (EIP-7688) onwards, which are not implemented yet. ProgressiveMerkleProofNotSupported, diff --git a/testing/ef_tests/src/cases/operations.rs b/testing/ef_tests/src/cases/operations.rs index 350d52dcf2a..c72e4a2256d 100644 --- a/testing/ef_tests/src/cases/operations.rs +++ b/testing/ef_tests/src/cases/operations.rs @@ -131,12 +131,14 @@ impl Operation for Attestation { initialize_progressive_balances_cache(state, spec)?; let mut ctxt = ConsensusContext::new(state.slot()); if state.fork_name_unchecked().gloas_enabled() { + let parent_slot = Some(state.latest_execution_payload_bid()?.slot); gloas::process_attestation( state, self.to_ref(), 0, - &mut ctxt, VerifySignatures::True, + parent_slot, + &mut ctxt, spec, ) } else if state.fork_name_unchecked().altair_enabled() {