mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-07 08:52:54 +00:00
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:
@@ -28,24 +28,24 @@ macro_rules! assign_method {
|
||||
}
|
||||
|
||||
/// Trait providing safe arithmetic operations for built-in types.
|
||||
pub trait SafeArith: Sized + Copy {
|
||||
pub trait SafeArith<Rhs = Self>: Sized + Copy {
|
||||
const ZERO: Self;
|
||||
const ONE: Self;
|
||||
|
||||
/// Safe variant of `+` that guards against overflow.
|
||||
fn safe_add(&self, other: Self) -> Result<Self>;
|
||||
fn safe_add(&self, other: Rhs) -> Result<Self>;
|
||||
|
||||
/// Safe variant of `-` that guards against overflow.
|
||||
fn safe_sub(&self, other: Self) -> Result<Self>;
|
||||
fn safe_sub(&self, other: Rhs) -> Result<Self>;
|
||||
|
||||
/// Safe variant of `*` that guards against overflow.
|
||||
fn safe_mul(&self, other: Self) -> Result<Self>;
|
||||
fn safe_mul(&self, other: Rhs) -> Result<Self>;
|
||||
|
||||
/// Safe variant of `/` that guards against division by 0.
|
||||
fn safe_div(&self, other: Self) -> Result<Self>;
|
||||
fn safe_div(&self, other: Rhs) -> Result<Self>;
|
||||
|
||||
/// Safe variant of `%` that guards against division by 0.
|
||||
fn safe_rem(&self, other: Self) -> Result<Self>;
|
||||
fn safe_rem(&self, other: Rhs) -> Result<Self>;
|
||||
|
||||
/// Safe variant of `<<` that guards against overflow.
|
||||
fn safe_shl(&self, other: u32) -> Result<Self>;
|
||||
@@ -53,18 +53,13 @@ pub trait SafeArith: Sized + Copy {
|
||||
/// Safe variant of `>>` that guards against overflow.
|
||||
fn safe_shr(&self, other: u32) -> Result<Self>;
|
||||
|
||||
assign_method!(safe_add_assign, safe_add, "+=");
|
||||
assign_method!(safe_sub_assign, safe_sub, "-=");
|
||||
assign_method!(safe_mul_assign, safe_mul, "*=");
|
||||
assign_method!(safe_div_assign, safe_div, "/=");
|
||||
assign_method!(safe_rem_assign, safe_rem, "%=");
|
||||
assign_method!(safe_add_assign, safe_add, Rhs, "+=");
|
||||
assign_method!(safe_sub_assign, safe_sub, Rhs, "-=");
|
||||
assign_method!(safe_mul_assign, safe_mul, Rhs, "*=");
|
||||
assign_method!(safe_div_assign, safe_div, Rhs, "/=");
|
||||
assign_method!(safe_rem_assign, safe_rem, Rhs, "%=");
|
||||
assign_method!(safe_shl_assign, safe_shl, u32, "<<=");
|
||||
assign_method!(safe_shr_assign, safe_shr, u32, ">>=");
|
||||
|
||||
/// Mutate `self` by adding 1, erroring on overflow.
|
||||
fn increment(&mut self) -> Result<()> {
|
||||
self.safe_add_assign(Self::ONE)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_safe_arith {
|
||||
@@ -136,8 +131,7 @@ mod test {
|
||||
#[test]
|
||||
fn mutate() {
|
||||
let mut x = 0u8;
|
||||
x.increment().unwrap();
|
||||
x.increment().unwrap();
|
||||
x.safe_add_assign(2).unwrap();
|
||||
assert_eq!(x, 2);
|
||||
x.safe_sub_assign(1).unwrap();
|
||||
assert_eq!(x, 1);
|
||||
|
||||
Reference in New Issue
Block a user