Optimise deposits processing.

This commit is contained in:
Paul Hauner
2019-03-10 08:33:17 +11:00
parent 5f3da0732f
commit 1ca99b8c4c
5 changed files with 182 additions and 38 deletions

View File

@@ -294,6 +294,11 @@ pub enum DepositInvalid {
///
/// (state_index, deposit_index)
BadIndex(u64, u64),
/// The proof-of-possession does not match the given pubkey.
BadProofOfPossession,
/// The withdrawal credentials for the depositing validator did not match the withdrawal
/// credentials of an existing validator with the same public key.
BadWithdrawalCredentials,
/// The specified `branch` and `index` did not form a valid proof that the deposit is included
/// in the eth1 deposit root.
BadMerkleProof,

View File

@@ -12,7 +12,7 @@ pub fn verify_attester_slashing(
state: &BeaconState,
attester_slashing: &AttesterSlashing,
spec: &ChainSpec,
) -> Result<Vec<u64>, Error> {
) -> Result<(), Error> {
let slashable_attestation_1 = &attester_slashing.slashable_attestation_1;
let slashable_attestation_2 = &attester_slashing.slashable_attestation_2;
@@ -31,6 +31,21 @@ pub fn verify_attester_slashing(
verify_slashable_attestation(state, &slashable_attestation_2, spec)
.map_err(|e| Error::Invalid(Invalid::SlashableAttestation2Invalid(e.into())))?;
Ok(())
}
/// For a given attester slashing, return the indices able to be slashed.
///
/// Returns Ok(indices) if `indices.len() > 0`.
///
/// Spec v0.4.0
pub fn gather_attester_slashing_indices(
state: &BeaconState,
attester_slashing: &AttesterSlashing,
) -> Result<Vec<u64>, Error> {
let slashable_attestation_1 = &attester_slashing.slashable_attestation_1;
let slashable_attestation_2 = &attester_slashing.slashable_attestation_2;
let mut slashable_indices = vec![];
for i in &slashable_attestation_1.validator_indices {
let validator = state
@@ -38,7 +53,7 @@ pub fn verify_attester_slashing(
.get(*i as usize)
.ok_or_else(|| Error::Invalid(Invalid::UnknownValidator(*i)))?;
if slashable_attestation_1.validator_indices.contains(&i) & !validator.slashed {
if slashable_attestation_2.validator_indices.contains(&i) & !validator.slashed {
slashable_indices.push(*i);
}
}

View File

@@ -1,15 +1,22 @@
use super::errors::{DepositInvalid as Invalid, DepositValidationError as Error};
use bls::verify_proof_of_possession;
use hashing::hash;
use merkle_proof::verify_merkle_proof;
use ssz::ssz_encode;
use ssz_derive::Encode;
use std::collections::HashMap;
use types::*;
pub type PublicKeyValidatorIndexHashmap = HashMap<PublicKey, u64>;
/// Indicates if a `Deposit` is valid to be included in a block in the current epoch of the given
/// state.
///
/// Returns `Ok(())` if the `Deposit` is valid, otherwise indicates the reason for invalidity.
///
/// This function _does not_ check `state.deposit_index` so this function may be run in parallel.
/// See the `verify_deposit_index` function for this.
///
/// Note: this function is incomplete.
///
/// Spec v0.4.0
@@ -20,8 +27,14 @@ pub fn verify_deposit(
spec: &ChainSpec,
) -> Result<(), Error> {
verify!(
deposit.index == state.deposit_index,
Invalid::BadIndex(state.deposit_index, deposit.index)
// TODO: update proof of possession.
//
// https://github.com/sigp/lighthouse/issues/239
verify_proof_of_possession(
&deposit.deposit_data.deposit_input.proof_of_possession,
&deposit.deposit_data.deposit_input.pubkey
),
Invalid::BadProofOfPossession
);
if verify_merkle_branch {
@@ -34,6 +47,50 @@ pub fn verify_deposit(
Ok(())
}
/// Verify that the `Deposit` index is correct.
///
/// Spec v0.4.0
pub fn verify_deposit_index(state: &BeaconState, deposit: &Deposit) -> Result<(), Error> {
verify!(
deposit.index == state.deposit_index,
Invalid::BadIndex(state.deposit_index, deposit.index)
);
Ok(())
}
pub fn build_public_key_hashmap(state: &BeaconState) -> PublicKeyValidatorIndexHashmap {
let mut hashmap = HashMap::with_capacity(state.validator_registry.len());
for (i, validator) in state.validator_registry.iter().enumerate() {
hashmap.insert(validator.pubkey.clone(), i as u64);
}
hashmap
}
pub fn get_existing_validator_index(
state: &BeaconState,
deposit: &Deposit,
pubkey_map: &HashMap<PublicKey, u64>,
) -> Result<Option<u64>, Error> {
let deposit_input = &deposit.deposit_data.deposit_input;
let validator_index = pubkey_map.get(&deposit_input.pubkey).and_then(|i| Some(*i));
match validator_index {
None => Ok(None),
Some(index) => {
verify!(
deposit_input.withdrawal_credentials
== state.validator_registry[index as usize].withdrawal_credentials,
Invalid::BadWithdrawalCredentials
);
Ok(Some(index))
}
}
}
/// Verify that a deposit is included in the state's eth1 deposit root.
///
/// Spec v0.4.0