Use SignatureBytes and PublicKeyBytes for deposits (#472)

* Replace deposit signatures with SignatureBytes, a struct which lazyly parsers signatures only on demand.

* check byte length when parsing SignatureBytes

* add comment to struct

* distinguish BadSignature and BadSignatureBytes in verify_deposit_signature

* add test for valid signature

* Implements TryInto<Signature> for &SignatureBytes and From<Signature> for &SignatureBytes

* add and use PublicKeyBytes + fix formatting

* fix compiler warning + docs for macro generated structs

* adds tests to ensure correct byte lengths

* small style improvement as suggested by michaelsproul
This commit is contained in:
blacktemplar
2019-08-06 05:49:11 +02:00
committed by Paul Hauner
parent 845f336a59
commit 01054ecf2f
14 changed files with 286 additions and 18 deletions

View File

@@ -2,6 +2,7 @@ use crate::common::{initiate_validator_exit, slash_validator};
use errors::{BlockInvalid as Invalid, BlockProcessingError as Error, IntoWithIndex};
use rayon::prelude::*;
use std::collections::HashSet;
use std::convert::TryInto;
use std::iter::FromIterator;
use tree_hash::{SignedRoot, TreeHash};
use types::*;
@@ -396,9 +397,13 @@ pub fn process_deposit<T: EthSpec>(
// depositing validator already exists in the registry.
state.update_pubkey_cache()?;
let pubkey: PublicKey = match (&deposit.data.pubkey).try_into() {
Err(_) => return Ok(()), //bad public key => return early
Ok(k) => k,
};
// Get an `Option<u64>` where `u64` is the validator index if this deposit public key
// already exists in the beacon_state.
let validator_index = get_existing_validator_index(state, deposit)
let validator_index = get_existing_validator_index(state, &pubkey)
.map_err(|e| e.into_with_index(deposit_index))?;
let amount = deposit.data.amount;
@@ -409,13 +414,13 @@ pub fn process_deposit<T: EthSpec>(
} else {
// The signature should be checked for new validators. Return early for a bad
// signature.
if verify_deposit_signature(state, deposit, spec).is_err() {
if verify_deposit_signature(state, deposit, spec, &pubkey).is_err() {
return Ok(());
}
// Create a new validator.
let validator = Validator {
pubkey: deposit.data.pubkey.clone(),
pubkey,
withdrawal_credentials: deposit.data.withdrawal_credentials,
activation_eligibility_epoch: spec.far_future_epoch,
activation_epoch: spec.far_future_epoch,

View File

@@ -349,6 +349,8 @@ pub enum DepositInvalid {
BadIndex { state: u64, deposit: u64 },
/// The signature (proof-of-possession) does not match the given pubkey.
BadSignature,
/// The signature does not represent a valid BLS signature.
BadSignatureBytes,
/// The specified `branch` and `index` did not form a valid proof that the deposit is included
/// in the eth1 deposit root.
BadMerkleProof,

View File

@@ -1,5 +1,6 @@
use super::errors::{DepositInvalid as Invalid, DepositValidationError as Error};
use merkle_proof::verify_merkle_proof;
use std::convert::TryInto;
use tree_hash::{SignedRoot, TreeHash};
use types::*;
@@ -10,15 +11,17 @@ pub fn verify_deposit_signature<T: EthSpec>(
state: &BeaconState<T>,
deposit: &Deposit,
spec: &ChainSpec,
pubkey: &PublicKey,
) -> Result<(), Error> {
// Note: Deposits are valid across forks, thus the deposit domain is computed
// with the fork zeroed.
let domain = spec.get_domain(state.current_epoch(), Domain::Deposit, &Fork::default());
let signature: Signature = (&deposit.data.signature)
.try_into()
.map_err(|_| Error::Invalid(Invalid::BadSignatureBytes))?;
verify!(
deposit
.data
.signature
.verify(&deposit.data.signed_root(), domain, &deposit.data.pubkey,),
signature.verify(&deposit.data.signed_root(), domain, pubkey),
Invalid::BadSignature
);
@@ -33,9 +36,9 @@ pub fn verify_deposit_signature<T: EthSpec>(
/// Errors if the state's `pubkey_cache` is not current.
pub fn get_existing_validator_index<T: EthSpec>(
state: &BeaconState<T>,
deposit: &Deposit,
pub_key: &PublicKey,
) -> Result<Option<u64>, Error> {
let validator_index = state.get_validator_index(&deposit.data.pubkey)?;
let validator_index = state.get_validator_index(pub_key)?;
Ok(validator_index.map(|idx| idx as u64))
}