Files
lighthouse/consensus/state_processing/src/per_block_processing/verify_exit.rs
Paul Hauner b73c497be2 Support multiple BLS implementations (#1335)
## Issue Addressed

NA

## Proposed Changes

- Refactor the `bls` crate to support multiple BLS "backends" (e.g., milagro, blst, etc).
- Removes some duplicate, unused code in `common/rest_types/src/validator.rs`.
- Removes the old "upgrade legacy keypairs" functionality (these were unencrypted keys that haven't been supported for a few testnets, no one should be using them anymore).

## Additional Info

Most of the files changed are just inconsequential changes to function names.

## TODO

- [x] Optimization levels
- [x] Infinity point: https://github.com/supranational/blst/issues/11
- [x] Ensure milagro *and* blst are tested via CI
- [x] What to do with unsafe code?
- [x] Test infinity point in signature sets
2020-07-25 02:03:18 +00:00

103 lines
3.0 KiB
Rust

use super::errors::{BlockOperationError, ExitInvalid};
use crate::per_block_processing::{
signature_sets::{exit_signature_set, get_pubkey_from_state},
VerifySignatures,
};
use types::*;
type Result<T> = std::result::Result<T, BlockOperationError<ExitInvalid>>;
fn error(reason: ExitInvalid) -> BlockOperationError<ExitInvalid> {
BlockOperationError::invalid(reason)
}
/// Indicates if an `Exit` is valid to be included in a block in the current epoch of the given
/// state.
///
/// Returns `Ok(())` if the `Exit` is valid, otherwise indicates the reason for invalidity.
///
/// Spec v0.12.1
pub fn verify_exit<T: EthSpec>(
state: &BeaconState<T>,
exit: &SignedVoluntaryExit,
verify_signatures: VerifySignatures,
spec: &ChainSpec,
) -> Result<()> {
verify_exit_parametric(state, exit, verify_signatures, spec, false)
}
/// Like `verify_exit` but doesn't run checks which may become true in future states.
///
/// Spec v0.12.1
pub fn verify_exit_time_independent_only<T: EthSpec>(
state: &BeaconState<T>,
exit: &SignedVoluntaryExit,
verify_signatures: VerifySignatures,
spec: &ChainSpec,
) -> Result<()> {
verify_exit_parametric(state, exit, verify_signatures, spec, true)
}
/// Parametric version of `verify_exit` that skips some checks if `time_independent_only` is true.
///
/// Spec v0.12.1
fn verify_exit_parametric<T: EthSpec>(
state: &BeaconState<T>,
signed_exit: &SignedVoluntaryExit,
verify_signatures: VerifySignatures,
spec: &ChainSpec,
time_independent_only: bool,
) -> Result<()> {
let exit = &signed_exit.message;
let validator = state
.validators
.get(exit.validator_index as usize)
.ok_or_else(|| error(ExitInvalid::ValidatorUnknown(exit.validator_index)))?;
// Verify the validator is active.
verify!(
validator.is_active_at(state.current_epoch()),
ExitInvalid::NotActive(exit.validator_index)
);
// Verify that the validator has not yet exited.
verify!(
validator.exit_epoch == spec.far_future_epoch,
ExitInvalid::AlreadyExited(exit.validator_index)
);
// Exits must specify an epoch when they become valid; they are not valid before then.
verify!(
time_independent_only || state.current_epoch() >= exit.epoch,
ExitInvalid::FutureEpoch {
state: state.current_epoch(),
exit: exit.epoch
}
);
// Verify the validator has been active long enough.
verify!(
state.current_epoch() >= validator.activation_epoch + spec.shard_committee_period,
ExitInvalid::TooYoungToExit {
current_epoch: state.current_epoch(),
earliest_exit_epoch: validator.activation_epoch + spec.shard_committee_period,
}
);
if verify_signatures.is_true() {
verify!(
exit_signature_set(
state,
|i| get_pubkey_from_state(state, i),
signed_exit,
spec
)?
.verify(),
ExitInvalid::BadSignature
);
}
Ok(())
}