Skip to content

Commit d96075e

Browse files
committed
Merge latest unstable
2 parents 0a20547 + 8b085dd commit d96075e

File tree

47 files changed

+1880
-1473
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1880
-1473
lines changed

Cargo.lock

Lines changed: 111 additions & 269 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ derivative = "2"
116116
dirs = "3"
117117
either = "1.9"
118118
rust_eth_kzg = "0.5.1"
119-
discv5 = { version = "0.4.1", features = ["libp2p"] }
119+
discv5 = { version = "0.7", features = ["libp2p"] }
120120
env_logger = "0.9"
121121
error-chain = "0.12"
122122
ethereum_hashing = "0.7.0"

beacon_node/beacon_chain/src/attestation_rewards.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use state_processing::per_epoch_processing::altair::{
1111
};
1212
use state_processing::per_epoch_processing::base::rewards_and_penalties::{
1313
get_attestation_component_delta, get_attestation_deltas_all, get_attestation_deltas_subset,
14-
get_inactivity_penalty_delta, get_inclusion_delay_delta,
14+
get_inactivity_penalty_delta, get_inclusion_delay_delta, ProposerRewardCalculation,
1515
};
1616
use state_processing::per_epoch_processing::base::validator_statuses::InclusionInfo;
1717
use state_processing::per_epoch_processing::base::{
@@ -81,13 +81,24 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
8181
self.compute_ideal_rewards_base(&state, &validator_statuses.total_balances)?;
8282

8383
let indices_to_attestation_delta = if validators.is_empty() {
84-
get_attestation_deltas_all(&state, &validator_statuses, spec)?
85-
.into_iter()
86-
.enumerate()
87-
.collect()
84+
get_attestation_deltas_all(
85+
&state,
86+
&validator_statuses,
87+
ProposerRewardCalculation::Exclude,
88+
spec,
89+
)?
90+
.into_iter()
91+
.enumerate()
92+
.collect()
8893
} else {
8994
let validator_indices = Self::validators_ids_to_indices(&mut state, validators)?;
90-
get_attestation_deltas_subset(&state, &validator_statuses, &validator_indices, spec)?
95+
get_attestation_deltas_subset(
96+
&state,
97+
&validator_statuses,
98+
ProposerRewardCalculation::Exclude,
99+
&validator_indices,
100+
spec,
101+
)?
91102
};
92103

93104
let mut total_rewards = vec![];

beacon_node/beacon_chain/src/beacon_block_reward.rs

Lines changed: 110 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
1-
use crate::{BeaconChain, BeaconChainError, BeaconChainTypes};
1+
use crate::{BeaconChain, BeaconChainError, BeaconChainTypes, StateSkipConfig};
2+
use attesting_indices_base::get_attesting_indices;
23
use eth2::lighthouse::StandardBlockReward;
3-
use operation_pool::RewardCache;
44
use safe_arith::SafeArith;
55
use slog::error;
6+
use state_processing::common::attesting_indices_base;
67
use state_processing::{
7-
common::{get_attestation_participation_flag_indices, get_attesting_indices_from_state},
8+
common::{
9+
base::{self, SqrtTotalActiveBalance},
10+
get_attestation_participation_flag_indices, get_attesting_indices_from_state,
11+
},
812
epoch_cache::initialize_epoch_cache,
913
per_block_processing::{
1014
altair::sync_committee::compute_sync_aggregate_rewards, get_slashable_indices,
1115
},
1216
};
17+
use std::collections::HashSet;
1318
use store::{
1419
consts::altair::{PARTICIPATION_FLAG_WEIGHTS, PROPOSER_WEIGHT, WEIGHT_DENOMINATOR},
1520
RelativeEpoch,
1621
};
17-
use types::{AbstractExecPayload, BeaconBlockRef, BeaconState, BeaconStateError, Hash256};
22+
use types::{AbstractExecPayload, BeaconBlockRef, BeaconState, BeaconStateError, EthSpec};
1823

1924
type BeaconBlockSubRewardValue = u64;
2025

2126
impl<T: BeaconChainTypes> BeaconChain<T> {
2227
pub fn compute_beacon_block_reward<Payload: AbstractExecPayload<T::EthSpec>>(
2328
&self,
2429
block: BeaconBlockRef<'_, T::EthSpec, Payload>,
25-
block_root: Hash256,
2630
state: &mut BeaconState<T::EthSpec>,
2731
) -> Result<StandardBlockReward, BeaconChainError> {
2832
if block.slot() != state.slot() {
@@ -33,15 +37,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
3337
state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
3438
initialize_epoch_cache(state, &self.spec)?;
3539

36-
self.compute_beacon_block_reward_with_cache(block, block_root, state)
40+
self.compute_beacon_block_reward_with_cache(block, state)
3741
}
3842

3943
// This should only be called after a committee cache has been built
4044
// for both the previous and current epoch
4145
fn compute_beacon_block_reward_with_cache<Payload: AbstractExecPayload<T::EthSpec>>(
4246
&self,
4347
block: BeaconBlockRef<'_, T::EthSpec, Payload>,
44-
block_root: Hash256,
4548
state: &BeaconState<T::EthSpec>,
4649
) -> Result<StandardBlockReward, BeaconChainError> {
4750
let proposer_index = block.proposer_index();
@@ -72,7 +75,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
7275
})?;
7376

7477
let block_attestation_reward = if let BeaconState::Base(_) = state {
75-
self.compute_beacon_block_attestation_reward_base(block, block_root, state)
78+
self.compute_beacon_block_attestation_reward_base(block, state)
7679
.map_err(|e| {
7780
error!(
7881
self.log,
@@ -169,19 +172,85 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
169172
fn compute_beacon_block_attestation_reward_base<Payload: AbstractExecPayload<T::EthSpec>>(
170173
&self,
171174
block: BeaconBlockRef<'_, T::EthSpec, Payload>,
172-
block_root: Hash256,
173175
state: &BeaconState<T::EthSpec>,
174176
) -> Result<BeaconBlockSubRewardValue, BeaconChainError> {
175-
// Call compute_block_reward in the base case
176-
// Since base does not have sync aggregate, we only grab attesation portion of the returned
177-
// value
178-
let mut reward_cache = RewardCache::default();
179-
let block_attestation_reward = self
180-
.compute_block_reward(block, block_root, state, &mut reward_cache, true)?
181-
.attestation_rewards
182-
.total;
183-
184-
Ok(block_attestation_reward)
177+
// In phase0, rewards for including attestations are awarded at epoch boundaries when the corresponding
178+
// attestations are contained in state.previous_epoch_attestations. So, if an attestation within this block has
179+
// target = previous_epoch, it is directly inserted into previous_epoch_attestations and we need the state at
180+
// the end of this epoch, or the attestation has target = current_epoch and thus we need the state at the end
181+
// of the next epoch.
182+
// We fetch these lazily, as only one might be needed depending on the block's content.
183+
let mut current_epoch_end = None;
184+
let mut next_epoch_end = None;
185+
186+
let epoch = block.epoch();
187+
let mut block_reward = 0;
188+
189+
let mut rewarded_attesters = HashSet::new();
190+
191+
for attestation in block.body().attestations() {
192+
let processing_epoch_end = if attestation.data().target.epoch == epoch {
193+
let next_epoch_end = match &mut next_epoch_end {
194+
Some(next_epoch_end) => next_epoch_end,
195+
None => {
196+
let state = self.state_at_slot(
197+
epoch.safe_add(1)?.end_slot(T::EthSpec::slots_per_epoch()),
198+
StateSkipConfig::WithoutStateRoots,
199+
)?;
200+
next_epoch_end.get_or_insert(state)
201+
}
202+
};
203+
204+
// If the next epoch end is no longer phase0, no proposer rewards are awarded, as Altair epoch boundry
205+
// processing kicks in. We check this here, as we know that current_epoch_end will always be phase0.
206+
if !matches!(next_epoch_end, BeaconState::Base(_)) {
207+
continue;
208+
}
209+
210+
next_epoch_end
211+
} else if attestation.data().target.epoch == epoch.safe_sub(1)? {
212+
match &mut current_epoch_end {
213+
Some(current_epoch_end) => current_epoch_end,
214+
None => {
215+
let state = self.state_at_slot(
216+
epoch.end_slot(T::EthSpec::slots_per_epoch()),
217+
StateSkipConfig::WithoutStateRoots,
218+
)?;
219+
current_epoch_end.get_or_insert(state)
220+
}
221+
}
222+
} else {
223+
return Err(BeaconChainError::BlockRewardAttestationError);
224+
};
225+
226+
let inclusion_delay = state.slot().safe_sub(attestation.data().slot)?.as_u64();
227+
let sqrt_total_active_balance =
228+
SqrtTotalActiveBalance::new(processing_epoch_end.get_total_active_balance()?);
229+
for attester in get_attesting_indices_from_state(state, attestation)? {
230+
let validator = processing_epoch_end.get_validator(attester as usize)?;
231+
if !validator.slashed
232+
&& !rewarded_attesters.contains(&attester)
233+
&& !has_earlier_attestation(
234+
state,
235+
processing_epoch_end,
236+
inclusion_delay,
237+
attester,
238+
)?
239+
{
240+
let base_reward = base::get_base_reward(
241+
validator.effective_balance,
242+
sqrt_total_active_balance,
243+
&self.spec,
244+
)?;
245+
let proposer_reward =
246+
base_reward.safe_div(self.spec.proposer_reward_quotient)?;
247+
block_reward.safe_add_assign(proposer_reward)?;
248+
rewarded_attesters.insert(attester);
249+
}
250+
}
251+
}
252+
253+
Ok(block_reward)
185254
}
186255

187256
fn compute_beacon_block_attestation_reward_altair_deneb<
@@ -244,3 +313,25 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
244313
Ok(total_proposer_reward)
245314
}
246315
}
316+
317+
fn has_earlier_attestation<E: EthSpec>(
318+
state: &BeaconState<E>,
319+
processing_epoch_end: &BeaconState<E>,
320+
inclusion_delay: u64,
321+
attester: u64,
322+
) -> Result<bool, BeaconChainError> {
323+
if inclusion_delay > 1 {
324+
for epoch_att in processing_epoch_end.previous_epoch_attestations()? {
325+
if epoch_att.inclusion_delay < inclusion_delay {
326+
let committee =
327+
state.get_beacon_committee(epoch_att.data.slot, epoch_att.data.index)?;
328+
let earlier_attesters =
329+
get_attesting_indices::<E>(committee.committee, &epoch_att.aggregation_bits)?;
330+
if earlier_attesters.contains(&attester) {
331+
return Ok(true);
332+
}
333+
}
334+
}
335+
}
336+
Ok(false)
337+
}

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5639,7 +5639,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
56395639
let mut ctxt = ConsensusContext::new(block.slot());
56405640

56415641
let consensus_block_value = self
5642-
.compute_beacon_block_reward(block.message(), Hash256::zero(), &mut state)
5642+
.compute_beacon_block_reward(block.message(), &mut state)
56435643
.map(|reward| reward.total)
56445644
.unwrap_or(0);
56455645

@@ -6987,32 +6987,18 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
69876987
&self,
69886988
block_root: &Hash256,
69896989
) -> Result<Option<(LightClientBootstrap<T::EthSpec>, ForkName)>, Error> {
6990-
let Some(block) = self.get_blinded_block(block_root)? else {
6991-
return Ok(None);
6992-
};
6993-
6994-
let (state_root, slot) = (block.state_root(), block.slot());
6995-
6996-
let Some(mut state) = self.get_state(&state_root, Some(slot))? else {
6997-
return Ok(None);
6998-
};
6990+
let head_state = &self.head().snapshot.beacon_state;
6991+
let finalized_period = head_state
6992+
.finalized_checkpoint()
6993+
.epoch
6994+
.sync_committee_period(&self.spec)?;
69996995

7000-
let fork_name = state
7001-
.fork_name(&self.spec)
7002-
.map_err(Error::InconsistentFork)?;
7003-
7004-
match fork_name {
7005-
ForkName::Altair
7006-
| ForkName::Bellatrix
7007-
| ForkName::Capella
7008-
| ForkName::Deneb
7009-
| ForkName::Electra => {
7010-
LightClientBootstrap::from_beacon_state(&mut state, &block, &self.spec)
7011-
.map(|bootstrap| Some((bootstrap, fork_name)))
7012-
.map_err(Error::LightClientError)
7013-
}
7014-
ForkName::Base => Err(Error::UnsupportedFork),
7015-
}
6996+
self.light_client_server_cache.get_light_client_bootstrap(
6997+
&self.store,
6998+
block_root,
6999+
finalized_period,
7000+
&self.spec,
7001+
)
70167002
}
70177003

70187004
pub fn metrics(&self) -> BeaconChainMetrics {

beacon_node/beacon_chain/src/errors.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,8 @@ pub enum BeaconChainError {
216216
UnableToPublish,
217217
UnableToBuildColumnSidecar(String),
218218
AvailabilityCheckError(AvailabilityCheckError),
219-
LightClientError(LightClientError),
219+
LightClientUpdateError(LightClientUpdateError),
220+
LightClientBootstrapError(String),
220221
UnsupportedFork,
221222
MilhouseError(MilhouseError),
222223
EmptyRpcCustodyColumns,
@@ -250,7 +251,7 @@ easy_from_to!(BlockReplayError, BeaconChainError);
250251
easy_from_to!(InconsistentFork, BeaconChainError);
251252
easy_from_to!(AvailabilityCheckError, BeaconChainError);
252253
easy_from_to!(EpochCacheError, BeaconChainError);
253-
easy_from_to!(LightClientError, BeaconChainError);
254+
easy_from_to!(LightClientUpdateError, BeaconChainError);
254255
easy_from_to!(MilhouseError, BeaconChainError);
255256
easy_from_to!(AttestationError, BeaconChainError);
256257

0 commit comments

Comments
 (0)