Optimise attester slashing processing.

This commit is contained in:
Paul Hauner 2019-03-10 08:55:45 +11:00
parent e7fba3a473
commit 3f98849362
No known key found for this signature in database
GPG Key ID: D362883A9218FCC6
3 changed files with 43 additions and 9 deletions

View File

@ -13,6 +13,7 @@ pub use verify_deposit::{
build_public_key_hashmap, get_existing_validator_index, verify_deposit, verify_deposit_index, build_public_key_hashmap, get_existing_validator_index, verify_deposit, verify_deposit_index,
}; };
pub use verify_exit::verify_exit; pub use verify_exit::verify_exit;
pub use verify_slashable_attestation::verify_slashable_attestation;
pub use verify_transfer::{execute_transfer, verify_transfer}; pub use verify_transfer::{execute_transfer, verify_transfer};
pub mod errors; pub mod errors;
@ -264,19 +265,40 @@ pub fn process_attester_slashings(
Invalid::MaxAttesterSlashingsExceed Invalid::MaxAttesterSlashingsExceed
); );
// Verify attester slashings in parallel. // Verify the `SlashableAttestation`s in parallel (these are the resource-consuming objects, not
attester_slashings // the `AttesterSlashing`s themselves).
let mut slashable_attestations: Vec<&SlashableAttestation> =
Vec::with_capacity(attester_slashings.len() * 2);
for attester_slashing in attester_slashings {
slashable_attestations.push(&attester_slashing.slashable_attestation_1);
slashable_attestations.push(&attester_slashing.slashable_attestation_2);
}
// Verify slashable attestations in parallel.
slashable_attestations
.par_iter() .par_iter()
.enumerate() .enumerate()
.try_for_each(|(i, attester_slashing)| { .try_for_each(|(i, slashable_attestation)| {
verify_attester_slashing(&state, &attester_slashing, spec) verify_slashable_attestation(&state, slashable_attestation, spec)
.map_err(|e| e.into_with_index(i)) .map_err(|e| e.into_with_index(i))
})?; })?;
let all_slashable_attestations_have_been_checked = true;
// Gather the slashable indices and update the state in series. // Gather the slashable indices and preform the final verification and update the state in series.
for (i, attester_slashing) in attester_slashings.iter().enumerate() { for (i, attester_slashing) in attester_slashings.iter().enumerate() {
let should_verify_slashable_attestations = !all_slashable_attestations_have_been_checked;
verify_attester_slashing(
&state,
&attester_slashing,
should_verify_slashable_attestations,
spec,
)
.map_err(|e| e.into_with_index(i))?;
let slashable_indices = gather_attester_slashing_indices(&state, &attester_slashing) let slashable_indices = gather_attester_slashing_indices(&state, &attester_slashing)
.map_err(|e| e.into_with_index(i))?; .map_err(|e| e.into_with_index(i))?;
for i in slashable_indices { for i in slashable_indices {
state.slash_validator(i as usize, spec)?; state.slash_validator(i as usize, spec)?;
} }

View File

@ -76,6 +76,10 @@ pub enum BlockInvalid {
MaxExitsExceeded, MaxExitsExceeded,
MaxTransfersExceed, MaxTransfersExceed,
AttestationInvalid(usize, AttestationInvalid), AttestationInvalid(usize, AttestationInvalid),
/// A `SlashableAttestation` inside an `AttesterSlashing` was invalid.
///
/// To determine the offending `AttesterSlashing` index, divide the error message `usize` by two.
SlashableAttestationInvalid(usize, SlashableAttestationInvalid),
AttesterSlashingInvalid(usize, AttesterSlashingInvalid), AttesterSlashingInvalid(usize, AttesterSlashingInvalid),
ProposerSlashingInvalid(usize, ProposerSlashingInvalid), ProposerSlashingInvalid(usize, ProposerSlashingInvalid),
DepositInvalid(usize, DepositInvalid), DepositInvalid(usize, DepositInvalid),
@ -235,6 +239,11 @@ impl Into<SlashableAttestationInvalid> for SlashableAttestationValidationError {
} }
} }
impl_into_with_index_without_beacon_error!(
SlashableAttestationValidationError,
SlashableAttestationInvalid
);
/* /*
* `ProposerSlashing` Validation * `ProposerSlashing` Validation
*/ */

View File

@ -11,6 +11,7 @@ use types::*;
pub fn verify_attester_slashing( pub fn verify_attester_slashing(
state: &BeaconState, state: &BeaconState,
attester_slashing: &AttesterSlashing, attester_slashing: &AttesterSlashing,
should_verify_slashable_attestations: bool,
spec: &ChainSpec, spec: &ChainSpec,
) -> Result<(), Error> { ) -> Result<(), Error> {
let slashable_attestation_1 = &attester_slashing.slashable_attestation_1; let slashable_attestation_1 = &attester_slashing.slashable_attestation_1;
@ -26,10 +27,12 @@ pub fn verify_attester_slashing(
Invalid::NotSlashable Invalid::NotSlashable
); );
verify_slashable_attestation(state, &slashable_attestation_1, spec) if should_verify_slashable_attestations {
.map_err(|e| Error::Invalid(Invalid::SlashableAttestation1Invalid(e.into())))?; verify_slashable_attestation(state, &slashable_attestation_1, spec)
verify_slashable_attestation(state, &slashable_attestation_2, spec) .map_err(|e| Error::Invalid(Invalid::SlashableAttestation1Invalid(e.into())))?;
.map_err(|e| Error::Invalid(Invalid::SlashableAttestation2Invalid(e.into())))?; verify_slashable_attestation(state, &slashable_attestation_2, spec)
.map_err(|e| Error::Invalid(Invalid::SlashableAttestation2Invalid(e.into())))?;
}
Ok(()) Ok(())
} }