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

@@ -47,7 +47,7 @@ impl DepositDataTree {
/// Add a deposit to the merkle tree.
pub fn push_leaf(&mut self, leaf: Hash256) -> Result<(), MerkleTreeError> {
self.tree.push_leaf(leaf, self.depth)?;
self.mix_in_length.increment()?;
self.mix_in_length.safe_add_assign(1)?;
Ok(())
}
}

View File

@@ -1,3 +1,4 @@
use safe_arith::SafeArith;
use std::cmp::max;
use types::{BeaconStateError as Error, *};
@@ -22,7 +23,7 @@ pub fn initiate_validator_exit<T: EthSpec>(
state.exit_cache.build(&state.validators, spec)?;
// Compute exit queue epoch
let delayed_epoch = state.compute_activation_exit_epoch(state.current_epoch(), spec);
let delayed_epoch = state.compute_activation_exit_epoch(state.current_epoch(), spec)?;
let mut exit_queue_epoch = state
.exit_cache
.max_epoch()?
@@ -30,13 +31,13 @@ pub fn initiate_validator_exit<T: EthSpec>(
let exit_queue_churn = state.exit_cache.get_churn_at(exit_queue_epoch)?;
if exit_queue_churn >= state.get_churn_limit(spec)? {
exit_queue_epoch += 1;
exit_queue_epoch.safe_add_assign(1)?;
}
state.exit_cache.record_validator_exit(exit_queue_epoch)?;
state.validators[index].exit_epoch = exit_queue_epoch;
state.validators[index].withdrawable_epoch =
exit_queue_epoch + spec.min_validator_withdrawability_delay;
exit_queue_epoch.safe_add(spec.min_validator_withdrawability_delay)?;
Ok(())
}

View File

@@ -23,7 +23,7 @@ pub fn slash_validator<T: EthSpec>(
state.validators[slashed_index].slashed = true;
state.validators[slashed_index].withdrawable_epoch = cmp::max(
state.validators[slashed_index].withdrawable_epoch,
epoch + Epoch::from(T::EpochsPerSlashingsVector::to_u64()),
epoch.safe_add(T::EpochsPerSlashingsVector::to_u64())?,
);
let validator_effective_balance = state.get_effective_balance(slashed_index, spec)?;
state.set_slashings(