-
Notifications
You must be signed in to change notification settings - Fork 677
/
verify_exit.rs
81 lines (71 loc) · 2.3 KB
/
verify_exit.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use super::errors::{BlockOperationError, ExitInvalid};
use crate::per_block_processing::{
signature_sets::{exit_signature_set, get_pubkey_from_state},
VerifySignatures,
};
use safe_arith::SafeArith;
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>,
signed_exit: &SignedVoluntaryExit,
verify_signatures: VerifySignatures,
spec: &ChainSpec,
) -> 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!(
state.current_epoch() >= exit.epoch,
ExitInvalid::FutureEpoch {
state: state.current_epoch(),
exit: exit.epoch
}
);
// Verify the validator has been active long enough.
let earliest_exit_epoch = validator
.activation_epoch
.safe_add(spec.shard_committee_period)?;
verify!(
state.current_epoch() >= earliest_exit_epoch,
ExitInvalid::TooYoungToExit {
current_epoch: state.current_epoch(),
earliest_exit_epoch,
}
);
if verify_signatures.is_true() {
verify!(
exit_signature_set(
state,
|i| get_pubkey_from_state(state, i),
signed_exit,
spec
)?
.verify(),
ExitInvalid::BadSignature
);
}
Ok(())
}