forked from sigp/lighthouse
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathblock_reward.rs
More file actions
131 lines (114 loc) · 4.5 KB
/
Copy pathblock_reward.rs
File metadata and controls
131 lines (114 loc) · 4.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use crate::{BeaconChain, BeaconChainError, BeaconChainTypes};
use eth2::lighthouse::{AttestationRewards, BlockReward, BlockRewardMeta};
use operation_pool::{AttMaxCover, MaxCover, RewardCache, SplitAttestation};
use state_processing::{
common::get_attesting_indices_from_state,
per_block_processing::altair::sync_committee::compute_sync_aggregate_rewards,
};
use types::{AbstractExecPayload, BeaconBlockRef, BeaconState, EthSpec, Hash256};
impl<T: BeaconChainTypes> BeaconChain<T> {
pub fn compute_block_reward<Payload: AbstractExecPayload<T::EthSpec>>(
&self,
block: BeaconBlockRef<'_, T::EthSpec, Payload>,
block_root: Hash256,
state: &BeaconState<T::EthSpec>,
reward_cache: &mut RewardCache,
include_attestations: bool,
) -> Result<BlockReward, BeaconChainError> {
if block.slot() != state.slot() {
return Err(BeaconChainError::BlockRewardSlotError);
}
reward_cache.update(state)?;
let total_active_balance = state.get_total_active_balance()?;
let split_attestations = block
.body()
.attestations()
.iter()
.map(|att| {
let attesting_indices = get_attesting_indices_from_state(state, att)?;
Ok(SplitAttestation::new(att.clone(), attesting_indices))
})
.collect::<Result<Vec<_>, BeaconChainError>>()?;
let mut per_attestation_rewards = split_attestations
.iter()
.map(|att| {
AttMaxCover::new(
att.as_ref(),
state,
reward_cache,
total_active_balance,
&self.spec,
)
.ok_or(BeaconChainError::BlockRewardAttestationError)
})
.collect::<Result<Vec<_>, _>>()?;
// Update the attestation rewards for each previous attestation included.
// This is O(n^2) in the number of attestations n.
for i in 0..per_attestation_rewards.len() {
let (updated, to_update) = per_attestation_rewards.split_at_mut(i + 1);
let latest_att = &updated[i];
for att in to_update {
att.update_covering_set(latest_att.intermediate(), latest_att.covering_set());
}
}
let mut prev_epoch_total = 0;
let mut curr_epoch_total = 0;
for cover in &per_attestation_rewards {
for &reward in cover.fresh_validators_rewards.values() {
if cover.att.data.slot.epoch(T::EthSpec::slots_per_epoch()) == state.current_epoch()
{
curr_epoch_total += reward;
} else {
prev_epoch_total += reward;
}
}
}
let attestation_total = prev_epoch_total + curr_epoch_total;
// Drop the covers.
let per_attestation_rewards = per_attestation_rewards
.into_iter()
.map(|cover| cover.fresh_validators_rewards)
.collect();
// Add the attestation data if desired.
let attestations = if include_attestations {
block
.body()
.attestations()
.iter()
.map(|a| a.data.clone())
.collect()
} else {
vec![]
};
let attestation_rewards = AttestationRewards {
total: attestation_total,
prev_epoch_total,
curr_epoch_total,
per_attestation_rewards,
attestations,
};
// Sync committee rewards.
let sync_committee_rewards = if let Ok(sync_aggregate) = block.body().sync_aggregate() {
let (_, proposer_reward_per_bit) = compute_sync_aggregate_rewards(state, &self.spec)
.map_err(|_| BeaconChainError::BlockRewardSyncError)?;
sync_aggregate.sync_committee_bits.num_set_bits() as u64 * proposer_reward_per_bit
} else {
0
};
// Total, metadata
let total = attestation_total + sync_committee_rewards;
let meta = BlockRewardMeta {
slot: block.slot(),
parent_slot: state.latest_block_header().slot,
proposer_index: block.proposer_index(),
graffiti: block.body().graffiti().as_utf8_lossy(),
};
Ok(BlockReward {
total,
block_root,
meta,
attestation_rewards,
sync_committee_rewards,
})
}
}