mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-11 04:31:51 +00:00
132 lines
3.7 KiB
Rust
132 lines
3.7 KiB
Rust
use super::errors::{DepositInvalid as Invalid, DepositValidationError as Error};
|
|
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
|
|
pub fn verify_deposit(
|
|
state: &BeaconState,
|
|
deposit: &Deposit,
|
|
verify_merkle_branch: bool,
|
|
spec: &ChainSpec,
|
|
) -> Result<(), Error> {
|
|
verify!(
|
|
deposit
|
|
.deposit_data
|
|
.deposit_input
|
|
.validate_proof_of_possession(
|
|
state.slot.epoch(spec.slots_per_epoch),
|
|
&state.fork,
|
|
spec
|
|
),
|
|
Invalid::BadProofOfPossession
|
|
);
|
|
|
|
if verify_merkle_branch {
|
|
verify!(
|
|
verify_deposit_merkle_proof(state, deposit, spec),
|
|
Invalid::BadMerkleProof
|
|
);
|
|
}
|
|
|
|
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,
|
|
) -> Result<Option<u64>, Error> {
|
|
let deposit_input = &deposit.deposit_data.deposit_input;
|
|
|
|
let validator_index = state
|
|
.get_validator_index(&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 as u64))
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Verify that a deposit is included in the state's eth1 deposit root.
|
|
///
|
|
/// Spec v0.4.0
|
|
fn verify_deposit_merkle_proof(state: &BeaconState, deposit: &Deposit, spec: &ChainSpec) -> bool {
|
|
let leaf = hash(&get_serialized_deposit_data(deposit));
|
|
verify_merkle_proof(
|
|
Hash256::from_slice(&leaf),
|
|
&deposit.branch,
|
|
spec.deposit_contract_tree_depth as usize,
|
|
deposit.index as usize,
|
|
state.latest_eth1_data.deposit_root,
|
|
)
|
|
}
|
|
|
|
/// Helper struct for easily getting the serialized data generated by the deposit contract.
|
|
///
|
|
/// Spec v0.4.0
|
|
#[derive(Encode)]
|
|
struct SerializedDepositData {
|
|
amount: u64,
|
|
timestamp: u64,
|
|
input: DepositInput,
|
|
}
|
|
|
|
/// Return the serialized data generated by the deposit contract that is used to generate the
|
|
/// merkle proof.
|
|
///
|
|
/// Spec v0.4.0
|
|
fn get_serialized_deposit_data(deposit: &Deposit) -> Vec<u8> {
|
|
let serialized_deposit_data = SerializedDepositData {
|
|
amount: deposit.deposit_data.amount,
|
|
timestamp: deposit.deposit_data.timestamp,
|
|
input: deposit.deposit_data.deposit_input.clone(),
|
|
};
|
|
|
|
ssz_encode(&serialized_deposit_data)
|
|
}
|