Update op_pool to use proper rewards (#707)
* Update op_pool to use proper rewards * Fix missing use import for tests * Address Michael's comments * Revert to private ValidatorStatuses * Rename variable for clearer code * Fix update_cover function * Remove expect * Add WIP test for rewards * Use aggregation_bits instead of earliest_attestation_validators * Use earliest attestation in test and correct typo * Fix op_pool test thanks to @michaelsproul 's help * Change test name
This commit is contained in:
parent
4632e9ce52
commit
1abb964652
@ -10,6 +10,7 @@ use crate::persisted_beacon_chain::{PersistedBeaconChain, BEACON_CHAIN_DB_KEY};
|
|||||||
use crate::timeout_rw_lock::TimeoutRwLock;
|
use crate::timeout_rw_lock::TimeoutRwLock;
|
||||||
use lmd_ghost::LmdGhost;
|
use lmd_ghost::LmdGhost;
|
||||||
use operation_pool::{OperationPool, PersistedOperationPool};
|
use operation_pool::{OperationPool, PersistedOperationPool};
|
||||||
|
use parking_lot::RwLock;
|
||||||
use slog::{debug, error, info, trace, warn, Logger};
|
use slog::{debug, error, info, trace, warn, Logger};
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use ssz::Encode;
|
use ssz::Encode;
|
||||||
@ -1514,7 +1515,11 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
|
|||||||
graffiti,
|
graffiti,
|
||||||
proposer_slashings: proposer_slashings.into(),
|
proposer_slashings: proposer_slashings.into(),
|
||||||
attester_slashings: attester_slashings.into(),
|
attester_slashings: attester_slashings.into(),
|
||||||
attestations: self.op_pool.get_attestations(&state, &self.spec).into(),
|
attestations: self
|
||||||
|
.op_pool
|
||||||
|
.get_attestations(&state, &self.spec)
|
||||||
|
.map_err(BlockProductionError::OpPoolError)?
|
||||||
|
.into(),
|
||||||
deposits,
|
deposits,
|
||||||
voluntary_exits: self.op_pool.get_voluntary_exits(&state, &self.spec).into(),
|
voluntary_exits: self.op_pool.get_voluntary_exits(&state, &self.spec).into(),
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::eth1_chain::Error as Eth1ChainError;
|
use crate::eth1_chain::Error as Eth1ChainError;
|
||||||
use crate::fork_choice::Error as ForkChoiceError;
|
use crate::fork_choice::Error as ForkChoiceError;
|
||||||
|
use operation_pool::OpPoolError;
|
||||||
use ssz_types::Error as SszTypesError;
|
use ssz_types::Error as SszTypesError;
|
||||||
use state_processing::per_block_processing::errors::AttestationValidationError;
|
use state_processing::per_block_processing::errors::AttestationValidationError;
|
||||||
use state_processing::BlockProcessingError;
|
use state_processing::BlockProcessingError;
|
||||||
@ -67,6 +68,7 @@ pub enum BlockProductionError {
|
|||||||
BlockProcessingError(BlockProcessingError),
|
BlockProcessingError(BlockProcessingError),
|
||||||
Eth1ChainError(Eth1ChainError),
|
Eth1ChainError(Eth1ChainError),
|
||||||
BeaconStateError(BeaconStateError),
|
BeaconStateError(BeaconStateError),
|
||||||
|
OpPoolError(OpPoolError),
|
||||||
/// The `BeaconChain` was explicitly configured _without_ a connection to eth1, therefore it
|
/// The `BeaconChain` was explicitly configured _without_ a connection to eth1, therefore it
|
||||||
/// cannot produce blocks.
|
/// cannot produce blocks.
|
||||||
NoEth1ChainConnection,
|
NoEth1ChainConnection,
|
||||||
|
@ -1,35 +1,52 @@
|
|||||||
use crate::max_cover::MaxCover;
|
use crate::max_cover::MaxCover;
|
||||||
use types::{Attestation, BeaconState, BitList, EthSpec};
|
use state_processing::common::{get_attesting_indices, get_base_reward};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use types::{Attestation, BeaconState, BitList, ChainSpec, EthSpec};
|
||||||
|
|
||||||
pub struct AttMaxCover<'a, T: EthSpec> {
|
pub struct AttMaxCover<'a, T: EthSpec> {
|
||||||
/// Underlying attestation.
|
/// Underlying attestation.
|
||||||
att: &'a Attestation<T>,
|
att: &'a Attestation<T>,
|
||||||
/// Bitfield of validators that are covered by this attestation.
|
/// Mapping of validator indices and their rewards.
|
||||||
fresh_validators: BitList<T::MaxValidatorsPerCommittee>,
|
fresh_validators_rewards: HashMap<u64, u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: EthSpec> AttMaxCover<'a, T> {
|
impl<'a, T: EthSpec> AttMaxCover<'a, T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
att: &'a Attestation<T>,
|
att: &'a Attestation<T>,
|
||||||
fresh_validators: BitList<T::MaxValidatorsPerCommittee>,
|
state: &BeaconState<T>,
|
||||||
) -> Self {
|
total_active_balance: u64,
|
||||||
Self {
|
spec: &ChainSpec,
|
||||||
|
) -> Option<Self> {
|
||||||
|
let fresh_validators = earliest_attestation_validators(att, state);
|
||||||
|
let indices = get_attesting_indices(state, &att.data, &fresh_validators).ok()?;
|
||||||
|
let fresh_validators_rewards: HashMap<u64, u64> = indices
|
||||||
|
.iter()
|
||||||
|
.map(|i| *i as u64)
|
||||||
|
.flat_map(|validator_index| {
|
||||||
|
let reward =
|
||||||
|
get_base_reward(state, validator_index as usize, total_active_balance, spec)
|
||||||
|
.ok()?
|
||||||
|
/ spec.proposer_reward_quotient;
|
||||||
|
Some((validator_index, reward))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
Some(Self {
|
||||||
att,
|
att,
|
||||||
fresh_validators,
|
fresh_validators_rewards,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: EthSpec> MaxCover for AttMaxCover<'a, T> {
|
impl<'a, T: EthSpec> MaxCover for AttMaxCover<'a, T> {
|
||||||
type Object = Attestation<T>;
|
type Object = Attestation<T>;
|
||||||
type Set = BitList<T::MaxValidatorsPerCommittee>;
|
type Set = HashMap<u64, u64>;
|
||||||
|
|
||||||
fn object(&self) -> Attestation<T> {
|
fn object(&self) -> Attestation<T> {
|
||||||
self.att.clone()
|
self.att.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn covering_set(&self) -> &BitList<T::MaxValidatorsPerCommittee> {
|
fn covering_set(&self) -> &HashMap<u64, u64> {
|
||||||
&self.fresh_validators
|
&self.fresh_validators_rewards
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sneaky: we keep all the attestations together in one bucket, even though
|
/// Sneaky: we keep all the attestations together in one bucket, even though
|
||||||
@ -40,15 +57,16 @@ impl<'a, T: EthSpec> MaxCover for AttMaxCover<'a, T> {
|
|||||||
fn update_covering_set(
|
fn update_covering_set(
|
||||||
&mut self,
|
&mut self,
|
||||||
best_att: &Attestation<T>,
|
best_att: &Attestation<T>,
|
||||||
covered_validators: &BitList<T::MaxValidatorsPerCommittee>,
|
covered_validators: &HashMap<u64, u64>,
|
||||||
) {
|
) {
|
||||||
if self.att.data.slot == best_att.data.slot && self.att.data.index == best_att.data.index {
|
if self.att.data.slot == best_att.data.slot && self.att.data.index == best_att.data.index {
|
||||||
self.fresh_validators.difference_inplace(covered_validators);
|
self.fresh_validators_rewards
|
||||||
|
.retain(|k, _| !covered_validators.contains_key(k))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn score(&self) -> usize {
|
fn score(&self) -> usize {
|
||||||
self.fresh_validators.num_set_bits()
|
self.fresh_validators_rewards.values().sum::<u64>() as usize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ mod persistence;
|
|||||||
|
|
||||||
pub use persistence::PersistedOperationPool;
|
pub use persistence::PersistedOperationPool;
|
||||||
|
|
||||||
use attestation::{earliest_attestation_validators, AttMaxCover};
|
use attestation::AttMaxCover;
|
||||||
use attestation_id::AttestationId;
|
use attestation_id::AttestationId;
|
||||||
use max_cover::maximum_cover;
|
use max_cover::maximum_cover;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
@ -21,8 +21,8 @@ use state_processing::per_block_processing::{
|
|||||||
use std::collections::{hash_map, HashMap, HashSet};
|
use std::collections::{hash_map, HashMap, HashSet};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use types::{
|
use types::{
|
||||||
typenum::Unsigned, Attestation, AttesterSlashing, BeaconState, ChainSpec, EthSpec,
|
typenum::Unsigned, Attestation, AttesterSlashing, BeaconState, BeaconStateError, ChainSpec,
|
||||||
ProposerSlashing, Validator, VoluntaryExit,
|
EthSpec, ProposerSlashing, RelativeEpoch, Validator, VoluntaryExit,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
@ -38,6 +38,11 @@ pub struct OperationPool<T: EthSpec + Default> {
|
|||||||
_phantom: PhantomData<T>,
|
_phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum OpPoolError {
|
||||||
|
GetAttestationsTotalBalanceError(BeaconStateError),
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: EthSpec> OperationPool<T> {
|
impl<T: EthSpec> OperationPool<T> {
|
||||||
/// Create a new operation pool.
|
/// Create a new operation pool.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@ -95,13 +100,19 @@ impl<T: EthSpec> OperationPool<T> {
|
|||||||
&self,
|
&self,
|
||||||
state: &BeaconState<T>,
|
state: &BeaconState<T>,
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
) -> Vec<Attestation<T>> {
|
) -> Result<Vec<Attestation<T>>, OpPoolError> {
|
||||||
// Attestations for the current fork, which may be from the current or previous epoch.
|
// Attestations for the current fork, which may be from the current or previous epoch.
|
||||||
let prev_epoch = state.previous_epoch();
|
let prev_epoch = state.previous_epoch();
|
||||||
let current_epoch = state.current_epoch();
|
let current_epoch = state.current_epoch();
|
||||||
let prev_domain_bytes = AttestationId::compute_domain_bytes(prev_epoch, state, spec);
|
let prev_domain_bytes = AttestationId::compute_domain_bytes(prev_epoch, state, spec);
|
||||||
let curr_domain_bytes = AttestationId::compute_domain_bytes(current_epoch, state, spec);
|
let curr_domain_bytes = AttestationId::compute_domain_bytes(current_epoch, state, spec);
|
||||||
let reader = self.attestations.read();
|
let reader = self.attestations.read();
|
||||||
|
let active_indices = state
|
||||||
|
.get_cached_active_validator_indices(RelativeEpoch::Current)
|
||||||
|
.map_err(OpPoolError::GetAttestationsTotalBalanceError)?;
|
||||||
|
let total_active_balance = state
|
||||||
|
.get_total_balance(&active_indices, spec)
|
||||||
|
.map_err(OpPoolError::GetAttestationsTotalBalanceError)?;
|
||||||
let valid_attestations = reader
|
let valid_attestations = reader
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(key, _)| {
|
.filter(|(key, _)| {
|
||||||
@ -119,9 +130,12 @@ impl<T: EthSpec> OperationPool<T> {
|
|||||||
)
|
)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
})
|
})
|
||||||
.map(|att| AttMaxCover::new(att, earliest_attestation_validators(att, state)));
|
.flat_map(|att| AttMaxCover::new(att, state, total_active_balance, spec));
|
||||||
|
|
||||||
maximum_cover(valid_attestations, T::MaxAttestations::to_usize())
|
Ok(maximum_cover(
|
||||||
|
valid_attestations,
|
||||||
|
T::MaxAttestations::to_usize(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove attestations which are too old to be included in a block.
|
/// Remove attestations which are too old to be included in a block.
|
||||||
@ -361,7 +375,10 @@ impl<T: EthSpec + Default> PartialEq for OperationPool<T> {
|
|||||||
// TODO: more tests
|
// TODO: more tests
|
||||||
#[cfg(all(test, not(debug_assertions)))]
|
#[cfg(all(test, not(debug_assertions)))]
|
||||||
mod release_tests {
|
mod release_tests {
|
||||||
|
use super::attestation::earliest_attestation_validators;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use state_processing::common::{get_attesting_indices, get_base_reward};
|
||||||
|
use std::collections::BTreeSet;
|
||||||
use types::test_utils::*;
|
use types::test_utils::*;
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
@ -522,12 +539,20 @@ mod release_tests {
|
|||||||
|
|
||||||
// Before the min attestation inclusion delay, get_attestations shouldn't return anything.
|
// Before the min attestation inclusion delay, get_attestations shouldn't return anything.
|
||||||
state.slot -= 1;
|
state.slot -= 1;
|
||||||
assert_eq!(op_pool.get_attestations(state, spec).len(), 0);
|
assert_eq!(
|
||||||
|
op_pool
|
||||||
|
.get_attestations(state, spec)
|
||||||
|
.expect("should have attestations")
|
||||||
|
.len(),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
// Then once the delay has elapsed, we should get a single aggregated attestation.
|
// Then once the delay has elapsed, we should get a single aggregated attestation.
|
||||||
state.slot += spec.min_attestation_inclusion_delay;
|
state.slot += spec.min_attestation_inclusion_delay;
|
||||||
|
|
||||||
let block_attestations = op_pool.get_attestations(state, spec);
|
let block_attestations = op_pool
|
||||||
|
.get_attestations(state, spec)
|
||||||
|
.expect("Should have block attestations");
|
||||||
assert_eq!(block_attestations.len(), committees.len());
|
assert_eq!(block_attestations.len(), committees.len());
|
||||||
|
|
||||||
let agg_att = &block_attestations[0];
|
let agg_att = &block_attestations[0];
|
||||||
@ -684,7 +709,9 @@ mod release_tests {
|
|||||||
assert!(op_pool.num_attestations() > max_attestations);
|
assert!(op_pool.num_attestations() > max_attestations);
|
||||||
|
|
||||||
state.slot += spec.min_attestation_inclusion_delay;
|
state.slot += spec.min_attestation_inclusion_delay;
|
||||||
let best_attestations = op_pool.get_attestations(state, spec);
|
let best_attestations = op_pool
|
||||||
|
.get_attestations(state, spec)
|
||||||
|
.expect("should have best attestations");
|
||||||
assert_eq!(best_attestations.len(), max_attestations);
|
assert_eq!(best_attestations.len(), max_attestations);
|
||||||
|
|
||||||
// All the best attestations should be signed by at least `big_step_size` (4) validators.
|
// All the best attestations should be signed by at least `big_step_size` (4) validators.
|
||||||
@ -692,4 +719,104 @@ mod release_tests {
|
|||||||
assert!(att.aggregation_bits.num_set_bits() >= big_step_size);
|
assert!(att.aggregation_bits.num_set_bits() >= big_step_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn attestation_rewards() {
|
||||||
|
let small_step_size = 2;
|
||||||
|
let big_step_size = 4;
|
||||||
|
|
||||||
|
let (ref mut state, ref keypairs, ref spec) =
|
||||||
|
attestation_test_state::<MainnetEthSpec>(big_step_size);
|
||||||
|
|
||||||
|
let op_pool = OperationPool::new();
|
||||||
|
|
||||||
|
let slot = state.slot - 1;
|
||||||
|
let committees = state
|
||||||
|
.get_beacon_committees_at_slot(slot)
|
||||||
|
.unwrap()
|
||||||
|
.into_iter()
|
||||||
|
.map(BeaconCommittee::into_owned)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let max_attestations = <MainnetEthSpec as EthSpec>::MaxAttestations::to_usize();
|
||||||
|
let target_committee_size = spec.target_committee_size as usize;
|
||||||
|
|
||||||
|
// Each validator will have a multiple of 1_000_000_000 wei.
|
||||||
|
// Safe from overflow unless there are about 18B validators (2^64 / 1_000_000_000).
|
||||||
|
for i in 0..state.validators.len() {
|
||||||
|
state.validators[i].effective_balance = 1_000_000_000 * i as u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
let insert_attestations = |bc: &OwnedBeaconCommittee, step_size| {
|
||||||
|
for i in (0..target_committee_size).step_by(step_size) {
|
||||||
|
let att = signed_attestation(
|
||||||
|
&bc.committee,
|
||||||
|
bc.index,
|
||||||
|
keypairs,
|
||||||
|
i..i + step_size,
|
||||||
|
slot,
|
||||||
|
state,
|
||||||
|
spec,
|
||||||
|
if i == 0 { None } else { Some(0) },
|
||||||
|
);
|
||||||
|
op_pool.insert_attestation(att, state, spec).unwrap();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for committee in &committees {
|
||||||
|
assert_eq!(committee.committee.len(), target_committee_size);
|
||||||
|
// Attestations signed by only 2-3 validators
|
||||||
|
insert_attestations(committee, small_step_size);
|
||||||
|
// Attestations signed by 4+ validators
|
||||||
|
insert_attestations(committee, big_step_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
let num_small = target_committee_size / small_step_size;
|
||||||
|
let num_big = target_committee_size / big_step_size;
|
||||||
|
|
||||||
|
assert_eq!(op_pool.attestations.read().len(), committees.len());
|
||||||
|
assert_eq!(
|
||||||
|
op_pool.num_attestations(),
|
||||||
|
(num_small + num_big) * committees.len()
|
||||||
|
);
|
||||||
|
assert!(op_pool.num_attestations() > max_attestations);
|
||||||
|
|
||||||
|
state.slot += spec.min_attestation_inclusion_delay;
|
||||||
|
let best_attestations = op_pool
|
||||||
|
.get_attestations(state, spec)
|
||||||
|
.expect("should have valid best attestations");
|
||||||
|
assert_eq!(best_attestations.len(), max_attestations);
|
||||||
|
|
||||||
|
let active_indices = state
|
||||||
|
.get_cached_active_validator_indices(RelativeEpoch::Current)
|
||||||
|
.unwrap();
|
||||||
|
let total_active_balance = state.get_total_balance(&active_indices, spec).unwrap();
|
||||||
|
|
||||||
|
// Set of indices covered by previous attestations in `best_attestations`.
|
||||||
|
let mut seen_indices = BTreeSet::new();
|
||||||
|
// Used for asserting that rewards are in decreasing order.
|
||||||
|
let mut prev_reward = u64::max_value();
|
||||||
|
|
||||||
|
for att in &best_attestations {
|
||||||
|
let fresh_validators_bitlist = earliest_attestation_validators(att, state);
|
||||||
|
let att_indices =
|
||||||
|
get_attesting_indices(state, &att.data, &fresh_validators_bitlist).unwrap();
|
||||||
|
let fresh_indices = &att_indices - &seen_indices;
|
||||||
|
|
||||||
|
let rewards = fresh_indices
|
||||||
|
.iter()
|
||||||
|
.map(|validator_index| {
|
||||||
|
get_base_reward(state, *validator_index as usize, total_active_balance, spec)
|
||||||
|
.unwrap()
|
||||||
|
/ spec.proposer_reward_quotient
|
||||||
|
})
|
||||||
|
.sum();
|
||||||
|
|
||||||
|
// Check that rewards are in decreasing order
|
||||||
|
assert!(prev_reward >= rewards);
|
||||||
|
|
||||||
|
prev_reward = rewards;
|
||||||
|
seen_indices.extend(fresh_indices);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
23
eth2/state_processing/src/common/get_base_reward.rs
Normal file
23
eth2/state_processing/src/common/get_base_reward.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use integer_sqrt::IntegerSquareRoot;
|
||||||
|
use types::*;
|
||||||
|
|
||||||
|
/// Returns the base reward for some validator.
|
||||||
|
///
|
||||||
|
/// Spec v0.9.1
|
||||||
|
pub fn get_base_reward<T: EthSpec>(
|
||||||
|
state: &BeaconState<T>,
|
||||||
|
index: usize,
|
||||||
|
// Should be == get_total_active_balance(state, spec)
|
||||||
|
total_active_balance: u64,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Result<u64, BeaconStateError> {
|
||||||
|
if total_active_balance == 0 {
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
Ok(
|
||||||
|
state.get_effective_balance(index, spec)? * spec.base_reward_factor
|
||||||
|
/ total_active_balance.integer_sqrt()
|
||||||
|
/ spec.base_rewards_per_epoch,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
mod get_attesting_indices;
|
mod get_attesting_indices;
|
||||||
|
mod get_base_reward;
|
||||||
mod get_indexed_attestation;
|
mod get_indexed_attestation;
|
||||||
mod initiate_validator_exit;
|
mod initiate_validator_exit;
|
||||||
mod slash_validator;
|
mod slash_validator;
|
||||||
|
|
||||||
pub use get_attesting_indices::get_attesting_indices;
|
pub use get_attesting_indices::get_attesting_indices;
|
||||||
|
pub use get_base_reward::get_base_reward;
|
||||||
pub use get_indexed_attestation::get_indexed_attestation;
|
pub use get_indexed_attestation::get_indexed_attestation;
|
||||||
pub use initiate_validator_exit::initiate_validator_exit;
|
pub use initiate_validator_exit::initiate_validator_exit;
|
||||||
pub use slash_validator::slash_validator;
|
pub use slash_validator::slash_validator;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
use super::super::common::get_base_reward;
|
||||||
use super::validator_statuses::{TotalBalances, ValidatorStatus, ValidatorStatuses};
|
use super::validator_statuses::{TotalBalances, ValidatorStatus, ValidatorStatuses};
|
||||||
use super::Error;
|
use super::Error;
|
||||||
use integer_sqrt::IntegerSquareRoot;
|
|
||||||
use types::*;
|
use types::*;
|
||||||
|
|
||||||
/// Use to track the changes to a validators balance.
|
/// Use to track the changes to a validators balance.
|
||||||
@ -211,24 +212,3 @@ fn get_attestation_delta<T: EthSpec>(
|
|||||||
|
|
||||||
delta
|
delta
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the base reward for some validator.
|
|
||||||
///
|
|
||||||
/// Spec v0.9.1
|
|
||||||
fn get_base_reward<T: EthSpec>(
|
|
||||||
state: &BeaconState<T>,
|
|
||||||
index: usize,
|
|
||||||
// Should be == get_total_active_balance(state, spec)
|
|
||||||
total_active_balance: u64,
|
|
||||||
spec: &ChainSpec,
|
|
||||||
) -> Result<u64, BeaconStateError> {
|
|
||||||
if total_active_balance == 0 {
|
|
||||||
Ok(0)
|
|
||||||
} else {
|
|
||||||
Ok(
|
|
||||||
state.get_effective_balance(index, spec)? * spec.base_reward_factor
|
|
||||||
/ total_active_balance.integer_sqrt()
|
|
||||||
/ spec.base_rewards_per_epoch,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user