diff --git a/Cargo.lock b/Cargo.lock index 481d2048652..071dbd05245 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2162,7 +2162,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18e4fdb82bd54a12e42fb58a800dcae6b9e13982238ce2296dc3570b92148e1f" dependencies = [ "data-encoding", - "syn 1.0.109", + "syn 2.0.100", ] [[package]] @@ -7374,7 +7374,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.100", @@ -8269,6 +8269,8 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "safe_arith" version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b147bb6111014916d3ef9d4c85173124a8e12193a67f6176d67244afd558d6c1" [[package]] name = "salsa20" diff --git a/Cargo.toml b/Cargo.toml index a5f01a498de..a46dc355e72 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,7 +56,6 @@ members = [ "consensus/int_to_bytes", "consensus/merkle_proof", "consensus/proto_array", - "consensus/safe_arith", "consensus/state_processing", "consensus/swap_or_not_shuffle", "consensus/types", @@ -225,7 +224,7 @@ ring = "0.17" rpds = "0.11" rusqlite = { version = "0.28", features = ["bundled"] } rust_eth_kzg = "0.9" -safe_arith = { path = "consensus/safe_arith" } +safe_arith = "0.1" sensitive_url = { path = "common/sensitive_url" } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/consensus/safe_arith/Cargo.toml b/consensus/safe_arith/Cargo.toml deleted file mode 100644 index 9ac9fe28d3a..00000000000 --- a/consensus/safe_arith/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "safe_arith" -version = "0.1.0" -authors = ["Michael Sproul "] -edition = { workspace = true } -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/consensus/safe_arith/src/iter.rs b/consensus/safe_arith/src/iter.rs deleted file mode 100644 index d5ee51b588d..00000000000 --- a/consensus/safe_arith/src/iter.rs +++ /dev/null @@ -1,70 +0,0 @@ -use crate::{Result, SafeArith}; - -/// Extension trait for iterators, providing a safe replacement for `sum`. -pub trait SafeArithIter { - fn safe_sum(self) -> Result; -} - -impl SafeArithIter for I -where - I: Iterator + Sized, - T: SafeArith, -{ - fn safe_sum(mut self) -> Result { - self.try_fold(T::ZERO, |acc, x| acc.safe_add(x)) - } -} - -#[cfg(test)] -mod test { - use super::*; - use crate::ArithError; - - #[test] - fn empty_sum() { - let v: Vec = vec![]; - assert_eq!(v.into_iter().safe_sum(), Ok(0)); - } - - #[test] - fn unsigned_sum_small() { - let arr = [400u64, 401, 402, 403, 404, 405, 406]; - assert_eq!( - arr.iter().copied().safe_sum().unwrap(), - arr.iter().copied().sum() - ); - } - - #[test] - fn unsigned_sum_overflow() { - let v = vec![u64::MAX, 1]; - assert_eq!(v.into_iter().safe_sum(), Err(ArithError::Overflow)); - } - - #[test] - fn signed_sum_small() { - let v = vec![-1i64, -2i64, -3i64, 3, 2, 1]; - assert_eq!(v.into_iter().safe_sum(), Ok(0)); - } - - #[test] - fn signed_sum_overflow_above() { - let v = vec![1, 2, 3, 4, i16::MAX, 0, 1, 2, 3]; - assert_eq!(v.into_iter().safe_sum(), Err(ArithError::Overflow)); - } - - #[test] - fn signed_sum_overflow_below() { - let v = vec![i16::MIN, -1]; - assert_eq!(v.into_iter().safe_sum(), Err(ArithError::Overflow)); - } - - #[test] - fn signed_sum_almost_overflow() { - let arr = [i64::MIN, 1, -1i64, i64::MAX, i64::MAX, 1]; - assert_eq!( - arr.iter().copied().safe_sum().unwrap(), - arr.iter().copied().sum() - ); - } -} diff --git a/consensus/safe_arith/src/lib.rs b/consensus/safe_arith/src/lib.rs deleted file mode 100644 index aa397c0603e..00000000000 --- a/consensus/safe_arith/src/lib.rs +++ /dev/null @@ -1,166 +0,0 @@ -//! Library for safe arithmetic on integers, avoiding overflow and division by zero. -mod iter; - -pub use iter::SafeArithIter; - -/// Error representing the failure of an arithmetic operation. -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum ArithError { - Overflow, - DivisionByZero, -} - -pub type Result = std::result::Result; - -macro_rules! assign_method { - ($name:ident, $op:ident, $doc_op:expr) => { - assign_method!($name, $op, Self, $doc_op); - }; - ($name:ident, $op:ident, $rhs_ty:ty, $doc_op:expr) => { - #[doc = "Safe variant of `"] - #[doc = $doc_op] - #[doc = "`."] - #[inline] - fn $name(&mut self, other: $rhs_ty) -> Result<()> { - *self = self.$op(other)?; - Ok(()) - } - }; -} - -/// Trait providing safe arithmetic operations for built-in types. -pub trait SafeArith: Sized + Copy { - const ZERO: Self; - const ONE: Self; - - /// Safe variant of `+` that guards against overflow. - fn safe_add(&self, other: Rhs) -> Result; - - /// Safe variant of `-` that guards against overflow. - fn safe_sub(&self, other: Rhs) -> Result; - - /// Safe variant of `*` that guards against overflow. - fn safe_mul(&self, other: Rhs) -> Result; - - /// Safe variant of `/` that guards against division by 0. - fn safe_div(&self, other: Rhs) -> Result; - - /// Safe variant of `%` that guards against division by 0. - fn safe_rem(&self, other: Rhs) -> Result; - - /// Safe variant of `<<` that guards against overflow. - fn safe_shl(&self, other: u32) -> Result; - - /// Safe variant of `>>` that guards against overflow. - fn safe_shr(&self, other: u32) -> Result; - - 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, ">>="); -} - -macro_rules! impl_safe_arith { - ($typ:ty) => { - impl SafeArith for $typ { - const ZERO: Self = 0; - const ONE: Self = 1; - - #[inline] - fn safe_add(&self, other: Self) -> Result { - self.checked_add(other).ok_or(ArithError::Overflow) - } - - #[inline] - fn safe_sub(&self, other: Self) -> Result { - self.checked_sub(other).ok_or(ArithError::Overflow) - } - - #[inline] - fn safe_mul(&self, other: Self) -> Result { - self.checked_mul(other).ok_or(ArithError::Overflow) - } - - #[inline] - fn safe_div(&self, other: Self) -> Result { - self.checked_div(other).ok_or(ArithError::DivisionByZero) - } - - #[inline] - fn safe_rem(&self, other: Self) -> Result { - self.checked_rem(other).ok_or(ArithError::DivisionByZero) - } - - #[inline] - fn safe_shl(&self, other: u32) -> Result { - self.checked_shl(other).ok_or(ArithError::Overflow) - } - - #[inline] - fn safe_shr(&self, other: u32) -> Result { - self.checked_shr(other).ok_or(ArithError::Overflow) - } - } - }; -} - -impl_safe_arith!(u8); -impl_safe_arith!(u16); -impl_safe_arith!(u32); -impl_safe_arith!(u64); -impl_safe_arith!(usize); -impl_safe_arith!(i8); -impl_safe_arith!(i16); -impl_safe_arith!(i32); -impl_safe_arith!(i64); -impl_safe_arith!(isize); - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn basic() { - let x = 10u32; - let y = 11; - assert_eq!(x.safe_add(y), Ok(x + y)); - assert_eq!(y.safe_sub(x), Ok(y - x)); - assert_eq!(x.safe_mul(y), Ok(x * y)); - assert_eq!(x.safe_div(y), Ok(x / y)); - assert_eq!(x.safe_rem(y), Ok(x % y)); - - assert_eq!(x.safe_shl(1), Ok(x << 1)); - assert_eq!(x.safe_shr(1), Ok(x >> 1)); - } - - #[test] - fn mutate() { - let mut x = 0u8; - x.safe_add_assign(2).unwrap(); - assert_eq!(x, 2); - x.safe_sub_assign(1).unwrap(); - assert_eq!(x, 1); - x.safe_shl_assign(1).unwrap(); - assert_eq!(x, 2); - x.safe_mul_assign(3).unwrap(); - assert_eq!(x, 6); - x.safe_div_assign(4).unwrap(); - assert_eq!(x, 1); - x.safe_shr_assign(1).unwrap(); - assert_eq!(x, 0); - } - - #[test] - fn errors() { - assert!(u32::MAX.safe_add(1).is_err()); - assert!(u32::MIN.safe_sub(1).is_err()); - assert!(u32::MAX.safe_mul(2).is_err()); - assert!(u32::MAX.safe_div(0).is_err()); - assert!(u32::MAX.safe_rem(0).is_err()); - assert!(u32::MAX.safe_shl(32).is_err()); - assert!(u32::MAX.safe_shr(32).is_err()); - } -}