mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-19 05:48:31 +00:00
Update state processing for v0.12
This commit is contained in:
@@ -36,7 +36,7 @@ fn worst_bench<T: EthSpec>(c: &mut Criterion, spec_desc: &str, validator_count:
|
||||
let mut spec = &mut T::default_spec();
|
||||
|
||||
// Allows the exits to be processed sucessfully.
|
||||
spec.persistent_committee_period = 0;
|
||||
spec.shard_committee_period = 0;
|
||||
|
||||
let (block, state) = get_worst_block(validator_count, spec);
|
||||
bench_block::<T>(c, block, state, spec, spec_desc, "high_complexity_block");
|
||||
|
||||
@@ -157,6 +157,15 @@ pub fn process_block_header<T: EthSpec>(
|
||||
// Verify that the slots match
|
||||
verify!(block.slot == state.slot, HeaderInvalid::StateSlotMismatch);
|
||||
|
||||
// Verify that the block is newer than the latest block header
|
||||
verify!(
|
||||
block.slot > state.latest_block_header.slot,
|
||||
HeaderInvalid::OlderThanLatestBlockHeader {
|
||||
block_slot: block.slot,
|
||||
latest_block_header_slot: state.latest_block_header.slot,
|
||||
}
|
||||
);
|
||||
|
||||
// Verify that proposer index is the correct index
|
||||
let proposer_index = block.proposer_index as usize;
|
||||
let state_proposer_index = state.get_beacon_proposer_index(block.slot, spec)?;
|
||||
|
||||
@@ -176,6 +176,10 @@ impl<T> From<ArithError> for BlockOperationError<T> {
|
||||
pub enum HeaderInvalid {
|
||||
ProposalSignatureInvalid,
|
||||
StateSlotMismatch,
|
||||
OlderThanLatestBlockHeader {
|
||||
latest_block_header_slot: Slot,
|
||||
block_slot: Slot,
|
||||
},
|
||||
ProposerIndexMismatch {
|
||||
block_proposer_index: usize,
|
||||
state_proposer_index: usize,
|
||||
@@ -255,9 +259,6 @@ pub enum AttestationInvalid {
|
||||
attestation: Checkpoint,
|
||||
is_current: bool,
|
||||
},
|
||||
/// There are no set bits on the attestation -- an attestation must be signed by at least one
|
||||
/// validator.
|
||||
AggregationBitfieldIsEmpty,
|
||||
/// The aggregation bitfield length is not the smallest possible size to represent the committee.
|
||||
BadAggregationBitfieldLength {
|
||||
committee_len: usize,
|
||||
@@ -291,10 +292,8 @@ impl From<BlockOperationError<IndexedAttestationInvalid>>
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum IndexedAttestationInvalid {
|
||||
/// The number of indices exceeds the global maximum.
|
||||
///
|
||||
/// (max_indices, indices_given)
|
||||
MaxIndicesExceed(usize, usize),
|
||||
/// The number of indices is 0.
|
||||
IndicesEmpty,
|
||||
/// The validator indices were not in increasing order.
|
||||
///
|
||||
/// The error occurred between the given `index` and `index + 1`
|
||||
|
||||
@@ -20,11 +20,8 @@ pub fn is_valid_indexed_attestation<T: EthSpec>(
|
||||
) -> Result<()> {
|
||||
let indices = &indexed_attestation.attesting_indices;
|
||||
|
||||
// Verify max number of indices
|
||||
verify!(
|
||||
indices.len() <= T::MaxValidatorsPerCommittee::to_usize(),
|
||||
Invalid::MaxIndicesExceed(T::MaxValidatorsPerCommittee::to_usize(), indices.len())
|
||||
);
|
||||
// Verify that indices aren't empty
|
||||
verify!(!indices.is_empty(), Invalid::IndicesEmpty);
|
||||
|
||||
// Check that indices are sorted and unique
|
||||
let check_sorted = |list: &[u64]| -> Result<()> {
|
||||
|
||||
@@ -11,7 +11,7 @@ use types::{
|
||||
AggregateSignature, AttesterSlashing, BeaconBlock, BeaconState, BeaconStateError, ChainSpec,
|
||||
DepositData, Domain, EthSpec, Fork, Hash256, IndexedAttestation, ProposerSlashing, PublicKey,
|
||||
Signature, SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockHeader, SignedRoot,
|
||||
SignedVoluntaryExit, SigningRoot,
|
||||
SignedVoluntaryExit, SigningData,
|
||||
};
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
@@ -92,7 +92,7 @@ where
|
||||
);
|
||||
|
||||
let message = if let Some(root) = block_root {
|
||||
SigningRoot {
|
||||
SigningData {
|
||||
object_root: root,
|
||||
domain,
|
||||
}
|
||||
|
||||
@@ -58,13 +58,6 @@ pub fn verify_attestation_for_state<T: EthSpec>(
|
||||
) -> Result<()> {
|
||||
let data = &attestation.data;
|
||||
|
||||
// This emptiness check is required *in addition* to the length check in `get_attesting_indices`
|
||||
// because we can parse a bitfield and know its length, even if it has no bits set.
|
||||
verify!(
|
||||
!attestation.aggregation_bits.is_zero(),
|
||||
Invalid::AggregationBitfieldIsEmpty
|
||||
);
|
||||
|
||||
verify!(
|
||||
data.index < state.get_committee_count_at_slot(data.slot)?,
|
||||
Invalid::BadCommitteeIndex
|
||||
|
||||
@@ -78,10 +78,10 @@ fn verify_exit_parametric<T: EthSpec>(
|
||||
|
||||
// Verify the validator has been active long enough.
|
||||
verify!(
|
||||
state.current_epoch() >= validator.activation_epoch + spec.persistent_committee_period,
|
||||
state.current_epoch() >= validator.activation_epoch + spec.shard_committee_period,
|
||||
ExitInvalid::TooYoungToExit {
|
||||
current_epoch: state.current_epoch(),
|
||||
earliest_exit_epoch: validator.activation_epoch + spec.persistent_committee_period,
|
||||
earliest_exit_epoch: validator.activation_epoch + spec.shard_committee_period,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -51,11 +51,7 @@ pub fn process_rewards_and_penalties<T: EthSpec>(
|
||||
return Err(Error::ValidatorStatusesInconsistent);
|
||||
}
|
||||
|
||||
let mut deltas = vec![Delta::default(); state.balances.len()];
|
||||
|
||||
get_attestation_deltas(&mut deltas, state, &validator_statuses, spec)?;
|
||||
|
||||
get_proposer_deltas(&mut deltas, state, validator_statuses, spec)?;
|
||||
let deltas = get_attestation_deltas(state, &validator_statuses, spec)?;
|
||||
|
||||
// Apply the deltas, erroring on overflow above but not on overflow below (saturating at 0
|
||||
// instead).
|
||||
@@ -67,78 +63,63 @@ pub fn process_rewards_and_penalties<T: EthSpec>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// For each attesting validator, reward the proposer who was first to include their attestation.
|
||||
///
|
||||
/// Spec v0.11.1
|
||||
fn get_proposer_deltas<T: EthSpec>(
|
||||
deltas: &mut Vec<Delta>,
|
||||
state: &BeaconState<T>,
|
||||
validator_statuses: &mut ValidatorStatuses,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
for (index, validator) in validator_statuses.statuses.iter().enumerate() {
|
||||
if validator.is_previous_epoch_attester && !validator.is_slashed {
|
||||
let inclusion = validator
|
||||
.inclusion_info
|
||||
.expect("It is a logic error for an attester not to have an inclusion delay.");
|
||||
|
||||
let base_reward = get_base_reward(
|
||||
state,
|
||||
index,
|
||||
validator_statuses.total_balances.current_epoch(),
|
||||
spec,
|
||||
)?;
|
||||
|
||||
if inclusion.proposer_index >= deltas.len() {
|
||||
return Err(Error::ValidatorStatusesInconsistent);
|
||||
}
|
||||
|
||||
deltas[inclusion.proposer_index]
|
||||
.reward(base_reward.safe_div(spec.proposer_reward_quotient)?)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Apply rewards for participation in attestations during the previous epoch.
|
||||
///
|
||||
/// Spec v0.11.1
|
||||
fn get_attestation_deltas<T: EthSpec>(
|
||||
deltas: &mut Vec<Delta>,
|
||||
state: &BeaconState<T>,
|
||||
validator_statuses: &ValidatorStatuses,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<Vec<Delta>, Error> {
|
||||
let finality_delay = (state.previous_epoch() - state.finalized_checkpoint.epoch).as_u64();
|
||||
|
||||
for (index, validator) in validator_statuses.statuses.iter().enumerate() {
|
||||
let base_reward = get_base_reward(
|
||||
state,
|
||||
index,
|
||||
validator_statuses.total_balances.current_epoch(),
|
||||
spec,
|
||||
)?;
|
||||
let mut deltas = vec![Delta::default(); state.validators.len()];
|
||||
|
||||
let delta = get_attestation_delta::<T>(
|
||||
&validator,
|
||||
&validator_statuses.total_balances,
|
||||
base_reward,
|
||||
finality_delay,
|
||||
spec,
|
||||
)?;
|
||||
let total_balances = &validator_statuses.total_balances;
|
||||
|
||||
deltas[index].combine(delta)?;
|
||||
// Filter out ineligible validators. All sub-functions of the spec do this except for
|
||||
// `get_inclusion_delay_deltas`. It's safe to do so here because any validator that is in the
|
||||
// unslashed indices of the matching source attestations is active, and therefore eligible.
|
||||
for (index, validator) in validator_statuses
|
||||
.statuses
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, validator)| is_eligible_validator(validator))
|
||||
{
|
||||
let base_reward = get_base_reward(state, index, total_balances.current_epoch(), spec)?;
|
||||
|
||||
let source_delta =
|
||||
get_source_delta(validator, base_reward, total_balances, finality_delay, spec)?;
|
||||
let target_delta =
|
||||
get_target_delta(validator, base_reward, total_balances, finality_delay, spec)?;
|
||||
let head_delta =
|
||||
get_head_delta(validator, base_reward, total_balances, finality_delay, spec)?;
|
||||
let (inclusion_delay_delta, proposer_delta) =
|
||||
get_inclusion_delay_delta(validator, base_reward, spec)?;
|
||||
let inactivity_penalty_delta =
|
||||
get_inactivity_penalty_delta(validator, base_reward, finality_delay, spec)?;
|
||||
|
||||
deltas[index].combine(source_delta)?;
|
||||
deltas[index].combine(target_delta)?;
|
||||
deltas[index].combine(head_delta)?;
|
||||
deltas[index].combine(inclusion_delay_delta)?;
|
||||
deltas[index].combine(inactivity_penalty_delta)?;
|
||||
|
||||
if let Some((proposer_index, proposer_delta)) = proposer_delta {
|
||||
if proposer_index >= deltas.len() {
|
||||
return Err(Error::ValidatorStatusesInconsistent);
|
||||
}
|
||||
|
||||
deltas[proposer_index].combine(proposer_delta)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(deltas)
|
||||
}
|
||||
|
||||
/// Determine the delta for a single validator, sans proposer rewards.
|
||||
///
|
||||
/// Spec v0.11.1
|
||||
fn get_attestation_delta<T: EthSpec>(
|
||||
validator: &ValidatorStatus,
|
||||
fn get_attestation_component_delta(
|
||||
index_in_unslashed_attesting_indices: bool,
|
||||
attesting_balance: u64,
|
||||
total_balances: &TotalBalances,
|
||||
base_reward: u64,
|
||||
finality_delay: u64,
|
||||
@@ -146,83 +127,122 @@ fn get_attestation_delta<T: EthSpec>(
|
||||
) -> Result<Delta, Error> {
|
||||
let mut delta = Delta::default();
|
||||
|
||||
// Is this validator eligible to be rewarded or penalized?
|
||||
// Spec: validator index in `eligible_validator_indices`
|
||||
let is_eligible = validator.is_active_in_previous_epoch
|
||||
|| (validator.is_slashed && !validator.is_withdrawable_in_current_epoch);
|
||||
let total_balance = total_balances.current_epoch();
|
||||
|
||||
if !is_eligible {
|
||||
return Ok(delta);
|
||||
if index_in_unslashed_attesting_indices {
|
||||
if finality_delay > spec.min_epochs_to_inactivity_penalty {
|
||||
// Since full base reward will be canceled out by inactivity penalty deltas,
|
||||
// optimal participation receives full base reward compensation here.
|
||||
delta.reward(base_reward)?;
|
||||
} else {
|
||||
let reward_numerator = base_reward
|
||||
.safe_mul(attesting_balance.safe_div(spec.effective_balance_increment)?)?;
|
||||
delta.reward(
|
||||
reward_numerator
|
||||
.safe_div(total_balance.safe_div(spec.effective_balance_increment)?)?,
|
||||
)?;
|
||||
}
|
||||
} else {
|
||||
delta.penalize(base_reward)?;
|
||||
}
|
||||
|
||||
// Handle integer overflow by dividing these quantities by EFFECTIVE_BALANCE_INCREMENT
|
||||
// Spec:
|
||||
// - increment = EFFECTIVE_BALANCE_INCREMENT
|
||||
// - reward_numerator = get_base_reward(state, index) * (attesting_balance // increment)
|
||||
// - rewards[index] = reward_numerator // (total_balance // increment)
|
||||
let total_balance_ebi = total_balances
|
||||
.current_epoch()
|
||||
.safe_div(spec.effective_balance_increment)?;
|
||||
let total_attesting_balance_ebi = total_balances
|
||||
.previous_epoch_attesters()
|
||||
.safe_div(spec.effective_balance_increment)?;
|
||||
let matching_target_balance_ebi = total_balances
|
||||
.previous_epoch_target_attesters()
|
||||
.safe_div(spec.effective_balance_increment)?;
|
||||
let matching_head_balance_ebi = total_balances
|
||||
.previous_epoch_head_attesters()
|
||||
.safe_div(spec.effective_balance_increment)?;
|
||||
Ok(delta)
|
||||
}
|
||||
|
||||
// Expected FFG source.
|
||||
// Spec:
|
||||
// - validator index in `get_unslashed_attesting_indices(state, matching_source_attestations)`
|
||||
fn get_source_delta(
|
||||
validator: &ValidatorStatus,
|
||||
base_reward: u64,
|
||||
total_balances: &TotalBalances,
|
||||
finality_delay: u64,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Delta, Error> {
|
||||
get_attestation_component_delta(
|
||||
validator.is_previous_epoch_attester && !validator.is_slashed,
|
||||
total_balances.previous_epoch_attesters(),
|
||||
total_balances,
|
||||
base_reward,
|
||||
finality_delay,
|
||||
spec,
|
||||
)
|
||||
}
|
||||
|
||||
fn get_target_delta(
|
||||
validator: &ValidatorStatus,
|
||||
base_reward: u64,
|
||||
total_balances: &TotalBalances,
|
||||
finality_delay: u64,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Delta, Error> {
|
||||
get_attestation_component_delta(
|
||||
validator.is_previous_epoch_target_attester && !validator.is_slashed,
|
||||
total_balances.previous_epoch_target_attesters(),
|
||||
total_balances,
|
||||
base_reward,
|
||||
finality_delay,
|
||||
spec,
|
||||
)
|
||||
}
|
||||
|
||||
fn get_head_delta(
|
||||
validator: &ValidatorStatus,
|
||||
base_reward: u64,
|
||||
total_balances: &TotalBalances,
|
||||
finality_delay: u64,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Delta, Error> {
|
||||
get_attestation_component_delta(
|
||||
validator.is_previous_epoch_head_attester && !validator.is_slashed,
|
||||
total_balances.previous_epoch_head_attesters(),
|
||||
total_balances,
|
||||
base_reward,
|
||||
finality_delay,
|
||||
spec,
|
||||
)
|
||||
}
|
||||
|
||||
fn get_inclusion_delay_delta(
|
||||
validator: &ValidatorStatus,
|
||||
base_reward: u64,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(Delta, Option<(usize, Delta)>), Error> {
|
||||
// Spec: `index in get_unslashed_attesting_indices(state, matching_source_attestations)`
|
||||
if validator.is_previous_epoch_attester && !validator.is_slashed {
|
||||
delta.reward(
|
||||
base_reward
|
||||
.safe_mul(total_attesting_balance_ebi)?
|
||||
.safe_div(total_balance_ebi)?,
|
||||
)?;
|
||||
// Inclusion speed bonus
|
||||
let proposer_reward = base_reward.safe_div(spec.proposer_reward_quotient)?;
|
||||
let max_attester_reward = base_reward.safe_sub(proposer_reward)?;
|
||||
let inclusion = validator
|
||||
let mut delta = Delta::default();
|
||||
let mut proposer_delta = Delta::default();
|
||||
|
||||
let inclusion_info = validator
|
||||
.inclusion_info
|
||||
.expect("It is a logic error for an attester not to have an inclusion delay.");
|
||||
delta.reward(max_attester_reward.safe_div(inclusion.delay)?)?;
|
||||
} else {
|
||||
delta.penalize(base_reward)?;
|
||||
}
|
||||
.ok_or(Error::ValidatorStatusesInconsistent)?;
|
||||
|
||||
// Expected FFG target.
|
||||
// Spec:
|
||||
// - validator index in `get_unslashed_attesting_indices(state, matching_target_attestations)`
|
||||
if validator.is_previous_epoch_target_attester && !validator.is_slashed {
|
||||
delta.reward(
|
||||
base_reward
|
||||
.safe_mul(matching_target_balance_ebi)?
|
||||
.safe_div(total_balance_ebi)?,
|
||||
)?;
|
||||
} else {
|
||||
delta.penalize(base_reward)?;
|
||||
}
|
||||
let proposer_reward = get_proposer_reward(base_reward, spec)?;
|
||||
proposer_delta.reward(proposer_reward)?;
|
||||
|
||||
// Expected head.
|
||||
// Spec:
|
||||
// - validator index in `get_unslashed_attesting_indices(state, matching_head_attestations)`
|
||||
if validator.is_previous_epoch_head_attester && !validator.is_slashed {
|
||||
delta.reward(
|
||||
base_reward
|
||||
.safe_mul(matching_head_balance_ebi)?
|
||||
.safe_div(total_balance_ebi)?,
|
||||
)?;
|
||||
let max_attester_reward = base_reward.safe_sub(proposer_reward)?;
|
||||
delta.reward(max_attester_reward.safe_div(inclusion_info.delay)?)?;
|
||||
|
||||
let proposer_index = inclusion_info.proposer_index as usize;
|
||||
Ok((delta, Some((proposer_index, proposer_delta))))
|
||||
} else {
|
||||
delta.penalize(base_reward)?;
|
||||
Ok((Delta::default(), None))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_inactivity_penalty_delta(
|
||||
validator: &ValidatorStatus,
|
||||
base_reward: u64,
|
||||
finality_delay: u64,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Delta, Error> {
|
||||
let mut delta = Delta::default();
|
||||
|
||||
// Inactivity penalty
|
||||
if finality_delay > spec.min_epochs_to_inactivity_penalty {
|
||||
// All eligible validators are penalized
|
||||
delta.penalize(spec.base_rewards_per_epoch.safe_mul(base_reward)?)?;
|
||||
// If validator is performing optimally this cancels all rewards for a neutral balance
|
||||
delta.penalize(
|
||||
spec.base_rewards_per_epoch
|
||||
.safe_mul(base_reward)?
|
||||
.safe_sub(get_proposer_reward(base_reward, spec)?)?,
|
||||
)?;
|
||||
|
||||
// Additionally, all validators whose FFG target didn't match are penalized extra
|
||||
// This condition is equivalent to this condition from the spec:
|
||||
@@ -237,10 +257,20 @@ fn get_attestation_delta<T: EthSpec>(
|
||||
}
|
||||
}
|
||||
|
||||
// Proposer bonus is handled in `get_proposer_deltas`.
|
||||
//
|
||||
// This function only computes the delta for a single validator, so it cannot also return a
|
||||
// delta for a validator.
|
||||
|
||||
Ok(delta)
|
||||
}
|
||||
|
||||
/// Compute the reward awarded to a proposer for including an attestation from a validator.
|
||||
///
|
||||
/// The `base_reward` param should be the `base_reward` of the attesting validator.
|
||||
fn get_proposer_reward(base_reward: u64, spec: &ChainSpec) -> Result<u64, Error> {
|
||||
Ok(base_reward.safe_div(spec.proposer_reward_quotient)?)
|
||||
}
|
||||
|
||||
/// Is the validator eligible for penalties and rewards at the current epoch?
|
||||
///
|
||||
/// Spec: v0.12.0
|
||||
fn is_eligible_validator(validator: &ValidatorStatus) -> bool {
|
||||
validator.is_active_in_previous_epoch
|
||||
|| (validator.is_slashed && !validator.is_withdrawable_in_current_epoch)
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ pub struct ValidatorStatus {
|
||||
/// True if the validator has been slashed, ever.
|
||||
pub is_slashed: bool,
|
||||
/// True if the validator can withdraw in the current epoch.
|
||||
// FIXME(sproul): refactor to use withdrawable epoch directly (to match spec).
|
||||
pub is_withdrawable_in_current_epoch: bool,
|
||||
/// True if the validator was active in the state's _current_ epoch.
|
||||
pub is_active_in_current_epoch: bool,
|
||||
|
||||
@@ -215,7 +215,7 @@ mod signatures_minimal {
|
||||
let mut spec = &mut TestEthSpec::default_spec();
|
||||
|
||||
// Allows the test to pass.
|
||||
spec.persistent_committee_period = 0;
|
||||
spec.shard_committee_period = 0;
|
||||
|
||||
test_scenario::<TestEthSpec, _, _>(
|
||||
|mut builder| {
|
||||
|
||||
@@ -82,7 +82,7 @@ pub struct ChainSpec {
|
||||
pub max_seed_lookahead: Epoch,
|
||||
pub min_epochs_to_inactivity_penalty: u64,
|
||||
pub min_validator_withdrawability_delay: Epoch,
|
||||
pub persistent_committee_period: u64,
|
||||
pub shard_committee_period: u64,
|
||||
|
||||
/*
|
||||
* Reward and penalty quotients
|
||||
@@ -292,7 +292,7 @@ impl ChainSpec {
|
||||
max_seed_lookahead: Epoch::new(4),
|
||||
min_epochs_to_inactivity_penalty: 4,
|
||||
min_validator_withdrawability_delay: Epoch::new(256),
|
||||
persistent_committee_period: 2_048,
|
||||
shard_committee_period: 256,
|
||||
|
||||
/*
|
||||
* Reward and penalty quotients
|
||||
@@ -300,7 +300,7 @@ impl ChainSpec {
|
||||
base_reward_factor: 64,
|
||||
whistleblower_reward_quotient: 512,
|
||||
proposer_reward_quotient: 8,
|
||||
inactivity_penalty_quotient: 33_554_432,
|
||||
inactivity_penalty_quotient: u64::pow(2, 24),
|
||||
min_slashing_penalty_quotient: 32,
|
||||
|
||||
/*
|
||||
@@ -353,7 +353,7 @@ impl ChainSpec {
|
||||
min_genesis_active_validator_count: 64,
|
||||
eth1_follow_distance: 16,
|
||||
genesis_fork_version: [0x00, 0x00, 0x00, 0x01],
|
||||
persistent_committee_period: 128,
|
||||
shard_committee_period: 64,
|
||||
min_genesis_delay: 300,
|
||||
milliseconds_per_slot: 6_000,
|
||||
safe_slots_to_update_justified: 2,
|
||||
@@ -481,7 +481,7 @@ pub struct YamlConfig {
|
||||
max_seed_lookahead: u64,
|
||||
min_epochs_to_inactivity_penalty: u64,
|
||||
min_validator_withdrawability_delay: u64,
|
||||
persistent_committee_period: u64,
|
||||
shard_committee_period: u64,
|
||||
base_reward_factor: u64,
|
||||
whistleblower_reward_quotient: u64,
|
||||
proposer_reward_quotient: u64,
|
||||
@@ -591,7 +591,7 @@ impl YamlConfig {
|
||||
min_seed_lookahead: spec.min_seed_lookahead.into(),
|
||||
max_seed_lookahead: spec.max_seed_lookahead.into(),
|
||||
min_validator_withdrawability_delay: spec.min_validator_withdrawability_delay.into(),
|
||||
persistent_committee_period: spec.persistent_committee_period,
|
||||
shard_committee_period: spec.shard_committee_period,
|
||||
min_epochs_to_inactivity_penalty: spec.min_epochs_to_inactivity_penalty,
|
||||
base_reward_factor: spec.base_reward_factor,
|
||||
whistleblower_reward_quotient: spec.whistleblower_reward_quotient,
|
||||
@@ -690,7 +690,7 @@ impl YamlConfig {
|
||||
min_validator_withdrawability_delay: Epoch::from(
|
||||
self.min_validator_withdrawability_delay,
|
||||
),
|
||||
persistent_committee_period: self.persistent_committee_period,
|
||||
shard_committee_period: self.shard_committee_period,
|
||||
min_epochs_to_inactivity_penalty: self.min_epochs_to_inactivity_penalty,
|
||||
base_reward_factor: self.base_reward_factor,
|
||||
whistleblower_reward_quotient: self.whistleblower_reward_quotient,
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::*;
|
||||
use safe_arith::SafeArith;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz_types::typenum::{
|
||||
Unsigned, U0, U1, U1024, U1099511627776, U128, U16, U16777216, U2, U2048, U32, U4, U4096, U64,
|
||||
Unsigned, U0, U1024, U1099511627776, U128, U16, U16777216, U2, U2048, U32, U4, U4096, U64,
|
||||
U65536, U8, U8192,
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
@@ -151,7 +151,7 @@ impl EthSpec for MainnetEthSpec {
|
||||
type HistoricalRootsLimit = U16777216;
|
||||
type ValidatorRegistryLimit = U1099511627776;
|
||||
type MaxProposerSlashings = U16;
|
||||
type MaxAttesterSlashings = U1;
|
||||
type MaxAttesterSlashings = U2;
|
||||
type MaxAttestations = U128;
|
||||
type MaxDeposits = U16;
|
||||
type MaxVoluntaryExits = U16;
|
||||
@@ -178,12 +178,12 @@ pub struct MinimalEthSpec;
|
||||
|
||||
impl EthSpec for MinimalEthSpec {
|
||||
type SlotsPerEpoch = U8;
|
||||
type EpochsPerEth1VotingPeriod = U2;
|
||||
type EpochsPerEth1VotingPeriod = U4;
|
||||
type SlotsPerHistoricalRoot = U64;
|
||||
type EpochsPerHistoricalVector = U64;
|
||||
type EpochsPerSlashingsVector = U64;
|
||||
type MaxPendingAttestations = U1024; // 128 max attestations * 8 slots per epoch
|
||||
type SlotsPerEth1VotingPeriod = U16; // 2 epochs * 8 slots per epoch
|
||||
type SlotsPerEth1VotingPeriod = U32; // 4 epochs * 8 slots per epoch
|
||||
|
||||
params_from_eth_spec!(MainnetEthSpec {
|
||||
JustificationBitsLength,
|
||||
|
||||
@@ -39,7 +39,7 @@ pub mod signed_aggregate_and_proof;
|
||||
pub mod signed_beacon_block;
|
||||
pub mod signed_beacon_block_header;
|
||||
pub mod signed_voluntary_exit;
|
||||
pub mod signing_root;
|
||||
pub mod signing_data;
|
||||
pub mod utils;
|
||||
pub mod validator;
|
||||
pub mod voluntary_exit;
|
||||
@@ -84,7 +84,7 @@ pub use crate::signed_aggregate_and_proof::SignedAggregateAndProof;
|
||||
pub use crate::signed_beacon_block::{SignedBeaconBlock, SignedBeaconBlockHash};
|
||||
pub use crate::signed_beacon_block_header::SignedBeaconBlockHeader;
|
||||
pub use crate::signed_voluntary_exit::SignedVoluntaryExit;
|
||||
pub use crate::signing_root::{SignedRoot, SigningRoot};
|
||||
pub use crate::signing_data::{SignedRoot, SigningData};
|
||||
pub use crate::slot_epoch::{Epoch, Slot};
|
||||
pub use crate::subnet_id::SubnetId;
|
||||
pub use crate::validator::Validator;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
test_utils::TestRandom, BeaconBlock, ChainSpec, Domain, EthSpec, Fork, Hash256, PublicKey,
|
||||
SignedRoot, SigningRoot, Slot,
|
||||
SignedRoot, SigningData, Slot,
|
||||
};
|
||||
use bls::Signature;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
@@ -69,7 +69,7 @@ impl<E: EthSpec> SignedBeaconBlock<E> {
|
||||
);
|
||||
|
||||
let message = if let Some(object_root) = object_root_opt {
|
||||
SigningRoot {
|
||||
SigningData {
|
||||
object_root,
|
||||
domain,
|
||||
}
|
||||
|
||||
@@ -9,14 +9,14 @@ use tree_hash_derive::TreeHash;
|
||||
|
||||
#[cfg_attr(feature = "arbitrary-fuzz", derive(arbitrary::Arbitrary))]
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Encode, Decode, TreeHash, TestRandom)]
|
||||
pub struct SigningRoot {
|
||||
pub struct SigningData {
|
||||
pub object_root: Hash256,
|
||||
pub domain: Hash256,
|
||||
}
|
||||
|
||||
pub trait SignedRoot: TreeHash {
|
||||
fn signing_root(&self, domain: Hash256) -> Hash256 {
|
||||
SigningRoot {
|
||||
SigningData {
|
||||
object_root: self.tree_hash_root(),
|
||||
domain,
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
# Bump the test tag here and in .gitlab-ci.yml and CI will take care of updating the cached tarballs
|
||||
TESTS_TAG := v0.11.1
|
||||
TESTS_TAG := v0.12.0
|
||||
TESTS = general minimal mainnet
|
||||
TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS))
|
||||
|
||||
|
||||
@@ -28,6 +28,25 @@ fn minimal_config_ok() {
|
||||
config_test::<MinimalEthSpec>();
|
||||
}
|
||||
|
||||
// Check that the hand-computed multiplications on EthSpec are correctly computed.
|
||||
// This test lives here because one is most likely to be muck these up during a spec update.
|
||||
fn check_typenum_values<E: EthSpec>() {
|
||||
assert_eq!(
|
||||
E::MaxPendingAttestations::to_u64(),
|
||||
E::MaxAttestations::to_u64() * E::SlotsPerEpoch::to_u64()
|
||||
);
|
||||
assert_eq!(
|
||||
E::SlotsPerEth1VotingPeriod::to_u64(),
|
||||
E::EpochsPerEth1VotingPeriod::to_u64() * E::SlotsPerEpoch::to_u64()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derived_typenum_values() {
|
||||
check_typenum_values::<MinimalEthSpec>();
|
||||
check_typenum_values::<MainnetEthSpec>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shuffling() {
|
||||
ShufflingHandler::<MinimalEthSpec>::run();
|
||||
|
||||
Reference in New Issue
Block a user