spec v0.6.1: verify attester slashing
This commit is contained in:
parent
58481c7119
commit
dab11c1eed
@ -7,30 +7,27 @@ use types::*;
|
||||
///
|
||||
/// Returns `Ok(())` if the `AttesterSlashing` is valid, otherwise indicates the reason for invalidity.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
/// Spec v0.6.1
|
||||
pub fn verify_attester_slashing<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attester_slashing: &AttesterSlashing,
|
||||
should_verify_indexed_attestations: bool,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<(), Error> {
|
||||
let indexed_attestation_1 = &attester_slashing.indexed_attestation_1;
|
||||
let indexed_attestation_2 = &attester_slashing.indexed_attestation_2;
|
||||
let attestation_1 = &attester_slashing.attestation_1;
|
||||
let attestation_2 = &attester_slashing.attestation_2;
|
||||
|
||||
// Spec: is_slashable_attestation_data
|
||||
verify!(
|
||||
indexed_attestation_1.data != indexed_attestation_2.data,
|
||||
Invalid::AttestationDataIdentical
|
||||
);
|
||||
verify!(
|
||||
indexed_attestation_1.is_double_vote(indexed_attestation_2, spec)
|
||||
| indexed_attestation_1.is_surround_vote(indexed_attestation_2, spec),
|
||||
attestation_1.is_double_vote(attestation_2, spec)
|
||||
|| attestation_1.is_surround_vote(attestation_2, spec),
|
||||
Invalid::NotSlashable
|
||||
);
|
||||
|
||||
if should_verify_indexed_attestations {
|
||||
verify_indexed_attestation(state, &indexed_attestation_1, spec)
|
||||
verify_indexed_attestation(state, &attestation_1, spec)
|
||||
.map_err(|e| Error::Invalid(Invalid::IndexedAttestation1Invalid(e.into())))?;
|
||||
verify_indexed_attestation(state, &indexed_attestation_2, spec)
|
||||
verify_indexed_attestation(state, &attestation_2, spec)
|
||||
.map_err(|e| Error::Invalid(Invalid::IndexedAttestation2Invalid(e.into())))?;
|
||||
}
|
||||
|
||||
@ -41,8 +38,8 @@ pub fn verify_attester_slashing<T: EthSpec>(
|
||||
///
|
||||
/// Returns Ok(indices) if `indices.len() > 0`.
|
||||
///
|
||||
/// Spec v0.5.1
|
||||
pub fn gather_attester_slashing_indices<T: EthSpec>(
|
||||
/// Spec v0.6.1
|
||||
pub fn get_slashable_indices<T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attester_slashing: &AttesterSlashing,
|
||||
spec: &ChainSpec,
|
||||
@ -50,47 +47,47 @@ pub fn gather_attester_slashing_indices<T: EthSpec>(
|
||||
gather_attester_slashing_indices_modular(
|
||||
state,
|
||||
attester_slashing,
|
||||
|_, validator| validator.slashed,
|
||||
|_, validator| validator.is_slashable_at(state.current_epoch()),
|
||||
spec,
|
||||
)
|
||||
}
|
||||
|
||||
/// Same as `gather_attester_slashing_indices` but allows the caller to specify the criteria
|
||||
/// for determining whether a given validator should be considered slashed.
|
||||
pub fn gather_attester_slashing_indices_modular<F, T: EthSpec>(
|
||||
/// for determining whether a given validator should be considered slashable.
|
||||
pub fn get_slashable_indices_modular<F, T: EthSpec>(
|
||||
state: &BeaconState<T>,
|
||||
attester_slashing: &AttesterSlashing,
|
||||
is_slashed: F,
|
||||
is_slashable: F,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<Vec<u64>, Error>
|
||||
where
|
||||
F: Fn(u64, &Validator) -> bool,
|
||||
{
|
||||
let indexed_attestation_1 = &attester_slashing.indexed_attestation_1;
|
||||
let indexed_attestation_2 = &attester_slashing.indexed_attestation_2;
|
||||
let attestation_1 = &attester_slashing.attestation_1;
|
||||
let attestation_2 = &attester_slashing.attestation_2;
|
||||
|
||||
let mut indexed_indices = Vec::with_capacity(spec.max_indices_per_indexed_vote);
|
||||
for i in &indexed_attestation_1.validator_indices {
|
||||
let mut attesting_indices_1 = HashSet::new();
|
||||
attesting_indices_1.extend(attestation_1.custody_bit_0_indices.clone());
|
||||
attesting_indices_1.extend(attestation_1.custody_bit_1_indices.clone());
|
||||
|
||||
let mut attesting_indices_2 = HashSet::new();
|
||||
attesting_indices_2.extend(attestation_2.custody_bit_0_indices.clone());
|
||||
attesting_indices_2.extend(attestation_2.custody_bit_1_indices.clone());
|
||||
|
||||
let mut slashable_indices = vec![];
|
||||
|
||||
for index in &attesting_indices_1 & &attesting_indices_2 {
|
||||
let validator = state
|
||||
.validator_registry
|
||||
.get(*i as usize)
|
||||
.ok_or_else(|| Error::Invalid(Invalid::UnknownValidator(*i)))?;
|
||||
.get(index as usize)
|
||||
.ok_or_else(|| Error::Invalid(Invalid::UnknownValidator(index)))?;
|
||||
|
||||
if indexed_attestation_2.validator_indices.contains(&i) & !is_slashed(*i, validator) {
|
||||
// TODO: verify that we should reject any indexed attestation which includes a
|
||||
// withdrawn validator. PH has asked the question on gitter, awaiting response.
|
||||
verify!(
|
||||
validator.withdrawable_epoch > state.slot.epoch(spec.slots_per_epoch),
|
||||
Invalid::ValidatorAlreadyWithdrawn(*i)
|
||||
);
|
||||
|
||||
indexed_indices.push(*i);
|
||||
if is_slashable(index, validator) {
|
||||
slashable_indices.push(index);
|
||||
}
|
||||
}
|
||||
|
||||
verify!(!indexed_indices.is_empty(), Invalid::NoSlashableIndices);
|
||||
verify!(!slashable_indices.is_empty(), Invalid::NoSlashableIndices);
|
||||
|
||||
indexed_indices.shrink_to_fit();
|
||||
|
||||
Ok(indexed_indices)
|
||||
Ok(slashable_indices)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user