Remove saturating arith from state_processing (#1644)

## Issue Addressed

Resolves #1100

## Proposed Changes

* Implement the `SafeArith` trait for `Slot` and `Epoch`, so that methods like `safe_add` become available.
* Tweak the `SafeArith` trait to allow a different `Rhs` type (analagous to `std::ops::Add`, etc).
* Add a `legacy-arith` feature to `types` and `state_processing` that conditionally enables implementations of
  the `std` ops with saturating semantics.
* Check compilation of `types` and `state_processing` _without_ `legacy-arith` on CI,
  thus guaranteeing that they only use the `SafeArith` primitives 🎉

## Additional Info

The `legacy-arith` feature gets turned on by all higher-level crates that depend on `state_processing` or `types`, thus allowing the beacon chain, networking, and other components to continue to rely on the availability of ops like `+`, `-`, `*`, etc.

**This is a consensus-breaking change**, but brings us in line with the spec, and our incompatibilities shouldn't have been reachable with any valid configuration of Eth2 parameters.
This commit is contained in:
Michael Sproul
2020-09-25 05:18:21 +00:00
parent 28b6d921c6
commit 3412a3ec54
26 changed files with 250 additions and 141 deletions

View File

@@ -2,6 +2,7 @@ use super::errors::{AttestationInvalid as Invalid, BlockOperationError};
use super::VerifySignatures;
use crate::common::get_indexed_attestation;
use crate::per_block_processing::is_valid_indexed_attestation;
use safe_arith::SafeArith;
use types::*;
type Result<T> = std::result::Result<T, BlockOperationError<Invalid>>;
@@ -25,7 +26,7 @@ pub fn verify_attestation_for_block_inclusion<T: EthSpec>(
let data = &attestation.data;
verify!(
data.slot + spec.min_attestation_inclusion_delay <= state.slot,
data.slot.safe_add(spec.min_attestation_inclusion_delay)? <= state.slot,
Invalid::IncludedTooEarly {
state: state.slot,
delay: spec.min_attestation_inclusion_delay,
@@ -33,7 +34,7 @@ pub fn verify_attestation_for_block_inclusion<T: EthSpec>(
}
);
verify!(
state.slot <= data.slot + T::slots_per_epoch(),
state.slot <= data.slot.safe_add(T::slots_per_epoch())?,
Invalid::IncludedTooLate {
state: state.slot,
attestation: data.slot,

View File

@@ -3,6 +3,7 @@ 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>>;
@@ -77,11 +78,14 @@ fn verify_exit_parametric<T: EthSpec>(
);
// 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() >= validator.activation_epoch + spec.shard_committee_period,
state.current_epoch() >= earliest_exit_epoch,
ExitInvalid::TooYoungToExit {
current_epoch: state.current_epoch(),
earliest_exit_epoch: validator.activation_epoch + spec.shard_committee_period,
earliest_exit_epoch,
}
);