From 963a14df85d6697b3490e44a26e23063f87a875b Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 15:35:25 +1300 Subject: [PATCH 01/63] Split up sr_arithmetic.rs --- core/sr-primitives/src/sr_arithmetic.rs | 2170 ----------------- .../src/sr_arithmetic/biguint.rs | 930 +++++++ .../src/sr_arithmetic/fixed64.rs | 206 ++ .../src/sr_arithmetic/helpers_128bit.rs | 103 + core/sr-primitives/src/sr_arithmetic/mod.rs | 27 + .../src/sr_arithmetic/parts_per_x.rs | 520 ++++ .../src/sr_arithmetic/rational128.rs | 462 ++++ 7 files changed, 2248 insertions(+), 2170 deletions(-) delete mode 100644 core/sr-primitives/src/sr_arithmetic.rs create mode 100644 core/sr-primitives/src/sr_arithmetic/biguint.rs create mode 100644 core/sr-primitives/src/sr_arithmetic/fixed64.rs create mode 100644 core/sr-primitives/src/sr_arithmetic/helpers_128bit.rs create mode 100644 core/sr-primitives/src/sr_arithmetic/mod.rs create mode 100644 core/sr-primitives/src/sr_arithmetic/parts_per_x.rs create mode 100644 core/sr-primitives/src/sr_arithmetic/rational128.rs diff --git a/core/sr-primitives/src/sr_arithmetic.rs b/core/sr-primitives/src/sr_arithmetic.rs deleted file mode 100644 index 043a383a33244..0000000000000 --- a/core/sr-primitives/src/sr_arithmetic.rs +++ /dev/null @@ -1,2170 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Minimal fixed point arithmetic primitives and types for runtime. - -#[cfg(feature = "std")] -use crate::serde::{Serialize, Deserialize}; - -use rstd::{ - ops, cmp::Ordering, prelude::*, - convert::{TryFrom, TryInto}, -}; -use codec::{Encode, Decode}; -use crate::traits::{ - SaturatedConversion, CheckedSub, CheckedAdd, Bounded, UniqueSaturatedInto, Saturating, Zero, -}; - -macro_rules! implement_per_thing { - ($name:ident, $test_mod:ident, [$($test_units:tt),+], $max:tt, $type:ty, $upper_type:ty, $title:expr $(,)?) => { - /// A fixed point representation of a number between in the range [0, 1]. - /// - #[doc = $title] - #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Ord, PartialOrd))] - #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq)] - pub struct $name($type); - - impl $name { - /// Nothing. - pub fn zero() -> Self { Self(0) } - - /// `true` if this is nothing. - pub fn is_zero(&self) -> bool { self.0 == 0 } - - /// Everything. - pub fn one() -> Self { Self($max) } - - /// Consume self and deconstruct into a raw numeric type. - pub fn deconstruct(self) -> $type { self.0 } - - /// Return the scale at which this per-thing is working. - pub const fn accuracy() -> $type { $max } - - /// From an explicitly defined number of parts per maximum of the type. - /// - /// This can be called at compile time. - pub const fn from_parts(parts: $type) -> Self { - Self([parts, $max][(parts > $max) as usize]) - } - - /// Converts from a percent. Equal to `x / 100`. - /// - /// This can be created at compile time. - pub const fn from_percent(x: $type) -> Self { - Self([x, 100][(x > 100) as usize] * ($max / 100)) - } - - /// Return the product of multiplication of this value by itself. - pub fn square(self) -> Self { - // both can be safely casted and multiplied. - let p: $upper_type = self.0 as $upper_type * self.0 as $upper_type; - let q: $upper_type = $max as $upper_type * $max as $upper_type; - Self::from_rational_approximation(p, q) - } - - /// Converts a fraction into `Permill`. - #[cfg(feature = "std")] - pub fn from_fraction(x: f64) -> Self { Self((x * ($max as f64)) as $type) } - - /// Approximate the fraction `p/q` into a per-thing fraction. This will never overflow. - /// - /// The computation of this approximation is performed in the generic type `N`. Given - /// `M` as the data type that can hold the maximum value of this per-thing (e.g. u32 for - /// perbill), this can only work if `N == M` or `N: From + TryInto`. - pub fn from_rational_approximation(p: N, q: N) -> Self - where N: Clone + Ord + From<$type> + TryInto<$type> + ops::Div - { - // q cannot be zero. - let q = q.max((1 as $type).into()); - // p should not be bigger than q. - let p = p.min(q.clone()); - - let factor = (q.clone() / $max.into()).max((1 as $type).into()); - - // q cannot overflow: (q / (q/$max)) < 2 * $max. p < q hence p also cannot overflow. - // this implies that $type must be able to fit 2 * $max. - let q_reduce: $type = (q / factor.clone()) - .try_into() - .map_err(|_| "Failed to convert") - .expect( - "q / (q/$max) < (2 * $max). Macro prevents any type being created that \ - does not satisfy this; qed" - ); - let p_reduce: $type = (p / factor.clone()) - .try_into() - .map_err(|_| "Failed to convert") - .expect( - "q / (q/$max) < (2 * $max). Macro prevents any type being created that \ - does not satisfy this; qed" - ); - - // `p_reduced` and `q_reduced` are withing $type. Mul by another $max will always - // fit in $upper_type. This is guaranteed by the macro tests. - let part = - p_reduce as $upper_type - * ($max as $upper_type) - / q_reduce as $upper_type; - - $name(part as $type) - } - } - - impl Saturating for $name { - fn saturating_add(self, rhs: Self) -> Self { - // defensive-only: since `$max * 2 < $type::max_value()`, this can never overflow. - Self::from_parts(self.0.saturating_add(rhs.0)) - } - fn saturating_sub(self, rhs: Self) -> Self { - Self::from_parts(self.0.saturating_sub(rhs.0)) - } - fn saturating_mul(self, rhs: Self) -> Self { - let a = self.0 as $upper_type; - let b = rhs.0 as $upper_type; - let m = $max as $upper_type; - let parts = a * b / m; - // This will always fit into $type. - Self::from_parts(parts as $type) - } - } - - impl ops::Div for $name { - type Output = Self; - - fn div(self, rhs: Self) -> Self::Output { - let p = self.0; - let q = rhs.0; - Self::from_rational_approximation(p, q) - } - } - - /// Overflow-prune multiplication. - /// - /// tailored to be used with a balance type. - impl ops::Mul for $name - where - N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem - + ops::Div + ops::Mul + ops::Add, - { - type Output = N; - fn mul(self, b: N) -> Self::Output { - let maximum: N = $max.into(); - let upper_max: $upper_type = $max.into(); - let part: N = self.0.into(); - - let rem_multiplied_divided = { - let rem = b.clone().rem(maximum.clone()); - - // `rem_sized` is inferior to $max, thus it fits into $type. This is assured by - // a test. - let rem_sized = rem.saturated_into::<$type>(); - - // `self` and `rem_sized` are inferior to $max, thus the product is less than - // $max^2 and fits into $upper_type. This is assured by a test. - let rem_multiplied_upper = rem_sized as $upper_type * self.0 as $upper_type; - - // `rem_multiplied_upper` is less than $max^2 therefore divided by $max it fits - // in $type. remember that $type always fits $max. - let mut rem_multiplied_divided_sized = - (rem_multiplied_upper / upper_max) as $type; - // fix a tiny rounding error - if rem_multiplied_upper % upper_max > upper_max / 2 { - rem_multiplied_divided_sized += 1; - } - - // `rem_multiplied_divided_sized` is inferior to b, thus it can be converted - // back to N type - rem_multiplied_divided_sized.into() - }; - - (b / maximum) * part + rem_multiplied_divided - } - } - - impl codec::CompactAs for $name { - type As = $type; - fn encode_as(&self) -> &$type { - &self.0 - } - fn decode_from(x: $type) -> Self { - Self(x) - } - } - - impl From> for $name { - fn from(x: codec::Compact<$name>) -> Self { - x.0 - } - } - - #[cfg(test)] - mod $test_mod { - use codec::{Encode, Decode}; - use super::{$name, Saturating}; - use crate::{assert_eq_error_rate, traits::Zero}; - - - #[test] - fn macro_expanded_correctly() { - // needed for the `from_percent` to work. - assert!($max >= 100); - assert!($max % 100 == 0); - - // needed for `from_rational_approximation` - assert!(2 * $max < <$type>::max_value()); - assert!(($max as $upper_type) < <$upper_type>::max_value()); - - // for something like percent they can be the same. - assert!((<$type>::max_value() as $upper_type) <= <$upper_type>::max_value()); - assert!(($max as $upper_type).checked_mul($max.into()).is_some()); - } - - #[derive(Encode, Decode, PartialEq, Eq, Debug)] - struct WithCompact { - data: T, - } - - #[test] - fn has_compact() { - let data = WithCompact { data: $name(1) }; - let encoded = data.encode(); - assert_eq!(data, WithCompact::<$name>::decode(&mut &encoded[..]).unwrap()); - } - - #[test] - fn compact_encoding() { - let tests = [ - // assume all per_things have the size u8 at least. - (0 as $type, 1usize), - (1 as $type, 1usize), - (63, 1), - (64, 2), - (65, 2), - (<$type>::max_value(), <$type>::max_value().encode().len() + 1) - ]; - for &(n, l) in &tests { - let compact: crate::codec::Compact<$name> = $name(n).into(); - let encoded = compact.encode(); - assert_eq!(encoded.len(), l); - let decoded = >::decode(&mut & encoded[..]) - .unwrap(); - let per_thingy: $name = decoded.into(); - assert_eq!(per_thingy, $name(n)); - } - } - - #[test] - fn per_thing_api_works() { - // some really basic stuff - assert_eq!($name::zero(), $name::from_parts(Zero::zero())); - assert_eq!($name::one(), $name::from_parts($max)); - assert_eq!($name::accuracy(), $max); - assert_eq!($name::from_percent(0), $name::from_parts(Zero::zero())); - assert_eq!($name::from_percent(10), $name::from_parts($max / 10)); - assert_eq!($name::from_percent(100), $name::from_parts($max)); - } - - macro_rules! per_thing_mul_test { - ($num_type:tt) => { - // multiplication from all sort of from_percent - assert_eq!( - $name::from_percent(100) * $num_type::max_value(), - $num_type::max_value() - ); - assert_eq_error_rate!( - $name::from_percent(99) * $num_type::max_value(), - ((Into::::into($num_type::max_value()) * 99u32) / 100u32).as_u128() as $num_type, - 1, - ); - assert_eq!( - $name::from_percent(50) * $num_type::max_value(), - $num_type::max_value() / 2, - ); - assert_eq_error_rate!( - $name::from_percent(1) * $num_type::max_value(), - $num_type::max_value() / 100, - 1, - ); - assert_eq!($name::from_percent(0) * $num_type::max_value(), 0); - - // // multiplication with bounds - assert_eq!($name::one() * $num_type::max_value(), $num_type::max_value()); - assert_eq!($name::zero() * $num_type::max_value(), 0); - } - } - - #[test] - fn per_thing_mul_works() { - use primitive_types::U256; - - // accuracy test - assert_eq!($name::from_rational_approximation(1 as $type, 3) * 30 as $type, 10); - - $(per_thing_mul_test!($test_units);)* - } - - #[test] - fn per_thing_mul_rounds_to_nearest_number() { - assert_eq!($name::from_percent(33) * 10u64, 3); - assert_eq!($name::from_percent(34) * 10u64, 3); - assert_eq!($name::from_percent(35) * 10u64, 3); - assert_eq!($name::from_percent(36) * 10u64, 4); - assert_eq!($name::from_percent(36) * 10u64, 4); - } - - #[test] - fn per_thing_multiplication_with_large_number() { - use primitive_types::U256; - let max_minus_one = $max - 1; - assert_eq_error_rate!( - $name::from_parts(max_minus_one) * std::u128::MAX, - ((Into::::into(std::u128::MAX) * max_minus_one) / $max).as_u128(), - 1, - ); - } - - macro_rules! per_thing_from_rationale_approx_test { - ($num_type:tt) => { - // within accuracy boundary - assert_eq!( - $name::from_rational_approximation(1 as $num_type, 0), - $name::one(), - ); - assert_eq!( - $name::from_rational_approximation(1 as $num_type, 1), - $name::one(), - ); - assert_eq_error_rate!( - $name::from_rational_approximation(1 as $num_type, 3).0, - $name::from_parts($max / 3).0, - 2 - ); - assert_eq!( - $name::from_rational_approximation(1 as $num_type, 10), - $name::from_percent(10), - ); - assert_eq!( - $name::from_rational_approximation(1 as $num_type, 4), - $name::from_percent(25), - ); - assert_eq!( - $name::from_rational_approximation(1 as $num_type, 4), - $name::from_rational_approximation(2 as $num_type, 8), - ); - // no accurate anymore but won't overflow. - assert_eq!( - $name::from_rational_approximation( - $num_type::max_value() - 1, - $num_type::max_value() - ), - $name::one(), - ); - assert_eq_error_rate!( - $name::from_rational_approximation( - $num_type::max_value() / 3, - $num_type::max_value() - ).0, - $name::from_parts($max / 3).0, - 2 - ); - assert_eq!( - $name::from_rational_approximation(1, $num_type::max_value()), - $name::zero(), - ); - }; - } - - #[test] - fn per_thing_from_rationale_approx_works() { - // This is just to make sure something like Percent which _might_ get built from a - // u8 does not overflow in the context of this test. - let max_value = $max as $upper_type; - // almost at the edge - assert_eq!( - $name::from_rational_approximation($max - 1, $max + 1), - $name::from_parts($max - 2), - ); - assert_eq!( - $name::from_rational_approximation(1, $max-1), - $name::from_parts(1), - ); - assert_eq!( - $name::from_rational_approximation(1, $max), - $name::from_parts(1), - ); - assert_eq!( - $name::from_rational_approximation(2, 2 * $max - 1), - $name::from_parts(1), - ); - assert_eq!( - $name::from_rational_approximation(1, $max+1), - $name::zero(), - ); - assert_eq!( - $name::from_rational_approximation(3 * max_value / 2, 3 * max_value), - $name::from_percent(50), - ); - $(per_thing_from_rationale_approx_test!($test_units);)* - } - - #[test] - fn per_things_mul_operates_in_output_type() { - // assert_eq!($name::from_percent(50) * 100u32, 50u32); - assert_eq!($name::from_percent(50) * 100u64, 50u64); - assert_eq!($name::from_percent(50) * 100u128, 50u128); - } - - #[test] - fn per_thing_saturating_op_works() { - assert_eq!( - $name::from_percent(50).saturating_add($name::from_percent(40)), - $name::from_percent(90) - ); - assert_eq!( - $name::from_percent(50).saturating_add($name::from_percent(50)), - $name::from_percent(100) - ); - assert_eq!( - $name::from_percent(60).saturating_add($name::from_percent(50)), - $name::from_percent(100) - ); - - assert_eq!( - $name::from_percent(60).saturating_sub($name::from_percent(50)), - $name::from_percent(10) - ); - assert_eq!( - $name::from_percent(60).saturating_sub($name::from_percent(60)), - $name::from_percent(0) - ); - assert_eq!( - $name::from_percent(60).saturating_sub($name::from_percent(70)), - $name::from_percent(0) - ); - - assert_eq!( - $name::from_percent(50).saturating_mul($name::from_percent(50)), - $name::from_percent(25) - ); - assert_eq!( - $name::from_percent(20).saturating_mul($name::from_percent(20)), - $name::from_percent(4) - ); - assert_eq!( - $name::from_percent(10).saturating_mul($name::from_percent(10)), - $name::from_percent(1) - ); - } - - #[test] - fn per_thing_square_works() { - assert_eq!($name::from_percent(100).square(), $name::from_percent(100)); - assert_eq!($name::from_percent(50).square(), $name::from_percent(25)); - assert_eq!($name::from_percent(10).square(), $name::from_percent(1)); - assert_eq!( - $name::from_percent(2).square(), - $name::from_parts((4 * ($max as $upper_type) / 100 / 100) as $type) - ); - } - - #[test] - fn per_things_div_works() { - // normal - assert_eq!($name::from_percent(10) / $name::from_percent(20), - $name::from_percent(50) - ); - assert_eq!($name::from_percent(10) / $name::from_percent(10), - $name::from_percent(100) - ); - assert_eq!($name::from_percent(10) / $name::from_percent(0), - $name::from_percent(100) - ); - - // will not overflow - assert_eq!($name::from_percent(10) / $name::from_percent(5), - $name::from_percent(100) - ); - assert_eq!($name::from_percent(100) / $name::from_percent(50), - $name::from_percent(100) - ); - } - } - }; -} - -implement_per_thing!( - Percent, - test_per_cent, - [u32, u64, u128], - 100u8, - u8, - u16, - "_Percent_", -); -implement_per_thing!( - Permill, - test_permill, - [u32, u64, u128], - 1_000_000u32, - u32, - u64, - "_Parts per Million_", -); -implement_per_thing!( - Perbill, - test_perbill, - [u32, u64, u128], - 1_000_000_000u32, - u32, - u64, - "_Parts per Billion_", -); -implement_per_thing!( - Perquintill, - test_perquintill, - [u64, u128], - 1_000_000_000_000_000_000u64, - u64, - u128, - "_Parts per Quintillion_", -); - -/// An unsigned fixed point number. Can hold any value in the range [-9_223_372_036, 9_223_372_036] -/// with fixed point accuracy of one billion. -#[cfg_attr(feature = "std", derive(Debug))] -#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Fixed64(i64); - -/// The accuracy of the `Fixed64` type. -const DIV: i64 = 1_000_000_000; - -impl Fixed64 { - /// creates self from a natural number. - /// - /// Note that this might be lossy. - pub fn from_natural(int: i64) -> Self { - Self(int.saturating_mul(DIV)) - } - - /// Return the accuracy of the type. Given that this function returns the value `X`, it means - /// that an instance composed of `X` parts (`Fixed64::from_parts(X)`) is equal to `1`. - pub fn accuracy() -> i64 { - DIV - } - - /// Raw constructor. Equal to `parts / 1_000_000_000`. - pub fn from_parts(parts: i64) -> Self { - Self(parts) - } - - /// creates self from a rational number. Equal to `n/d`. - /// - /// Note that this might be lossy. - pub fn from_rational(n: i64, d: u64) -> Self { - Self( - ((n as i128).saturating_mul(DIV as i128) / (d as i128).max(1)) - .try_into() - .unwrap_or(Bounded::max_value()) - ) - } - - /// Performs a saturated multiply and accumulate by unsigned number. - /// - /// Returns a saturated `int + (self * int)`. - pub fn saturated_multiply_accumulate(&self, int: N) -> N - where - N: TryFrom + From + UniqueSaturatedInto + Bounded + Clone + Saturating + - ops::Rem + ops::Div + ops::Mul + - ops::Add, - { - let div = DIV as u64; - let positive = self.0 > 0; - // safe to convert as absolute value. - let parts = self.0.checked_abs().map(|v| v as u64).unwrap_or(i64::max_value() as u64 + 1); - - - // will always fit. - let natural_parts = parts / div; - // might saturate. - let natural_parts: N = natural_parts.saturated_into(); - // fractional parts can always fit into u32. - let perbill_parts = (parts % div) as u32; - - let n = int.clone().saturating_mul(natural_parts); - let p = Perbill::from_parts(perbill_parts) * int.clone(); - - // everything that needs to be either added or subtracted from the original weight. - let excess = n.saturating_add(p); - - if positive { - int.saturating_add(excess) - } else { - int.saturating_sub(excess) - } - } -} - -impl Saturating for Fixed64 { - fn saturating_add(self, rhs: Self) -> Self { - Self(self.0.saturating_add(rhs.0)) - } - fn saturating_mul(self, rhs: Self) -> Self { - Self(self.0.saturating_mul(rhs.0) / DIV) - } - fn saturating_sub(self, rhs: Self) -> Self { - Self(self.0.saturating_sub(rhs.0)) - } -} - -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait -/// for safe addition. -impl ops::Add for Fixed64 { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - Self(self.0 + rhs.0) - } -} - -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait -/// for safe subtraction. -impl ops::Sub for Fixed64 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self::Output { - Self(self.0 - rhs.0) - } -} - -impl CheckedSub for Fixed64 { - fn checked_sub(&self, rhs: &Self) -> Option { - if let Some(v) = self.0.checked_sub(rhs.0) { - Some(Self(v)) - } else { - None - } - } -} - -impl CheckedAdd for Fixed64 { - fn checked_add(&self, rhs: &Self) -> Option { - if let Some(v) = self.0.checked_add(rhs.0) { - Some(Self(v)) - } else { - None - } - } -} - -/// Infinite precision unsigned integer for substrate runtime. -pub mod biguint { - use super::Zero; - use rstd::{cmp::Ordering, ops, prelude::*, cell::RefCell, convert::TryFrom}; - - // A sensible value for this would be half of the dword size of the host machine. Since the - // runtime is compiled to 32bit webassembly, using 32 and 64 for single and double respectively - // should yield the most performance. TODO #3745 we could benchmark this and verify. - /// Representation of a single limb. - pub type Single = u32; - /// Representation of two limbs. - pub type Double = u64; - /// Difference in the number of bits of [`Single`] and [`Double`]. - const SHIFT: usize = 32; - /// short form of _Base_. Analogous to the value 10 in base-10 decimal numbers. - const B: Double = Single::max_value() as Double + 1; - - /// Splits a [`Double`] limb number into a tuple of two [`Single`] limb numbers. - pub fn split(a: Double) -> (Single, Single) { - let al = a as Single; - let ah = (a >> SHIFT) as Single; - (ah, al) - } - - /// Assumed as a given primitive. - /// - /// Multiplication of two singles, which at most yields 1 double. - pub fn mul_single(a: Single, b: Single) -> Double { - let a: Double = a.into(); - let b: Double = b.into(); - let r = a * b; - r - } - - /// Assumed as a given primitive. - /// - /// Addition of two singles, which at most takes a single limb of result and a carry, - /// returned as a tuple respectively. - pub fn add_single(a: Single, b: Single) -> (Single, Single) { - let a: Double = a.into(); - let b: Double = b.into(); - let q = a + b; - let (carry, r) = split(q); - (r, carry) - } - - /// Assumed as a given primitive. - /// - /// Division of double by a single limb. Always returns a double limb of quotient and a single - /// limb of remainder. - fn div_single(a: Double, b: Single) -> (Double, Single) { - let b: Double = b.into(); - let q = a / b; - let r = a % b; - // both conversions are trivially safe. - (q, r as Single) - } - - /// Simple wrapper around an infinitely large integer, represented as limbs of [`Single`]. - #[derive(Clone, Default)] - pub struct BigUint { - /// digits (limbs) of this number (sorted as msb -> lsd). - pub(crate) digits: Vec, - } - - impl BigUint { - /// Create a new instance with `size` limbs. This prevents any number with zero limbs to be - /// created. - /// - /// The behavior of the type is undefined with zero limbs. - pub fn with_capacity(size: usize) -> Self { - Self { digits: vec![0; size.max(1)] } - } - - /// Raw constructor from custom limbs. If `limbs` is empty, `Zero::zero()` implementation is - /// used. - pub fn from_limbs(limbs: &[Single]) -> Self { - if limbs.len() > 0 { - Self { digits: limbs.to_vec() } - } else { - Zero::zero() - } - } - - /// Number of limbs. - pub fn len(&self) -> usize { self.digits.len() } - - /// A naive getter for limb at `index`. Note that the order is lsb -> msb. - /// - /// #### Panics - /// - /// This panics if index is out of range. - pub fn get(&self, index: usize) -> Single { - self.digits[self.len() - 1 - index] - } - - /// A naive getter for limb at `index`. Note that the order is lsb -> msb. - pub fn checked_get(&self, index: usize) -> Option { - if let Some(i) = self.len().checked_sub(1) { - if let Some(j) = i.checked_sub(index) { - return self.digits.get(j).cloned(); - } - } - return None; - } - - /// A naive setter for limb at `index`. Note that the order is lsb -> msb. - /// - /// #### Panics - /// - /// This panics if index is out of range. - pub fn set(&mut self, index: usize, value: Single) { - let len = self.digits.len(); - self.digits[len - 1 - index] = value; - } - - /// returns the least significant limb of the number. - /// - /// #### Panics - /// - /// While the constructor of the type prevents this, this can panic if `self` has no digits. - pub fn lsb(&self) -> Single { - self.digits[self.len() - 1] - } - - /// returns the most significant limb of the number. - /// - /// #### Panics - /// - /// While the constructor of the type prevents this, this can panic if `self` has no digits. - pub fn msb(&self) -> Single { - self.digits[0] - } - - /// Strips zeros from the left side of `self`, if any. - pub fn lstrip(&mut self) { - // by definition, a big-int number should never have leading zero limbs. This function - // has the ability to cause this. There is nothing to do if the number already has 1 - // limb only. call it a day and return. - if self.len().is_zero() { return; } - let mut index = 0; - for elem in self.digits.iter() { - if *elem != 0 { break } else { index += 1 } - } - if index > 0 { - self.digits = self.digits[index..].to_vec() - } - } - - /// Zero-pad `self` from left to reach `size` limbs. Will not make any difference if `self` - /// is already bigger than `size` limbs. - pub fn lpad(&mut self, size: usize) { - let n = self.len(); - if n >= size { return; } - let pad = size - n; - let mut new_digits = (0..pad).map(|_| 0).collect::>(); - new_digits.extend(self.digits.iter()); - self.digits = new_digits; - } - - /// Adds `self` with `other`. self and other do not have to have any particular size. Given - /// that the `n = max{size(self), size(other)}`, it will produce a number with `n + 1` - /// limbs. - /// - /// This function does not strip the output and returns the original allocated `n + 1` - /// limbs. The caller may strip the output if desired. - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn add(self, other: &Self) -> Self { - let n = self.len().max(other.len()); - let mut k: Double = 0; - let mut w = Self::with_capacity(n + 1); - - for j in 0..n { - let u = Double::from(self.checked_get(j).unwrap_or(0)); - let v = Double::from(other.checked_get(j).unwrap_or(0)); - let s = u + v + k; - w.set(j, (s % B) as Single); - k = s / B; - } - // k is always 0 or 1. - w.set(n, k as Single); - w - } - - /// Subtracts `other` from `self`. self and other do not have to have any particular size. - /// Given that the `n = max{size(self), size(other)}`, it will produce a number of size `n`. - /// - /// If `other` is bigger than `self`, `Err(B - borrow)` is returned. - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn sub(self, other: &Self) -> Result { - let n = self.len().max(other.len()); - let mut k = 0; - let mut w = Self::with_capacity(n); - for j in 0..n { - let s = { - let u = Double::from(self.checked_get(j).unwrap_or(0)); - let v = Double::from(other.checked_get(j).unwrap_or(0)); - let mut needs_borrow = false; - let mut t = 0; - - if let Some(v) = u.checked_sub(v) { - if let Some(v2) = v.checked_sub(k) { - t = v2 % B; - k = 0; - } else { - needs_borrow = true; - } - } else { - needs_borrow = true; - } - if needs_borrow { - t = u + B - v - k; - k = 1; - } - t - }; - // PROOF: t either comes from `v2 % B`, or from `u + B - v - k`. The former is - // trivial. The latter will not overflow this branch will only happen if the sum of - // `u - v - k` part has been negative, hence `u + B - v - k < b`. - w.set(j, s as Single); - } - - if k.is_zero() { - Ok(w) - } else { - Err(w) - } - } - - /// Multiplies n-limb number `self` with m-limb number `other`. - /// - /// The resulting number will always have `n + m` limbs. - /// - /// This function does not strip the output and returns the original allocated `n + m` - /// limbs. The caller may strip the output if desired. - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn mul(self, other: &Self) -> Self { - let n = self.len(); - let m = other.len(); - let mut w = Self::with_capacity(m + n); - - for j in 0..n { - if self.get(j) == 0 { - // Note: `with_capacity` allocates with 0. Explicitly set j + m to zero if - // otherwise. - continue; - } - - let mut k = 0; - for i in 0..m { - // PROOF: (B−1) × (B−1) + (B−1) + (B−1) = B^2 −1 < B^2. addition is safe. - let t = - mul_single(self.get(j), other.get(i)) - + Double::from(w.get(i + j)) - + Double::from(k); - w.set(i + j, (t % B) as Single); - // PROOF: (B^2 - 1) / B < B. conversion is safe. - k = (t / B) as Single; - } - w.set(j + m, k); - } - w - } - - /// Divides `self` by a single limb `other`. This can be used in cases where the original - /// division cannot work due to the divisor (`other`) being just one limb. - /// - /// Invariant: `other` cannot be zero. - pub fn div_unit(self, mut other: Single) -> Self { - other = other.max(1); - let n = self.len(); - let mut out = Self::with_capacity(n); - let mut r: Single = 0; - // PROOF: (B-1) * B + (B-1) still fits in double - let with_r = |x: Double, r: Single| { r as Double * B + x }; - for d in (0..=n-1).rev() { - let (q, rr) = div_single(with_r(self.get(d).into(), r), other) ; - out.set(d, q as Single); - r = rr; - } - out - } - - /// Divides an `n + m` limb self by a `n` limb `other`. The result is a `m + 1` limb - /// quotient and a `n` limb remainder, if enabled by passing `true` in `rem` argument, both - /// in the form of an option's `Ok`. - /// - /// - requires `other` to be stripped and have no leading zeros. - /// - requires `self` to be stripped and have no leading zeros. - /// - requires `other` to have at least two limbs. - /// - requires `self` to have a greater length compared to `other`. - /// - /// All arguments are examined without being stripped for the above conditions. If any of - /// the above fails, `None` is returned.` - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn div(self, other: &Self, rem: bool) -> Option<(Self, Self)> { - if other.len() <= 1 - || other.msb() == 0 - || self.msb() == 0 - || self.len() <= other.len() - { - return None - } - let n = other.len(); - let m = self.len() - n; - - let mut q = Self::with_capacity(m + 1); - let mut r = Self::with_capacity(n); - - debug_assert!(other.msb() != 0); - - // PROOF: 0 <= normalizer_bits < SHIFT 0 <= normalizer < B. all conversions are - // safe. - let normalizer_bits = other.msb().leading_zeros() as Single; - let normalizer = (2 as Single).pow(normalizer_bits as u32) as Single; - - // step D1. - let mut self_norm = self.mul(&Self::from(normalizer)); - let mut other_norm = other.clone().mul(&Self::from(normalizer)); - - // defensive only; the mul implementation should always create this. - self_norm.lpad(n + m + 1); - other_norm.lstrip(); - - // step D2. - for j in (0..=m).rev() { - // step D3.0 Find an estimate of q[j], named qhat. - let (qhat, rhat) = { - // PROOF: this always fits into `Double`. In the context of Single = u8, and - // Double = u16, think of 255 * 256 + 255 which is just u16::max_value(). - let dividend = - Double::from(self_norm.get(j + n)) - * B - + Double::from(self_norm.get(j + n - 1)); - let divisor = other_norm.get(n - 1); - div_single(dividend, divisor.into()) - }; - - // D3.1 test qhat - // replace qhat and rhat with RefCells. This helps share state with the closure - let qhat = RefCell::new(qhat); - let rhat = RefCell::new(rhat as Double); - - let test = || { - // decrease qhat if it is bigger than the base (B) - let qhat_local = *qhat.borrow(); - let rhat_local = *rhat.borrow(); - let predicate_1 = qhat_local >= B; - let predicate_2 = { - let lhs = qhat_local * other_norm.get(n - 2) as Double; - let rhs = B * rhat_local + self_norm.get(j + n - 2) as Double; - lhs > rhs - }; - if predicate_1 || predicate_2 { - *qhat.borrow_mut() -= 1; - *rhat.borrow_mut() += other_norm.get(n - 1) as Double; - true - } else { - false - } - }; - - test(); - while (*rhat.borrow() as Double) < B { - if !test() { break; } - } - - let qhat = qhat.into_inner(); - // we don't need rhat anymore. just let it go out of scope when it does. - - // step D4 - let lhs = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; - let rhs = other_norm.clone().mul(&Self::from(qhat)); - - let maybe_sub = lhs.sub(&rhs); - let mut negative = false; - let sub = match maybe_sub { - Ok(t) => t, - Err(t) => { negative = true; t } - }; - (j..=j+n).for_each(|d| { self_norm.set(d, sub.get(d - j)); }); - - // step D5 - // PROOF: the `test()` specifically decreases qhat until it is below `B`. conversion - // is safe. - q.set(j, qhat as Single); - - // step D6: add back if negative happened. - if negative { - q.set(j, q.get(j) - 1); - let u = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; - let r = other_norm.clone().add(&u); - (j..=j+n).rev().for_each(|d| { self_norm.set(d, r.get(d - j)); }) - } - } - - // if requested, calculate remainder. - if rem { - // undo the normalization. - if normalizer_bits > 0 { - let s = SHIFT as u32; - let nb = normalizer_bits; - for d in 0..n-1 { - let v = self_norm.get(d) >> nb - | self_norm.get(d + 1).overflowing_shl(s - nb).0; - r.set(d, v); - } - r.set(n - 1, self_norm.get(n - 1) >> normalizer_bits); - } else { - r = self_norm; - } - } - - Some((q, r)) - } - } - - #[cfg(feature = "std")] - impl rstd::fmt::Debug for BigUint { - fn fmt(&self, f: &mut rstd::fmt::Formatter<'_>) -> rstd::fmt::Result { - write!( - f, - "BigUint {{ {:?} ({:?})}}", - self.digits, - u128::try_from(self.clone()).unwrap_or_else(|_| 0), - ) - } - } - - impl PartialEq for BigUint { - fn eq(&self, other: &Self) -> bool { - // sadly, we have to reallocate here as strip mutably uses self. - let mut lhs = self.clone(); - let mut rhs = other.clone(); - lhs.lstrip(); - rhs.lstrip(); - lhs.digits.eq(&rhs.digits) - } - } - - impl Eq for BigUint {} - - impl Ord for BigUint { - fn cmp(&self, other: &Self) -> Ordering { - let lhs_first = self.digits.iter().position(|&e| e != 0); - let rhs_first = other.digits.iter().position(|&e| e != 0); - - match (lhs_first, rhs_first) { - // edge cases that should not happen. This basically means that one or both were - // zero. - (None, None) => Ordering::Equal, - (Some(_), None) => Ordering::Greater, - (None, Some(_)) => Ordering::Less, - (Some(lhs_idx), Some(rhs_idx)) => { - let lhs = &self.digits[lhs_idx..]; - let rhs = &other.digits[rhs_idx..]; - let len_cmp = lhs.len().cmp(&rhs.len()); - match len_cmp { - Ordering::Equal => lhs.cmp(rhs), - _ => len_cmp, - } - } - } - } - } - - impl PartialOrd for BigUint { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } - } - - impl ops::Add for BigUint { - type Output = Self; - fn add(self, rhs: Self) -> Self::Output { - self.add(&rhs) - } - } - - impl ops::Sub for BigUint { - type Output = Self; - fn sub(self, rhs: Self) -> Self::Output { - self.sub(&rhs).unwrap_or_else(|e| e) - } - } - - impl ops::Mul for BigUint { - type Output = Self; - fn mul(self, rhs: Self) -> Self::Output { - self.mul(&rhs) - } - } - - impl Zero for BigUint { - fn zero() -> Self { - Self { digits: vec![Zero::zero()] } - } - - fn is_zero(&self) -> bool { - self.digits.iter().all(|d| d.is_zero()) - } - } - - macro_rules! impl_try_from_number_for { - ($([$type:ty, $len:expr]),+) => { - $( - impl TryFrom for $type { - type Error = &'static str; - fn try_from(mut value: BigUint) -> Result<$type, Self::Error> { - value.lstrip(); - let error_message = concat!("cannot fit a number into ", stringify!($type)); - if value.len() * SHIFT > $len { - Err(error_message) - } else { - let mut acc: $type = Zero::zero(); - for (i, d) in value.digits.iter().rev().cloned().enumerate() { - let d: $type = d.into(); - acc += d << (SHIFT * i); - } - Ok(acc) - } - } - } - )* - }; - } - // can only be implemented for sizes bigger than two limb. - impl_try_from_number_for!([u128, 128], [u64, 64]); - - macro_rules! impl_from_for_smaller_than_word { - ($($type:ty),+) => { - $(impl From<$type> for BigUint { - fn from(a: $type) -> Self { - Self { digits: vec! [a.into()] } - } - })* - } - } - impl_from_for_smaller_than_word!(u8, u16, Single); - - impl From for BigUint { - fn from(a: Double) -> Self { - let (ah, al) = split(a); - Self { digits: vec![ah, al] } - } - } - - #[cfg(test)] - pub mod tests_biguint { - use super::*; - use rand::Rng; - #[cfg(feature = "bench")] - use test::Bencher; - - // TODO move into a proper fuzzer #3745 - const FUZZ_COUNT: usize = 100_000; - - pub fn random_big_uint(size: usize) -> BigUint { - let mut rng = rand::thread_rng(); - let digits = (0..size).map(|_| rng.gen_range(0, Single::max_value())).collect(); - BigUint { digits } - } - - fn run_with_data_set( - count: usize, - limbs_ub_1: usize, - limbs_ub_2: usize, - exact: bool, - assertion: F, - ) where - F: Fn(BigUint, BigUint) -> () - { - let mut rng = rand::thread_rng(); - for _ in 0..count { - let digits_len_1 = if exact { limbs_ub_1 } else { rng.gen_range(1, limbs_ub_1) }; - let digits_len_2 = if exact { limbs_ub_2 } else { rng.gen_range(1, limbs_ub_2) }; - - let u = random_big_uint(digits_len_1); - let v = random_big_uint(digits_len_2); - assertion(u, v); - } - } - - fn with_limbs(n: usize) -> BigUint { - BigUint { digits: vec![1; n] } - } - - #[test] - fn split_works() { - let a = SHIFT / 2; - let b = SHIFT * 3 / 2; - let num: Double = 1 << a | 1 << b; - // example when `Single = u8` - // assert_eq!(num, 0b_0001_0000_0001_0000) - assert_eq!(split(num), (1 << a, 1 << a)); - } - - #[test] - fn strip_works() { - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![1, 0] }); - - let mut a = BigUint::from_limbs(&[0, 0, 1]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![1] }); - - let mut a = BigUint::from_limbs(&[0, 0]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![0] }); - - let mut a = BigUint::from_limbs(&[0, 0, 0]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![0] }); - } - - #[test] - fn lpad_works() { - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lpad(2); - assert_eq!(a.digits, vec![0, 1, 0]); - - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lpad(3); - assert_eq!(a.digits, vec![0, 1, 0]); - - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lpad(4); - assert_eq!(a.digits, vec![0, 0, 1, 0]); - } - - #[test] - fn equality_works() { - assert_eq!( - BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, - true, - ); - assert_eq!( - BigUint { digits: vec![3, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, - false, - ); - assert_eq!( - BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, - true, - ); - } - - #[test] - fn ordering_works() { - assert!(BigUint { digits: vec![0] } < BigUint { digits: vec![1] }); - assert!(BigUint { digits: vec![0] } == BigUint { digits: vec![0] }); - assert!(BigUint { digits: vec![] } == BigUint { digits: vec![0] }); - assert!(BigUint { digits: vec![] } == BigUint { digits: vec![] }); - assert!(BigUint { digits: vec![] } < BigUint { digits: vec![1] }); - - assert!(BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); - assert!(BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); - - assert!(BigUint { digits: vec![1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); - assert!(BigUint { digits: vec![0, 1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); - assert!(BigUint { digits: vec![1, 2, 1, 0] } > BigUint { digits: vec![1, 2, 3] }); - - assert!(BigUint { digits: vec![0, 1, 2, 1] } < BigUint { digits: vec![1, 2, 3] }); - } - - #[test] - fn basic_random_ord_eq_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { - let ue = S::try_from(u.clone()).unwrap(); - let ve = S::try_from(v.clone()).unwrap(); - assert_eq!(u.cmp(&v), ue.cmp(&ve)); - assert_eq!(u.eq(&v), ue.eq(&ve)); - }) - } - - #[test] - fn can_try_build_numbers_from_types() { - use rstd::convert::TryFrom; - assert_eq!(u64::try_from(with_limbs(1)).unwrap(), 1); - assert_eq!(u64::try_from(with_limbs(2)).unwrap(), u32::max_value() as u64 + 2); - assert_eq!( - u64::try_from(with_limbs(3)).unwrap_err(), - "cannot fit a number into u64", - ); - assert_eq!( - u128::try_from(with_limbs(3)).unwrap(), - u32::max_value() as u128 + u64::max_value() as u128 + 3 - ); - } - - #[test] - fn zero_works() { - assert_eq!(BigUint::zero(), BigUint { digits: vec![0] }); - assert_eq!(BigUint { digits: vec![0, 1, 0] }.is_zero(), false); - assert_eq!(BigUint { digits: vec![0, 0, 0] }.is_zero(), true); - - let a = BigUint::zero(); - let b = BigUint::zero(); - let c = a * b; - assert_eq!(c.digits, vec![0, 0]); - } - - #[test] - fn basic_random_add_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 3, 3, false, |u, v| { - let expected = S::try_from(u.clone()).unwrap() + S::try_from(v.clone()).unwrap(); - let t = u.clone().add(&v); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - }) - } - - #[test] - fn sub_negative_works() { - assert_eq!( - BigUint::from(10 as Single).sub(&BigUint::from(5 as Single)).unwrap(), - BigUint::from(5 as Single) - ); - assert_eq!( - BigUint::from(10 as Single).sub(&BigUint::from(10 as Single)).unwrap(), - BigUint::from(0 as Single) - ); - assert_eq!( - BigUint::from(10 as Single).sub(&BigUint::from(13 as Single)).unwrap_err(), - BigUint::from((B - 3) as Single), - ); - } - - #[test] - fn basic_random_sub_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { - let expected = S::try_from(u.clone()).unwrap() - .checked_sub(S::try_from(v.clone()).unwrap()); - let t = u.clone().sub(&v); - if expected.is_none() { - assert!(t.is_err()) - } else { - let t = t.unwrap(); - let expected = expected.unwrap(); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - } - }) - } - - #[test] - fn basic_random_mul_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 2, 2, false, |u, v| { - let expected = S::try_from(u.clone()).unwrap() * S::try_from(v.clone()).unwrap(); - let t = u.clone().mul(&v); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - }) - } - - #[test] - fn mul_always_appends_one_digit() { - let a = BigUint::from(10 as Single); - let b = BigUint::from(4 as Single); - assert_eq!(a.len(), 1); - assert_eq!(b.len(), 1); - - let n = a.mul(&b); - - assert_eq!(n.len(), 2); - assert_eq!(n.digits, vec![0, 40]); - } - - #[test] - fn div_conditions_work() { - let a = BigUint { digits: vec![2] }; - let b = BigUint { digits: vec![1, 2] }; - let c = BigUint { digits: vec![1, 1, 2] }; - let d = BigUint { digits: vec![0, 2] }; - let e = BigUint { digits: vec![0, 1, 1, 2] }; - - assert!(a.clone().div(&b, true).is_none()); - assert!(c.clone().div(&a, true).is_none()); - assert!(c.clone().div(&d, true).is_none()); - assert!(e.clone().div(&a, true).is_none()); - - assert!(c.clone().div(&b, true).is_some()); - } - - #[test] - fn div_unit_works() { - let a = BigUint { digits: vec![100] }; - let b = BigUint { digits: vec![1, 100] }; - - assert_eq!(a.clone().div_unit(1), a); - assert_eq!(a.clone().div_unit(0), a); - assert_eq!(a.clone().div_unit(2), BigUint::from(50 as Single)); - assert_eq!(a.clone().div_unit(7), BigUint::from(14 as Single)); - - assert_eq!(b.clone().div_unit(1), b); - assert_eq!(b.clone().div_unit(0), b); - assert_eq!(b.clone().div_unit(2), BigUint::from(((B + 100) / 2) as Single)); - assert_eq!(b.clone().div_unit(7), BigUint::from(((B + 100) / 7) as Single)); - - } - - #[test] - fn basic_random_div_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { - let ue = S::try_from(u.clone()).unwrap(); - let ve = S::try_from(v.clone()).unwrap(); - let (q, r) = (ue / ve, ue % ve); - if let Some((qq, rr)) = u.clone().div(&v, true) { - assert_eq!( - S::try_from(qq.clone()).unwrap(), q, - "{:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, - ); - assert_eq!( - S::try_from(rr.clone()).unwrap(), r, - "{:?} % {:?} ===> {:?} != {:?}", u, v, rr, r, - ); - } else if v.len() == 1 { - let qq = u.clone().div_unit(ve as Single); - assert_eq!( - S::try_from(qq.clone()).unwrap(), q, - "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, - ); - } else { - if v.msb() == 0 || v.msb() == 0 || u.len() <= v.len() {} // nada - else { panic!("div returned none for an unexpected reason"); } - } - }) - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_addition_2_digit(bencher: &mut Bencher) { - let a = random_big_uint(2); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().add(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_addition_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(4); - bencher.iter(|| { - let _ = a.clone().add(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_subtraction_2_digit(bencher: &mut Bencher) { - let a = random_big_uint(2); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().sub(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_subtraction_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(4); - bencher.iter(|| { - let _ = a.clone().sub(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_multiplication_2_digit(bencher: &mut Bencher) { - let a = random_big_uint(2); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().mul(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_multiplication_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(4); - bencher.iter(|| { - let _ = a.clone().mul(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_division_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().div(&b, true); - }); - } - } -} - -/// Some helper functions to work with 128bit numbers. Note that the functionality provided here is -/// only sensible to use with 128bit numbers because for smaller sizes, you can always rely on -/// assumptions of a bigger type (u128) being available, or simply create a per-thing and use the -/// multiplication implementation provided there. -pub mod helpers_128bit { - use crate::biguint; - use crate::traits::Zero; - use rstd::{cmp::{min, max}, convert::TryInto}; - - /// Helper gcd function used in Rational128 implementation. - pub fn gcd(a: u128, b: u128) -> u128 { - match ((a, b), (a & 1, b & 1)) { - ((x, y), _) if x == y => y, - ((0, x), _) | ((x, 0), _) => x, - ((x, y), (0, 1)) | ((y, x), (1, 0)) => gcd(x >> 1, y), - ((x, y), (0, 0)) => gcd(x >> 1, y >> 1) << 1, - ((x, y), (1, 1)) => { - let (x, y) = (min(x, y), max(x, y)); - gcd((y - x) >> 1, x) - }, - _ => unreachable!(), - } - } - - /// split a u128 into two u64 limbs - pub fn split(a: u128) -> (u64, u64) { - let al = a as u64; - let ah = (a >> 64) as u64; - (ah, al) - } - - /// Convert a u128 to a u32 based biguint. - pub fn to_big_uint(x: u128) -> biguint::BigUint { - let (xh, xl) = split(x); - let (xhh, xhl) = biguint::split(xh); - let (xlh, xll) = biguint::split(xl); - let mut n = biguint::BigUint::from_limbs(&[xhh, xhl, xlh, xll]); - n.lstrip(); - n - } - - /// Safely and accurately compute `a * b / c`. The approach is: - /// - Simply try `a * b / c`. - /// - Else, convert them both into big numbers and re-try. `Err` is returned if the result - /// cannot be safely casted back to u128. - /// - /// Invariant: c must be greater than or equal to 1. - pub fn multiply_by_rational(a: u128, b: u128, c: u128) -> Result { - if a.is_zero() || b.is_zero() { return Ok(Zero::zero()); } - let c = c.max(1); - - // a and b are interchangeable by definition in this function. It always helps to assume the - // bigger of which is being multiplied by a `0 < b/c < 1`. Hence, a should be the bigger and - // b the smaller one. - let t = a; - let a = a.max(b); - let b = t.min(b); - - if let Some(x) = a.checked_mul(b) { - // This is the safest way to go. Try it. - Ok(x / c) - } else { - let a_num = to_big_uint(a); - let b_num = to_big_uint(b); - let c_num = to_big_uint(c); - - let mut ab = a_num * b_num; - ab.lstrip(); - let mut q = if c_num.len() == 1 { - // PROOF: if `c_num.len() == 1` then `c` fits in one limb. - ab.div_unit(c as biguint::Single) - } else { - // PROOF: both `ab` and `c` cannot have leading zero limbs; if length of `c` is 1, - // the previous branch would handle. Also, if ab for sure has a bigger size than - // c, because `a.checked_mul(b)` has failed, hence ab must be at least one limb - // bigger than c. In this case, returning zero is defensive-only and div should - // always return Some. - let (mut q, r) = ab.div(&c_num, true).unwrap_or((Zero::zero(), Zero::zero())); - let r: u128 = r.try_into() - .expect("reminder of div by c is always less than c; qed"); - if r > (c / 2) { q = q.add(&to_big_uint(1)); } - q - }; - q.lstrip(); - q.try_into().map_err(|_| "result cannot fit in u128") - } - } -} - -/// A wrapper for any rational number with a 128 bit numerator and denominator. -#[derive(Clone, Copy, Default, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct Rational128(u128, u128); - -impl Rational128 { - /// Nothing. - pub fn zero() -> Self { - Self(0, 1) - } - - /// If it is zero or not - pub fn is_zero(&self) -> bool { - self.0.is_zero() - } - - /// Build from a raw `n/d`. - pub fn from(n: u128, d: u128) -> Self { - Self(n, d.max(1)) - } - - /// Build from a raw `n/d`. This could lead to / 0 if not properly handled. - pub fn from_unchecked(n: u128, d: u128) -> Self { - Self(n, d) - } - - /// Return the numerator. - pub fn n(&self) -> u128 { - self.0 - } - - /// Return the denominator. - pub fn d(&self) -> u128 { - self.1 - } - - /// Convert `self` to a similar rational number where denominator is the given `den`. - // - /// This only returns if the result is accurate. `Err` is returned if the result cannot be - /// accurately calculated. - pub fn to_den(self, den: u128) -> Result { - if den == self.1 { - Ok(self) - } else { - helpers_128bit::multiply_by_rational(self.0, den, self.1).map(|n| Self(n, den)) - } - } - - /// Get the least common divisor of `self` and `other`. - /// - /// This only returns if the result is accurate. `Err` is returned if the result cannot be - /// accurately calculated. - pub fn lcm(&self, other: &Self) -> Result { - // this should be tested better: two large numbers that are almost the same. - if self.1 == other.1 { return Ok(self.1) } - let g = helpers_128bit::gcd(self.1, other.1); - helpers_128bit::multiply_by_rational(self.1 , other.1, g) - } - - /// A saturating add that assumes `self` and `other` have the same denominator. - pub fn lazy_saturating_add(self, other: Self) -> Self { - if other.is_zero() { - self - } else { - Self(self.0.saturating_add(other.0) ,self.1) - } - } - - /// A saturating subtraction that assumes `self` and `other` have the same denominator. - pub fn lazy_saturating_sub(self, other: Self) -> Self { - if other.is_zero() { - self - } else { - Self(self.0.saturating_sub(other.0) ,self.1) - } - } - - /// Addition. Simply tries to unify the denominators and add the numerators. - /// - /// Overflow might happen during any of the steps. Error is returned in such cases. - pub fn checked_add(self, other: Self) -> Result { - let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; - let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - let n = self_scaled.0.checked_add(other_scaled.0) - .ok_or("overflow while adding numerators")?; - Ok(Self(n, self_scaled.1)) - } - - /// Subtraction. Simply tries to unify the denominators and subtract the numerators. - /// - /// Overflow might happen during any of the steps. None is returned in such cases. - pub fn checked_sub(self, other: Self) -> Result { - let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; - let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - - let n = self_scaled.0.checked_sub(other_scaled.0) - .ok_or("overflow while subtracting numerators")?; - Ok(Self(n, self_scaled.1)) - } -} - -impl PartialOrd for Rational128 { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for Rational128 { - fn cmp(&self, other: &Self) -> Ordering { - // handle some edge cases. - if self.1 == other.1 { - self.0.cmp(&other.0) - } else if self.1.is_zero() { - Ordering::Greater - } else if other.1.is_zero() { - Ordering::Less - } else { - // Don't even compute gcd. - let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); - let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); - self_n.cmp(&other_n) - } - } -} - -impl PartialEq for Rational128 { - fn eq(&self, other: &Self) -> bool { - // handle some edge cases. - if self.1 == other.1 { - self.0.eq(&other.0) - } else { - let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); - let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); - self_n.eq(&other_n) - } - } -} - -#[cfg(test)] -mod test_rational128 { - use super::*; - use super::helpers_128bit::*; - use rand::Rng; - - const MAX128: u128 = u128::max_value(); - const MAX64: u128 = u64::max_value() as u128; - const MAX64_2: u128 = 2 * u64::max_value() as u128; - - fn r(p: u128, q: u128) -> Rational128 { - Rational128(p, q) - } - - fn mul_div(a: u128, b: u128, c: u128) -> u128 { - use primitive_types::U256; - if a.is_zero() { return Zero::zero(); } - let c = c.max(1); - - // e for extended - let ae: U256 = a.into(); - let be: U256 = b.into(); - let ce: U256 = c.into(); - - let r = ae * be / ce; - if r > u128::max_value().into() { - a - } else { - r.as_u128() - } - } - - #[test] - fn truth_value_function_works() { - assert_eq!( - mul_div(2u128.pow(100), 8, 4), - 2u128.pow(101) - ); - assert_eq!( - mul_div(2u128.pow(100), 4, 8), - 2u128.pow(99) - ); - - // and it returns a if result cannot fit - assert_eq!(mul_div(MAX128 - 10, 2, 1), MAX128 - 10); - } - - #[test] - fn to_denom_works() { - // simple up and down - assert_eq!(r(1, 5).to_den(10), Ok(r(2, 10))); - assert_eq!(r(4, 10).to_den(5), Ok(r(2, 5))); - - // up and down with large numbers - assert_eq!(r(MAX128 - 10, MAX128).to_den(10), Ok(r(10, 10))); - assert_eq!(r(MAX128 / 2, MAX128).to_den(10), Ok(r(5, 10))); - - // large to perbill. This is very well needed for phragmen. - assert_eq!( - r(MAX128 / 2, MAX128).to_den(1000_000_000), - Ok(r(500_000_000, 1000_000_000)) - ); - - // large to large - assert_eq!(r(MAX128 / 2, MAX128).to_den(MAX128/2), Ok(r(MAX128/4, MAX128/2))); - } - - #[test] - fn gdc_works() { - assert_eq!(gcd(10, 5), 5); - assert_eq!(gcd(7, 22), 1); - } - - #[test] - fn lcm_works() { - // simple stuff - assert_eq!(r(3, 10).lcm(&r(4, 15)).unwrap(), 30); - assert_eq!(r(5, 30).lcm(&r(1, 7)).unwrap(), 210); - assert_eq!(r(5, 30).lcm(&r(1, 10)).unwrap(), 30); - - // large numbers - assert_eq!( - r(1_000_000_000, MAX128).lcm(&r(7_000_000_000, MAX128-1)), - Err("result cannot fit in u128"), - ); - assert_eq!( - r(1_000_000_000, MAX64).lcm(&r(7_000_000_000, MAX64-1)), - Ok(340282366920938463408034375210639556610), - ); - assert!(340282366920938463408034375210639556610 < MAX128); - assert!(340282366920938463408034375210639556610 == MAX64 * (MAX64 - 1)); - } - - #[test] - fn add_works() { - // works - assert_eq!(r(3, 10).checked_add(r(1, 10)).unwrap(), r(2, 5)); - assert_eq!(r(3, 10).checked_add(r(3, 7)).unwrap(), r(51, 70)); - - // errors - assert_eq!( - r(1, MAX128).checked_add(r(1, MAX128-1)), - Err("failed to scale to denominator"), - ); - assert_eq!( - r(7, MAX128).checked_add(r(MAX128, MAX128)), - Err("overflow while adding numerators"), - ); - assert_eq!( - r(MAX128, MAX128).checked_add(r(MAX128, MAX128)), - Err("overflow while adding numerators"), - ); - } - - #[test] - fn sub_works() { - // works - assert_eq!(r(3, 10).checked_sub(r(1, 10)).unwrap(), r(1, 5)); - assert_eq!(r(6, 10).checked_sub(r(3, 7)).unwrap(), r(12, 70)); - - // errors - assert_eq!( - r(2, MAX128).checked_sub(r(1, MAX128-1)), - Err("failed to scale to denominator"), - ); - assert_eq!( - r(7, MAX128).checked_sub(r(MAX128, MAX128)), - Err("overflow while subtracting numerators"), - ); - assert_eq!( - r(1, 10).checked_sub(r(2,10)), - Err("overflow while subtracting numerators"), - ); - } - - #[test] - fn ordering_and_eq_works() { - assert!(r(1, 2) > r(1, 3)); - assert!(r(1, 2) > r(2, 6)); - - assert!(r(1, 2) < r(6, 6)); - assert!(r(2, 1) > r(2, 6)); - - assert!(r(5, 10) == r(1, 2)); - assert!(r(1, 2) == r(1, 2)); - - assert!(r(1, 1490000000000200000) > r(1, 1490000000000200001)); - } - - #[test] - fn multiply_by_rational_works() { - assert_eq!(multiply_by_rational(7, 2, 3).unwrap(), 7 * 2 / 3); - assert_eq!(multiply_by_rational(7, 20, 30).unwrap(), 7 * 2 / 3); - assert_eq!(multiply_by_rational(20, 7, 30).unwrap(), 7 * 2 / 3); - - assert_eq!( - // MAX128 % 3 == 0 - multiply_by_rational(MAX128, 2, 3).unwrap(), - MAX128 / 3 * 2, - ); - assert_eq!( - // MAX128 % 7 == 3 - multiply_by_rational(MAX128, 5, 7).unwrap(), - (MAX128 / 7 * 5) + (3 * 5 / 7), - ); - assert_eq!( - // MAX128 % 7 == 3 - multiply_by_rational(MAX128, 11 , 13).unwrap(), - (MAX128 / 13 * 11) + (8 * 11 / 13), - ); - assert_eq!( - // MAX128 % 1000 == 455 - multiply_by_rational(MAX128, 555, 1000).unwrap(), - (MAX128 / 1000 * 555) + (455 * 555 / 1000), - ); - - assert_eq!( - multiply_by_rational(2 * MAX64 - 1, MAX64, MAX64).unwrap(), - 2 * MAX64 - 1, - ); - assert_eq!( - multiply_by_rational(2 * MAX64 - 1, MAX64 - 1, MAX64).unwrap(), - 2 * MAX64 - 3, - ); - - assert_eq!( - multiply_by_rational(MAX64 + 100, MAX64_2, MAX64_2 / 2).unwrap(), - (MAX64 + 100) * 2, - ); - assert_eq!( - multiply_by_rational(MAX64 + 100, MAX64_2 / 100, MAX64_2 / 200).unwrap(), - (MAX64 + 100) * 2, - ); - - assert_eq!( - multiply_by_rational(2u128.pow(66) - 1, 2u128.pow(65) - 1, 2u128.pow(65)).unwrap(), - 73786976294838206461, - ); - assert_eq!( - multiply_by_rational(1_000_000_000, MAX128 / 8, MAX128 / 2).unwrap(), - 250000000, - ); - } - - #[test] - fn multiply_by_rational_a_b_are_interchangeable() { - assert_eq!( - multiply_by_rational(10, MAX128, MAX128 / 2), - Ok(20), - ); - assert_eq!( - multiply_by_rational(MAX128, 10, MAX128 / 2), - Ok(20), - ); - } - - fn do_fuzz_multiply_by_rational( - iters: usize, - bits: u32, - maximum_error: u128, - do_print: bool, - bounded: bool, - mul_fn: F, - ) where F: Fn(u128, u128, u128) -> u128 { - let mut rng = rand::thread_rng(); - let mut average_diff = 0.0; - let upper_bound = 2u128.pow(bits); - - for _ in 0..iters { - let a = rng.gen_range(0u128, upper_bound); - let c = rng.gen_range(0u128, upper_bound); - let b = rng.gen_range( - 0u128, - if bounded { c } else { upper_bound } - ); - - let a: u128 = a.into(); - let b: u128 = b.into(); - let c: u128 = c.into(); - - let truth = mul_div(a, b, c); - let result = mul_fn(a, b, c); - let diff = truth.max(result) - truth.min(result); - let loss_ratio = diff as f64 / truth as f64; - average_diff += loss_ratio; - - if do_print && diff > maximum_error { - println!("++ Computed with more loss than expected: {} * {} / {}", a, b, c); - println!("++ Expected {}", truth); - println!("+++++++ Got {}", result); - } - } - - // print report - println!( - "## Fuzzed with {} numbers. Average error was {}", - iters, - average_diff / (iters as f64), - ); - } - - // TODO $# move into a proper fuzzer #3745 - const FUZZ_COUNT: usize = 100_000; - - #[test] - fn fuzz_multiply_by_rational_32() { - // if Err just return the truth value. We don't care about such cases. The point of this - // fuzzing is to make sure: if `multiply_by_rational` returns `Ok`, it must be 100% accurate - // returning `Err` is fine. - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 32, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 32, 0, false, false, f); - } - - #[test] - fn fuzz_multiply_by_rational_64() { - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 64, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 64, 0, false, false, f); - } - - #[test] - fn fuzz_multiply_by_rational_96() { - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 96, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 96, 0, false, false, f); - } - - #[test] - fn fuzz_multiply_by_rational_128() { - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 127, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 127, 0, false, false, f); - } -} - -#[cfg(test)] -mod tests_fixed64 { - use super::*; - - fn max() -> Fixed64 { - Fixed64::from_parts(i64::max_value()) - } - - #[test] - fn fixed64_semantics() { - assert_eq!(Fixed64::from_rational(5, 2).0, 5 * 1_000_000_000 / 2); - assert_eq!(Fixed64::from_rational(5, 2), Fixed64::from_rational(10, 4)); - assert_eq!(Fixed64::from_rational(5, 0), Fixed64::from_rational(5, 1)); - - // biggest value that can be created. - assert_ne!(max(), Fixed64::from_natural(9_223_372_036)); - assert_eq!(max(), Fixed64::from_natural(9_223_372_037)); - } - - macro_rules! saturating_mul_acc_test { - ($num_type:tt) => { - assert_eq!( - Fixed64::from_rational(100, 1).saturated_multiply_accumulate(10 as $num_type), - 1010, - ); - assert_eq!( - Fixed64::from_rational(100, 2).saturated_multiply_accumulate(10 as $num_type), - 510, - ); - assert_eq!( - Fixed64::from_rational(100, 3).saturated_multiply_accumulate(0 as $num_type), - 0, - ); - assert_eq!( - Fixed64::from_rational(5, 1).saturated_multiply_accumulate($num_type::max_value()), - $num_type::max_value() - ); - assert_eq!( - max().saturated_multiply_accumulate($num_type::max_value()), - $num_type::max_value() - ); - } - } - - #[test] - fn fixed64_multiply_accumulate_works() { - saturating_mul_acc_test!(u32); - saturating_mul_acc_test!(u64); - saturating_mul_acc_test!(u128); - } -} diff --git a/core/sr-primitives/src/sr_arithmetic/biguint.rs b/core/sr-primitives/src/sr_arithmetic/biguint.rs new file mode 100644 index 0000000000000..f269207f32ac0 --- /dev/null +++ b/core/sr-primitives/src/sr_arithmetic/biguint.rs @@ -0,0 +1,930 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Infinite precision unsigned integer for substrate runtime. + +use crate::traits::Zero; +use rstd::{cmp::Ordering, ops, prelude::*, cell::RefCell, convert::TryFrom}; + +// A sensible value for this would be half of the dword size of the host machine. Since the +// runtime is compiled to 32bit webassembly, using 32 and 64 for single and double respectively +// should yield the most performance. TODO #3745 we could benchmark this and verify. +/// Representation of a single limb. +pub type Single = u32; +/// Representation of two limbs. +pub type Double = u64; +/// Difference in the number of bits of [`Single`] and [`Double`]. +const SHIFT: usize = 32; +/// short form of _Base_. Analogous to the value 10 in base-10 decimal numbers. +const B: Double = Single::max_value() as Double + 1; + +/// Splits a [`Double`] limb number into a tuple of two [`Single`] limb numbers. +pub fn split(a: Double) -> (Single, Single) { + let al = a as Single; + let ah = (a >> SHIFT) as Single; + (ah, al) +} + +/// Assumed as a given primitive. +/// +/// Multiplication of two singles, which at most yields 1 double. +pub fn mul_single(a: Single, b: Single) -> Double { + let a: Double = a.into(); + let b: Double = b.into(); + let r = a * b; + r +} + +/// Assumed as a given primitive. +/// +/// Addition of two singles, which at most takes a single limb of result and a carry, +/// returned as a tuple respectively. +pub fn add_single(a: Single, b: Single) -> (Single, Single) { + let a: Double = a.into(); + let b: Double = b.into(); + let q = a + b; + let (carry, r) = split(q); + (r, carry) +} + +/// Assumed as a given primitive. +/// +/// Division of double by a single limb. Always returns a double limb of quotient and a single +/// limb of remainder. +fn div_single(a: Double, b: Single) -> (Double, Single) { + let b: Double = b.into(); + let q = a / b; + let r = a % b; + // both conversions are trivially safe. + (q, r as Single) +} + +/// Simple wrapper around an infinitely large integer, represented as limbs of [`Single`]. +#[derive(Clone, Default)] +pub struct BigUint { + /// digits (limbs) of this number (sorted as msb -> lsd). + pub(crate) digits: Vec, +} + +impl BigUint { + /// Create a new instance with `size` limbs. This prevents any number with zero limbs to be + /// created. + /// + /// The behavior of the type is undefined with zero limbs. + pub fn with_capacity(size: usize) -> Self { + Self { digits: vec![0; size.max(1)] } + } + + /// Raw constructor from custom limbs. If `limbs` is empty, `Zero::zero()` implementation is + /// used. + pub fn from_limbs(limbs: &[Single]) -> Self { + if limbs.len() > 0 { + Self { digits: limbs.to_vec() } + } else { + Zero::zero() + } + } + + /// Number of limbs. + pub fn len(&self) -> usize { self.digits.len() } + + /// A naive getter for limb at `index`. Note that the order is lsb -> msb. + /// + /// #### Panics + /// + /// This panics if index is out of range. + pub fn get(&self, index: usize) -> Single { + self.digits[self.len() - 1 - index] + } + + /// A naive getter for limb at `index`. Note that the order is lsb -> msb. + pub fn checked_get(&self, index: usize) -> Option { + if let Some(i) = self.len().checked_sub(1) { + if let Some(j) = i.checked_sub(index) { + return self.digits.get(j).cloned(); + } + } + return None; + } + + /// A naive setter for limb at `index`. Note that the order is lsb -> msb. + /// + /// #### Panics + /// + /// This panics if index is out of range. + pub fn set(&mut self, index: usize, value: Single) { + let len = self.digits.len(); + self.digits[len - 1 - index] = value; + } + + /// returns the least significant limb of the number. + /// + /// #### Panics + /// + /// While the constructor of the type prevents this, this can panic if `self` has no digits. + pub fn lsb(&self) -> Single { + self.digits[self.len() - 1] + } + + /// returns the most significant limb of the number. + /// + /// #### Panics + /// + /// While the constructor of the type prevents this, this can panic if `self` has no digits. + pub fn msb(&self) -> Single { + self.digits[0] + } + + /// Strips zeros from the left side of `self`, if any. + pub fn lstrip(&mut self) { + // by definition, a big-int number should never have leading zero limbs. This function + // has the ability to cause this. There is nothing to do if the number already has 1 + // limb only. call it a day and return. + if self.len().is_zero() { return; } + let mut index = 0; + for elem in self.digits.iter() { + if *elem != 0 { break } else { index += 1 } + } + if index > 0 { + self.digits = self.digits[index..].to_vec() + } + } + + /// Zero-pad `self` from left to reach `size` limbs. Will not make any difference if `self` + /// is already bigger than `size` limbs. + pub fn lpad(&mut self, size: usize) { + let n = self.len(); + if n >= size { return; } + let pad = size - n; + let mut new_digits = (0..pad).map(|_| 0).collect::>(); + new_digits.extend(self.digits.iter()); + self.digits = new_digits; + } + + /// Adds `self` with `other`. self and other do not have to have any particular size. Given + /// that the `n = max{size(self), size(other)}`, it will produce a number with `n + 1` + /// limbs. + /// + /// This function does not strip the output and returns the original allocated `n + 1` + /// limbs. The caller may strip the output if desired. + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn add(self, other: &Self) -> Self { + let n = self.len().max(other.len()); + let mut k: Double = 0; + let mut w = Self::with_capacity(n + 1); + + for j in 0..n { + let u = Double::from(self.checked_get(j).unwrap_or(0)); + let v = Double::from(other.checked_get(j).unwrap_or(0)); + let s = u + v + k; + w.set(j, (s % B) as Single); + k = s / B; + } + // k is always 0 or 1. + w.set(n, k as Single); + w + } + + /// Subtracts `other` from `self`. self and other do not have to have any particular size. + /// Given that the `n = max{size(self), size(other)}`, it will produce a number of size `n`. + /// + /// If `other` is bigger than `self`, `Err(B - borrow)` is returned. + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn sub(self, other: &Self) -> Result { + let n = self.len().max(other.len()); + let mut k = 0; + let mut w = Self::with_capacity(n); + for j in 0..n { + let s = { + let u = Double::from(self.checked_get(j).unwrap_or(0)); + let v = Double::from(other.checked_get(j).unwrap_or(0)); + let mut needs_borrow = false; + let mut t = 0; + + if let Some(v) = u.checked_sub(v) { + if let Some(v2) = v.checked_sub(k) { + t = v2 % B; + k = 0; + } else { + needs_borrow = true; + } + } else { + needs_borrow = true; + } + if needs_borrow { + t = u + B - v - k; + k = 1; + } + t + }; + // PROOF: t either comes from `v2 % B`, or from `u + B - v - k`. The former is + // trivial. The latter will not overflow this branch will only happen if the sum of + // `u - v - k` part has been negative, hence `u + B - v - k < b`. + w.set(j, s as Single); + } + + if k.is_zero() { + Ok(w) + } else { + Err(w) + } + } + + /// Multiplies n-limb number `self` with m-limb number `other`. + /// + /// The resulting number will always have `n + m` limbs. + /// + /// This function does not strip the output and returns the original allocated `n + m` + /// limbs. The caller may strip the output if desired. + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn mul(self, other: &Self) -> Self { + let n = self.len(); + let m = other.len(); + let mut w = Self::with_capacity(m + n); + + for j in 0..n { + if self.get(j) == 0 { + // Note: `with_capacity` allocates with 0. Explicitly set j + m to zero if + // otherwise. + continue; + } + + let mut k = 0; + for i in 0..m { + // PROOF: (B−1) × (B−1) + (B−1) + (B−1) = B^2 −1 < B^2. addition is safe. + let t = + mul_single(self.get(j), other.get(i)) + + Double::from(w.get(i + j)) + + Double::from(k); + w.set(i + j, (t % B) as Single); + // PROOF: (B^2 - 1) / B < B. conversion is safe. + k = (t / B) as Single; + } + w.set(j + m, k); + } + w + } + + /// Divides `self` by a single limb `other`. This can be used in cases where the original + /// division cannot work due to the divisor (`other`) being just one limb. + /// + /// Invariant: `other` cannot be zero. + pub fn div_unit(self, mut other: Single) -> Self { + other = other.max(1); + let n = self.len(); + let mut out = Self::with_capacity(n); + let mut r: Single = 0; + // PROOF: (B-1) * B + (B-1) still fits in double + let with_r = |x: Double, r: Single| { r as Double * B + x }; + for d in (0..=n-1).rev() { + let (q, rr) = div_single(with_r(self.get(d).into(), r), other) ; + out.set(d, q as Single); + r = rr; + } + out + } + + /// Divides an `n + m` limb self by a `n` limb `other`. The result is a `m + 1` limb + /// quotient and a `n` limb remainder, if enabled by passing `true` in `rem` argument, both + /// in the form of an option's `Ok`. + /// + /// - requires `other` to be stripped and have no leading zeros. + /// - requires `self` to be stripped and have no leading zeros. + /// - requires `other` to have at least two limbs. + /// - requires `self` to have a greater length compared to `other`. + /// + /// All arguments are examined without being stripped for the above conditions. If any of + /// the above fails, `None` is returned.` + /// + /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. + pub fn div(self, other: &Self, rem: bool) -> Option<(Self, Self)> { + if other.len() <= 1 + || other.msb() == 0 + || self.msb() == 0 + || self.len() <= other.len() + { + return None + } + let n = other.len(); + let m = self.len() - n; + + let mut q = Self::with_capacity(m + 1); + let mut r = Self::with_capacity(n); + + debug_assert!(other.msb() != 0); + + // PROOF: 0 <= normalizer_bits < SHIFT 0 <= normalizer < B. all conversions are + // safe. + let normalizer_bits = other.msb().leading_zeros() as Single; + let normalizer = (2 as Single).pow(normalizer_bits as u32) as Single; + + // step D1. + let mut self_norm = self.mul(&Self::from(normalizer)); + let mut other_norm = other.clone().mul(&Self::from(normalizer)); + + // defensive only; the mul implementation should always create this. + self_norm.lpad(n + m + 1); + other_norm.lstrip(); + + // step D2. + for j in (0..=m).rev() { + // step D3.0 Find an estimate of q[j], named qhat. + let (qhat, rhat) = { + // PROOF: this always fits into `Double`. In the context of Single = u8, and + // Double = u16, think of 255 * 256 + 255 which is just u16::max_value(). + let dividend = + Double::from(self_norm.get(j + n)) + * B + + Double::from(self_norm.get(j + n - 1)); + let divisor = other_norm.get(n - 1); + div_single(dividend, divisor.into()) + }; + + // D3.1 test qhat + // replace qhat and rhat with RefCells. This helps share state with the closure + let qhat = RefCell::new(qhat); + let rhat = RefCell::new(rhat as Double); + + let test = || { + // decrease qhat if it is bigger than the base (B) + let qhat_local = *qhat.borrow(); + let rhat_local = *rhat.borrow(); + let predicate_1 = qhat_local >= B; + let predicate_2 = { + let lhs = qhat_local * other_norm.get(n - 2) as Double; + let rhs = B * rhat_local + self_norm.get(j + n - 2) as Double; + lhs > rhs + }; + if predicate_1 || predicate_2 { + *qhat.borrow_mut() -= 1; + *rhat.borrow_mut() += other_norm.get(n - 1) as Double; + true + } else { + false + } + }; + + test(); + while (*rhat.borrow() as Double) < B { + if !test() { break; } + } + + let qhat = qhat.into_inner(); + // we don't need rhat anymore. just let it go out of scope when it does. + + // step D4 + let lhs = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; + let rhs = other_norm.clone().mul(&Self::from(qhat)); + + let maybe_sub = lhs.sub(&rhs); + let mut negative = false; + let sub = match maybe_sub { + Ok(t) => t, + Err(t) => { negative = true; t } + }; + (j..=j+n).for_each(|d| { self_norm.set(d, sub.get(d - j)); }); + + // step D5 + // PROOF: the `test()` specifically decreases qhat until it is below `B`. conversion + // is safe. + q.set(j, qhat as Single); + + // step D6: add back if negative happened. + if negative { + q.set(j, q.get(j) - 1); + let u = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; + let r = other_norm.clone().add(&u); + (j..=j+n).rev().for_each(|d| { self_norm.set(d, r.get(d - j)); }) + } + } + + // if requested, calculate remainder. + if rem { + // undo the normalization. + if normalizer_bits > 0 { + let s = SHIFT as u32; + let nb = normalizer_bits; + for d in 0..n-1 { + let v = self_norm.get(d) >> nb + | self_norm.get(d + 1).overflowing_shl(s - nb).0; + r.set(d, v); + } + r.set(n - 1, self_norm.get(n - 1) >> normalizer_bits); + } else { + r = self_norm; + } + } + + Some((q, r)) + } +} + +#[cfg(feature = "std")] +impl rstd::fmt::Debug for BigUint { + fn fmt(&self, f: &mut rstd::fmt::Formatter<'_>) -> rstd::fmt::Result { + write!( + f, + "BigUint {{ {:?} ({:?})}}", + self.digits, + u128::try_from(self.clone()).unwrap_or_else(|_| 0), + ) + } +} + +impl PartialEq for BigUint { + fn eq(&self, other: &Self) -> bool { + // sadly, we have to reallocate here as strip mutably uses self. + let mut lhs = self.clone(); + let mut rhs = other.clone(); + lhs.lstrip(); + rhs.lstrip(); + lhs.digits.eq(&rhs.digits) + } +} + +impl Eq for BigUint {} + +impl Ord for BigUint { + fn cmp(&self, other: &Self) -> Ordering { + let lhs_first = self.digits.iter().position(|&e| e != 0); + let rhs_first = other.digits.iter().position(|&e| e != 0); + + match (lhs_first, rhs_first) { + // edge cases that should not happen. This basically means that one or both were + // zero. + (None, None) => Ordering::Equal, + (Some(_), None) => Ordering::Greater, + (None, Some(_)) => Ordering::Less, + (Some(lhs_idx), Some(rhs_idx)) => { + let lhs = &self.digits[lhs_idx..]; + let rhs = &other.digits[rhs_idx..]; + let len_cmp = lhs.len().cmp(&rhs.len()); + match len_cmp { + Ordering::Equal => lhs.cmp(rhs), + _ => len_cmp, + } + } + } + } +} + +impl PartialOrd for BigUint { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl ops::Add for BigUint { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + self.add(&rhs) + } +} + +impl ops::Sub for BigUint { + type Output = Self; + fn sub(self, rhs: Self) -> Self::Output { + self.sub(&rhs).unwrap_or_else(|e| e) + } +} + +impl ops::Mul for BigUint { + type Output = Self; + fn mul(self, rhs: Self) -> Self::Output { + self.mul(&rhs) + } +} + +impl Zero for BigUint { + fn zero() -> Self { + Self { digits: vec![Zero::zero()] } + } + + fn is_zero(&self) -> bool { + self.digits.iter().all(|d| d.is_zero()) + } +} + +macro_rules! impl_try_from_number_for { + ($([$type:ty, $len:expr]),+) => { + $( + impl TryFrom for $type { + type Error = &'static str; + fn try_from(mut value: BigUint) -> Result<$type, Self::Error> { + value.lstrip(); + let error_message = concat!("cannot fit a number into ", stringify!($type)); + if value.len() * SHIFT > $len { + Err(error_message) + } else { + let mut acc: $type = Zero::zero(); + for (i, d) in value.digits.iter().rev().cloned().enumerate() { + let d: $type = d.into(); + acc += d << (SHIFT * i); + } + Ok(acc) + } + } + } + )* + }; + } +// can only be implemented for sizes bigger than two limb. +impl_try_from_number_for!([u128, 128], [u64, 64]); + +macro_rules! impl_from_for_smaller_than_word { + ($($type:ty),+) => { + $(impl From<$type> for BigUint { + fn from(a: $type) -> Self { + Self { digits: vec! [a.into()] } + } + })* + } + } +impl_from_for_smaller_than_word!(u8, u16, Single); + +impl From for BigUint { + fn from(a: Double) -> Self { + let (ah, al) = split(a); + Self { digits: vec![ah, al] } + } +} + +#[cfg(test)] +pub mod tests { + use super::*; + use rand::Rng; + #[cfg(feature = "bench")] + use test::Bencher; + + // TODO move into a proper fuzzer #3745 + const FUZZ_COUNT: usize = 100_000; + + pub fn random_big_uint(size: usize) -> BigUint { + let mut rng = rand::thread_rng(); + let digits = (0..size).map(|_| rng.gen_range(0, Single::max_value())).collect(); + BigUint { digits } + } + + fn run_with_data_set( + count: usize, + limbs_ub_1: usize, + limbs_ub_2: usize, + exact: bool, + assertion: F, + ) where + F: Fn(BigUint, BigUint) -> () + { + let mut rng = rand::thread_rng(); + for _ in 0..count { + let digits_len_1 = if exact { limbs_ub_1 } else { rng.gen_range(1, limbs_ub_1) }; + let digits_len_2 = if exact { limbs_ub_2 } else { rng.gen_range(1, limbs_ub_2) }; + + let u = random_big_uint(digits_len_1); + let v = random_big_uint(digits_len_2); + assertion(u, v); + } + } + + fn with_limbs(n: usize) -> BigUint { + BigUint { digits: vec![1; n] } + } + + #[test] + fn split_works() { + let a = SHIFT / 2; + let b = SHIFT * 3 / 2; + let num: Double = 1 << a | 1 << b; + // example when `Single = u8` + // assert_eq!(num, 0b_0001_0000_0001_0000) + assert_eq!(split(num), (1 << a, 1 << a)); + } + + #[test] + fn strip_works() { + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![1, 0] }); + + let mut a = BigUint::from_limbs(&[0, 0, 1]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![1] }); + + let mut a = BigUint::from_limbs(&[0, 0]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![0] }); + + let mut a = BigUint::from_limbs(&[0, 0, 0]); + a.lstrip(); + assert_eq!(a, BigUint { digits: vec![0] }); + } + + #[test] + fn lpad_works() { + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lpad(2); + assert_eq!(a.digits, vec![0, 1, 0]); + + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lpad(3); + assert_eq!(a.digits, vec![0, 1, 0]); + + let mut a = BigUint::from_limbs(&[0, 1, 0]); + a.lpad(4); + assert_eq!(a.digits, vec![0, 0, 1, 0]); + } + + #[test] + fn equality_works() { + assert_eq!( + BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, + true, + ); + assert_eq!( + BigUint { digits: vec![3, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, + false, + ); + assert_eq!( + BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, + true, + ); + } + + #[test] + fn ordering_works() { + assert!(BigUint { digits: vec![0] } < BigUint { digits: vec![1] }); + assert!(BigUint { digits: vec![0] } == BigUint { digits: vec![0] }); + assert!(BigUint { digits: vec![] } == BigUint { digits: vec![0] }); + assert!(BigUint { digits: vec![] } == BigUint { digits: vec![] }); + assert!(BigUint { digits: vec![] } < BigUint { digits: vec![1] }); + + assert!(BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); + assert!(BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); + + assert!(BigUint { digits: vec![1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); + assert!(BigUint { digits: vec![0, 1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); + assert!(BigUint { digits: vec![1, 2, 1, 0] } > BigUint { digits: vec![1, 2, 3] }); + + assert!(BigUint { digits: vec![0, 1, 2, 1] } < BigUint { digits: vec![1, 2, 3] }); + } + + #[test] + fn basic_random_ord_eq_works() { + type S = u128; + run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { + let ue = S::try_from(u.clone()).unwrap(); + let ve = S::try_from(v.clone()).unwrap(); + assert_eq!(u.cmp(&v), ue.cmp(&ve)); + assert_eq!(u.eq(&v), ue.eq(&ve)); + }) + } + + #[test] + fn can_try_build_numbers_from_types() { + use rstd::convert::TryFrom; + assert_eq!(u64::try_from(with_limbs(1)).unwrap(), 1); + assert_eq!(u64::try_from(with_limbs(2)).unwrap(), u32::max_value() as u64 + 2); + assert_eq!( + u64::try_from(with_limbs(3)).unwrap_err(), + "cannot fit a number into u64", + ); + assert_eq!( + u128::try_from(with_limbs(3)).unwrap(), + u32::max_value() as u128 + u64::max_value() as u128 + 3 + ); + } + + #[test] + fn zero_works() { + assert_eq!(BigUint::zero(), BigUint { digits: vec![0] }); + assert_eq!(BigUint { digits: vec![0, 1, 0] }.is_zero(), false); + assert_eq!(BigUint { digits: vec![0, 0, 0] }.is_zero(), true); + + let a = BigUint::zero(); + let b = BigUint::zero(); + let c = a * b; + assert_eq!(c.digits, vec![0, 0]); + } + + #[test] + fn basic_random_add_works() { + type S = u128; + run_with_data_set(FUZZ_COUNT, 3, 3, false, |u, v| { + let expected = S::try_from(u.clone()).unwrap() + S::try_from(v.clone()).unwrap(); + let t = u.clone().add(&v); + assert_eq!( + S::try_from(t.clone()).unwrap(), expected, + "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + }) + } + + #[test] + fn sub_negative_works() { + assert_eq!( + BigUint::from(10 as Single).sub(&BigUint::from(5 as Single)).unwrap(), + BigUint::from(5 as Single) + ); + assert_eq!( + BigUint::from(10 as Single).sub(&BigUint::from(10 as Single)).unwrap(), + BigUint::from(0 as Single) + ); + assert_eq!( + BigUint::from(10 as Single).sub(&BigUint::from(13 as Single)).unwrap_err(), + BigUint::from((B - 3) as Single), + ); + } + + #[test] + fn basic_random_sub_works() { + type S = u128; + run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { + let expected = S::try_from(u.clone()).unwrap() + .checked_sub(S::try_from(v.clone()).unwrap()); + let t = u.clone().sub(&v); + if expected.is_none() { + assert!(t.is_err()) + } else { + let t = t.unwrap(); + let expected = expected.unwrap(); + assert_eq!( + S::try_from(t.clone()).unwrap(), expected, + "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + } + }) + } + + #[test] + fn basic_random_mul_works() { + type S = u128; + run_with_data_set(FUZZ_COUNT, 2, 2, false, |u, v| { + let expected = S::try_from(u.clone()).unwrap() * S::try_from(v.clone()).unwrap(); + let t = u.clone().mul(&v); + assert_eq!( + S::try_from(t.clone()).unwrap(), expected, + "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + }) + } + + #[test] + fn mul_always_appends_one_digit() { + let a = BigUint::from(10 as Single); + let b = BigUint::from(4 as Single); + assert_eq!(a.len(), 1); + assert_eq!(b.len(), 1); + + let n = a.mul(&b); + + assert_eq!(n.len(), 2); + assert_eq!(n.digits, vec![0, 40]); + } + + #[test] + fn div_conditions_work() { + let a = BigUint { digits: vec![2] }; + let b = BigUint { digits: vec![1, 2] }; + let c = BigUint { digits: vec![1, 1, 2] }; + let d = BigUint { digits: vec![0, 2] }; + let e = BigUint { digits: vec![0, 1, 1, 2] }; + + assert!(a.clone().div(&b, true).is_none()); + assert!(c.clone().div(&a, true).is_none()); + assert!(c.clone().div(&d, true).is_none()); + assert!(e.clone().div(&a, true).is_none()); + + assert!(c.clone().div(&b, true).is_some()); + } + + #[test] + fn div_unit_works() { + let a = BigUint { digits: vec![100] }; + let b = BigUint { digits: vec![1, 100] }; + + assert_eq!(a.clone().div_unit(1), a); + assert_eq!(a.clone().div_unit(0), a); + assert_eq!(a.clone().div_unit(2), BigUint::from(50 as Single)); + assert_eq!(a.clone().div_unit(7), BigUint::from(14 as Single)); + + assert_eq!(b.clone().div_unit(1), b); + assert_eq!(b.clone().div_unit(0), b); + assert_eq!(b.clone().div_unit(2), BigUint::from(((B + 100) / 2) as Single)); + assert_eq!(b.clone().div_unit(7), BigUint::from(((B + 100) / 7) as Single)); + + } + + #[test] + fn basic_random_div_works() { + type S = u128; + run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { + let ue = S::try_from(u.clone()).unwrap(); + let ve = S::try_from(v.clone()).unwrap(); + let (q, r) = (ue / ve, ue % ve); + if let Some((qq, rr)) = u.clone().div(&v, true) { + assert_eq!( + S::try_from(qq.clone()).unwrap(), q, + "{:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, + ); + assert_eq!( + S::try_from(rr.clone()).unwrap(), r, + "{:?} % {:?} ===> {:?} != {:?}", u, v, rr, r, + ); + } else if v.len() == 1 { + let qq = u.clone().div_unit(ve as Single); + assert_eq!( + S::try_from(qq.clone()).unwrap(), q, + "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, + ); + } else { + if v.msb() == 0 || v.msb() == 0 || u.len() <= v.len() {} // nada + else { panic!("div returned none for an unexpected reason"); } + } + }) + } + + #[cfg(feature = "bench")] + #[bench] + fn bench_addition_2_digit(bencher: &mut Bencher) { + let a = random_big_uint(2); + let b = random_big_uint(2); + bencher.iter(|| { + let _ = a.clone().add(&b); + }); + } + + #[cfg(feature = "bench")] + #[bench] + fn bench_addition_4_digit(bencher: &mut Bencher) { + let a = random_big_uint(4); + let b = random_big_uint(4); + bencher.iter(|| { + let _ = a.clone().add(&b); + }); + } + + #[cfg(feature = "bench")] + #[bench] + fn bench_subtraction_2_digit(bencher: &mut Bencher) { + let a = random_big_uint(2); + let b = random_big_uint(2); + bencher.iter(|| { + let _ = a.clone().sub(&b); + }); + } + + #[cfg(feature = "bench")] + #[bench] + fn bench_subtraction_4_digit(bencher: &mut Bencher) { + let a = random_big_uint(4); + let b = random_big_uint(4); + bencher.iter(|| { + let _ = a.clone().sub(&b); + }); + } + + #[cfg(feature = "bench")] + #[bench] + fn bench_multiplication_2_digit(bencher: &mut Bencher) { + let a = random_big_uint(2); + let b = random_big_uint(2); + bencher.iter(|| { + let _ = a.clone().mul(&b); + }); + } + + #[cfg(feature = "bench")] + #[bench] + fn bench_multiplication_4_digit(bencher: &mut Bencher) { + let a = random_big_uint(4); + let b = random_big_uint(4); + bencher.iter(|| { + let _ = a.clone().mul(&b); + }); + } + + #[cfg(feature = "bench")] + #[bench] + fn bench_division_4_digit(bencher: &mut Bencher) { + let a = random_big_uint(4); + let b = random_big_uint(2); + bencher.iter(|| { + let _ = a.clone().div(&b, true); + }); + } +} \ No newline at end of file diff --git a/core/sr-primitives/src/sr_arithmetic/fixed64.rs b/core/sr-primitives/src/sr_arithmetic/fixed64.rs new file mode 100644 index 0000000000000..62bebb002340a --- /dev/null +++ b/core/sr-primitives/src/sr_arithmetic/fixed64.rs @@ -0,0 +1,206 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use rstd::{ + ops, prelude::*, + convert::{TryFrom, TryInto}, +}; +use codec::{Encode, Decode}; +use crate::{ + Perbill, + traits::{ + SaturatedConversion, CheckedSub, CheckedAdd, Bounded, UniqueSaturatedInto, Saturating, + } +}; + +/// An unsigned fixed point number. Can hold any value in the range [-9_223_372_036, 9_223_372_036] +/// with fixed point accuracy of one billion. +#[cfg_attr(feature = "std", derive(Debug))] +#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Fixed64(i64); + +/// The accuracy of the `Fixed64` type. +const DIV: i64 = 1_000_000_000; + +impl Fixed64 { + /// creates self from a natural number. + /// + /// Note that this might be lossy. + pub fn from_natural(int: i64) -> Self { + Self(int.saturating_mul(DIV)) + } + + /// Return the accuracy of the type. Given that this function returns the value `X`, it means + /// that an instance composed of `X` parts (`Fixed64::from_parts(X)`) is equal to `1`. + pub fn accuracy() -> i64 { + DIV + } + + /// Raw constructor. Equal to `parts / 1_000_000_000`. + pub fn from_parts(parts: i64) -> Self { + Self(parts) + } + + /// creates self from a rational number. Equal to `n/d`. + /// + /// Note that this might be lossy. + pub fn from_rational(n: i64, d: u64) -> Self { + Self( + ((n as i128).saturating_mul(DIV as i128) / (d as i128).max(1)) + .try_into() + .unwrap_or(Bounded::max_value()) + ) + } + + /// Performs a saturated multiply and accumulate by unsigned number. + /// + /// Returns a saturated `int + (self * int)`. + pub fn saturated_multiply_accumulate(&self, int: N) -> N + where + N: TryFrom + From + UniqueSaturatedInto + Bounded + Clone + Saturating + + ops::Rem + ops::Div + ops::Mul + + ops::Add, + { + let div = DIV as u64; + let positive = self.0 > 0; + // safe to convert as absolute value. + let parts = self.0.checked_abs().map(|v| v as u64).unwrap_or(i64::max_value() as u64 + 1); + + + // will always fit. + let natural_parts = parts / div; + // might saturate. + let natural_parts: N = natural_parts.saturated_into(); + // fractional parts can always fit into u32. + let perbill_parts = (parts % div) as u32; + + let n = int.clone().saturating_mul(natural_parts); + let p = Perbill::from_parts(perbill_parts) * int.clone(); + + // everything that needs to be either added or subtracted from the original weight. + let excess = n.saturating_add(p); + + if positive { + int.saturating_add(excess) + } else { + int.saturating_sub(excess) + } + } +} + +impl Saturating for Fixed64 { + fn saturating_add(self, rhs: Self) -> Self { + Self(self.0.saturating_add(rhs.0)) + } + fn saturating_mul(self, rhs: Self) -> Self { + Self(self.0.saturating_mul(rhs.0) / DIV) + } + fn saturating_sub(self, rhs: Self) -> Self { + Self(self.0.saturating_sub(rhs.0)) + } +} + +/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait +/// for safe addition. +impl ops::Add for Fixed64 { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 + rhs.0) + } +} + +/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait +/// for safe subtraction. +impl ops::Sub for Fixed64 { + type Output = Self; + + fn sub(self, rhs: Self) -> Self::Output { + Self(self.0 - rhs.0) + } +} + +impl CheckedSub for Fixed64 { + fn checked_sub(&self, rhs: &Self) -> Option { + if let Some(v) = self.0.checked_sub(rhs.0) { + Some(Self(v)) + } else { + None + } + } +} + +impl CheckedAdd for Fixed64 { + fn checked_add(&self, rhs: &Self) -> Option { + if let Some(v) = self.0.checked_add(rhs.0) { + Some(Self(v)) + } else { + None + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn max() -> Fixed64 { + Fixed64::from_parts(i64::max_value()) + } + + #[test] + fn fixed64_semantics() { + assert_eq!(Fixed64::from_rational(5, 2).0, 5 * 1_000_000_000 / 2); + assert_eq!(Fixed64::from_rational(5, 2), Fixed64::from_rational(10, 4)); + assert_eq!(Fixed64::from_rational(5, 0), Fixed64::from_rational(5, 1)); + + // biggest value that can be created. + assert_ne!(max(), Fixed64::from_natural(9_223_372_036)); + assert_eq!(max(), Fixed64::from_natural(9_223_372_037)); + } + + macro_rules! saturating_mul_acc_test { + ($num_type:tt) => { + assert_eq!( + Fixed64::from_rational(100, 1).saturated_multiply_accumulate(10 as $num_type), + 1010, + ); + assert_eq!( + Fixed64::from_rational(100, 2).saturated_multiply_accumulate(10 as $num_type), + 510, + ); + assert_eq!( + Fixed64::from_rational(100, 3).saturated_multiply_accumulate(0 as $num_type), + 0, + ); + assert_eq!( + Fixed64::from_rational(5, 1).saturated_multiply_accumulate($num_type::max_value()), + $num_type::max_value() + ); + assert_eq!( + max().saturated_multiply_accumulate($num_type::max_value()), + $num_type::max_value() + ); + } + } + + #[test] + fn fixed64_multiply_accumulate_works() { + saturating_mul_acc_test!(u32); + saturating_mul_acc_test!(u64); + saturating_mul_acc_test!(u128); + } +} \ No newline at end of file diff --git a/core/sr-primitives/src/sr_arithmetic/helpers_128bit.rs b/core/sr-primitives/src/sr_arithmetic/helpers_128bit.rs new file mode 100644 index 0000000000000..b820dca141457 --- /dev/null +++ b/core/sr-primitives/src/sr_arithmetic/helpers_128bit.rs @@ -0,0 +1,103 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Some helper functions to work with 128bit numbers. Note that the functionality provided here is +//! only sensible to use with 128bit numbers because for smaller sizes, you can always rely on +//! assumptions of a bigger type (u128) being available, or simply create a per-thing and use the +//! multiplication implementation provided there. + +use crate::biguint; +use crate::traits::Zero; +use rstd::{cmp::{min, max}, convert::TryInto}; + +/// Helper gcd function used in Rational128 implementation. +pub fn gcd(a: u128, b: u128) -> u128 { + match ((a, b), (a & 1, b & 1)) { + ((x, y), _) if x == y => y, + ((0, x), _) | ((x, 0), _) => x, + ((x, y), (0, 1)) | ((y, x), (1, 0)) => gcd(x >> 1, y), + ((x, y), (0, 0)) => gcd(x >> 1, y >> 1) << 1, + ((x, y), (1, 1)) => { + let (x, y) = (min(x, y), max(x, y)); + gcd((y - x) >> 1, x) + }, + _ => unreachable!(), + } +} + +/// split a u128 into two u64 limbs +pub fn split(a: u128) -> (u64, u64) { + let al = a as u64; + let ah = (a >> 64) as u64; + (ah, al) +} + +/// Convert a u128 to a u32 based biguint. +pub fn to_big_uint(x: u128) -> biguint::BigUint { + let (xh, xl) = split(x); + let (xhh, xhl) = biguint::split(xh); + let (xlh, xll) = biguint::split(xl); + let mut n = biguint::BigUint::from_limbs(&[xhh, xhl, xlh, xll]); + n.lstrip(); + n +} + +/// Safely and accurately compute `a * b / c`. The approach is: +/// - Simply try `a * b / c`. +/// - Else, convert them both into big numbers and re-try. `Err` is returned if the result +/// cannot be safely casted back to u128. +/// +/// Invariant: c must be greater than or equal to 1. +pub fn multiply_by_rational(a: u128, b: u128, c: u128) -> Result { + if a.is_zero() || b.is_zero() { return Ok(Zero::zero()); } + let c = c.max(1); + + // a and b are interchangeable by definition in this function. It always helps to assume the + // bigger of which is being multiplied by a `0 < b/c < 1`. Hence, a should be the bigger and + // b the smaller one. + let t = a; + let a = a.max(b); + let b = t.min(b); + + if let Some(x) = a.checked_mul(b) { + // This is the safest way to go. Try it. + Ok(x / c) + } else { + let a_num = to_big_uint(a); + let b_num = to_big_uint(b); + let c_num = to_big_uint(c); + + let mut ab = a_num * b_num; + ab.lstrip(); + let mut q = if c_num.len() == 1 { + // PROOF: if `c_num.len() == 1` then `c` fits in one limb. + ab.div_unit(c as biguint::Single) + } else { + // PROOF: both `ab` and `c` cannot have leading zero limbs; if length of `c` is 1, + // the previous branch would handle. Also, if ab for sure has a bigger size than + // c, because `a.checked_mul(b)` has failed, hence ab must be at least one limb + // bigger than c. In this case, returning zero is defensive-only and div should + // always return Some. + let (mut q, r) = ab.div(&c_num, true).unwrap_or((Zero::zero(), Zero::zero())); + let r: u128 = r.try_into() + .expect("reminder of div by c is always less than c; qed"); + if r > (c / 2) { q = q.add(&to_big_uint(1)); } + q + }; + q.lstrip(); + q.try_into().map_err(|_| "result cannot fit in u128") + } +} \ No newline at end of file diff --git a/core/sr-primitives/src/sr_arithmetic/mod.rs b/core/sr-primitives/src/sr_arithmetic/mod.rs new file mode 100644 index 0000000000000..30e0fe96a54de --- /dev/null +++ b/core/sr-primitives/src/sr_arithmetic/mod.rs @@ -0,0 +1,27 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Minimal fixed point arithmetic primitives and types for runtime. + +pub mod biguint; +pub mod helpers_128bit; +mod parts_per_x; +mod fixed64; +mod rational128; + +pub use fixed64::Fixed64; +pub use parts_per_x::{Percent, Permill, Perbill, Perquintill}; +pub use rational128::Rational128; \ No newline at end of file diff --git a/core/sr-primitives/src/sr_arithmetic/parts_per_x.rs b/core/sr-primitives/src/sr_arithmetic/parts_per_x.rs new file mode 100644 index 0000000000000..0f22c22a93f3e --- /dev/null +++ b/core/sr-primitives/src/sr_arithmetic/parts_per_x.rs @@ -0,0 +1,520 @@ + +#[cfg(feature = "std")] +use crate::serde::{Serialize, Deserialize}; + +use rstd::{ops, prelude::*, convert::TryInto}; +use codec::{Encode, Decode}; +use crate::traits::{SaturatedConversion, UniqueSaturatedInto, Saturating}; + +macro_rules! implement_per_thing { + ($name:ident, $test_mod:ident, [$($test_units:tt),+], $max:tt, $type:ty, $upper_type:ty, $title:expr $(,)?) => { + /// A fixed point representation of a number between in the range [0, 1]. + /// + #[doc = $title] + #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Ord, PartialOrd))] + #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq)] + pub struct $name($type); + + impl $name { + /// Nothing. + pub fn zero() -> Self { Self(0) } + + /// `true` if this is nothing. + pub fn is_zero(&self) -> bool { self.0 == 0 } + + /// Everything. + pub fn one() -> Self { Self($max) } + + /// Consume self and deconstruct into a raw numeric type. + pub fn deconstruct(self) -> $type { self.0 } + + /// Return the scale at which this per-thing is working. + pub const fn accuracy() -> $type { $max } + + /// From an explicitly defined number of parts per maximum of the type. + /// + /// This can be called at compile time. + pub const fn from_parts(parts: $type) -> Self { + Self([parts, $max][(parts > $max) as usize]) + } + + /// Converts from a percent. Equal to `x / 100`. + /// + /// This can be created at compile time. + pub const fn from_percent(x: $type) -> Self { + Self([x, 100][(x > 100) as usize] * ($max / 100)) + } + + /// Return the product of multiplication of this value by itself. + pub fn square(self) -> Self { + // both can be safely casted and multiplied. + let p: $upper_type = self.0 as $upper_type * self.0 as $upper_type; + let q: $upper_type = $max as $upper_type * $max as $upper_type; + Self::from_rational_approximation(p, q) + } + + /// Converts a fraction into `Permill`. + #[cfg(feature = "std")] + pub fn from_fraction(x: f64) -> Self { Self((x * ($max as f64)) as $type) } + + /// Approximate the fraction `p/q` into a per-thing fraction. This will never overflow. + /// + /// The computation of this approximation is performed in the generic type `N`. Given + /// `M` as the data type that can hold the maximum value of this per-thing (e.g. u32 for + /// perbill), this can only work if `N == M` or `N: From + TryInto`. + pub fn from_rational_approximation(p: N, q: N) -> Self + where N: Clone + Ord + From<$type> + TryInto<$type> + ops::Div + { + // q cannot be zero. + let q = q.max((1 as $type).into()); + // p should not be bigger than q. + let p = p.min(q.clone()); + + let factor = (q.clone() / $max.into()).max((1 as $type).into()); + + // q cannot overflow: (q / (q/$max)) < 2 * $max. p < q hence p also cannot overflow. + // this implies that $type must be able to fit 2 * $max. + let q_reduce: $type = (q / factor.clone()) + .try_into() + .map_err(|_| "Failed to convert") + .expect( + "q / (q/$max) < (2 * $max). Macro prevents any type being created that \ + does not satisfy this; qed" + ); + let p_reduce: $type = (p / factor.clone()) + .try_into() + .map_err(|_| "Failed to convert") + .expect( + "q / (q/$max) < (2 * $max). Macro prevents any type being created that \ + does not satisfy this; qed" + ); + + // `p_reduced` and `q_reduced` are withing $type. Mul by another $max will always + // fit in $upper_type. This is guaranteed by the macro tests. + let part = + p_reduce as $upper_type + * ($max as $upper_type) + / q_reduce as $upper_type; + + $name(part as $type) + } + } + + impl Saturating for $name { + fn saturating_add(self, rhs: Self) -> Self { + // defensive-only: since `$max * 2 < $type::max_value()`, this can never overflow. + Self::from_parts(self.0.saturating_add(rhs.0)) + } + fn saturating_sub(self, rhs: Self) -> Self { + Self::from_parts(self.0.saturating_sub(rhs.0)) + } + fn saturating_mul(self, rhs: Self) -> Self { + let a = self.0 as $upper_type; + let b = rhs.0 as $upper_type; + let m = $max as $upper_type; + let parts = a * b / m; + // This will always fit into $type. + Self::from_parts(parts as $type) + } + } + + impl ops::Div for $name { + type Output = Self; + + fn div(self, rhs: Self) -> Self::Output { + let p = self.0; + let q = rhs.0; + Self::from_rational_approximation(p, q) + } + } + + /// Overflow-prune multiplication. + /// + /// tailored to be used with a balance type. + impl ops::Mul for $name + where + N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem + + ops::Div + ops::Mul + ops::Add, + { + type Output = N; + fn mul(self, b: N) -> Self::Output { + let maximum: N = $max.into(); + let upper_max: $upper_type = $max.into(); + let part: N = self.0.into(); + + let rem_multiplied_divided = { + let rem = b.clone().rem(maximum.clone()); + + // `rem_sized` is inferior to $max, thus it fits into $type. This is assured by + // a test. + let rem_sized = rem.saturated_into::<$type>(); + + // `self` and `rem_sized` are inferior to $max, thus the product is less than + // $max^2 and fits into $upper_type. This is assured by a test. + let rem_multiplied_upper = rem_sized as $upper_type * self.0 as $upper_type; + + // `rem_multiplied_upper` is less than $max^2 therefore divided by $max it fits + // in $type. remember that $type always fits $max. + let mut rem_multiplied_divided_sized = + (rem_multiplied_upper / upper_max) as $type; + // fix a tiny rounding error + if rem_multiplied_upper % upper_max > upper_max / 2 { + rem_multiplied_divided_sized += 1; + } + + // `rem_multiplied_divided_sized` is inferior to b, thus it can be converted + // back to N type + rem_multiplied_divided_sized.into() + }; + + (b / maximum) * part + rem_multiplied_divided + } + } + + impl codec::CompactAs for $name { + type As = $type; + fn encode_as(&self) -> &$type { + &self.0 + } + fn decode_from(x: $type) -> Self { + Self(x) + } + } + + impl From> for $name { + fn from(x: codec::Compact<$name>) -> Self { + x.0 + } + } + + #[cfg(test)] + mod $test_mod { + use codec::{Encode, Decode}; + use super::{$name, Saturating}; + use crate::{assert_eq_error_rate, traits::Zero}; + + + #[test] + fn macro_expanded_correctly() { + // needed for the `from_percent` to work. + assert!($max >= 100); + assert!($max % 100 == 0); + + // needed for `from_rational_approximation` + assert!(2 * $max < <$type>::max_value()); + assert!(($max as $upper_type) < <$upper_type>::max_value()); + + // for something like percent they can be the same. + assert!((<$type>::max_value() as $upper_type) <= <$upper_type>::max_value()); + assert!(($max as $upper_type).checked_mul($max.into()).is_some()); + } + + #[derive(Encode, Decode, PartialEq, Eq, Debug)] + struct WithCompact { + data: T, + } + + #[test] + fn has_compact() { + let data = WithCompact { data: $name(1) }; + let encoded = data.encode(); + assert_eq!(data, WithCompact::<$name>::decode(&mut &encoded[..]).unwrap()); + } + + #[test] + fn compact_encoding() { + let tests = [ + // assume all per_things have the size u8 at least. + (0 as $type, 1usize), + (1 as $type, 1usize), + (63, 1), + (64, 2), + (65, 2), + (<$type>::max_value(), <$type>::max_value().encode().len() + 1) + ]; + for &(n, l) in &tests { + let compact: crate::codec::Compact<$name> = $name(n).into(); + let encoded = compact.encode(); + assert_eq!(encoded.len(), l); + let decoded = >::decode(&mut & encoded[..]) + .unwrap(); + let per_thingy: $name = decoded.into(); + assert_eq!(per_thingy, $name(n)); + } + } + + #[test] + fn per_thing_api_works() { + // some really basic stuff + assert_eq!($name::zero(), $name::from_parts(Zero::zero())); + assert_eq!($name::one(), $name::from_parts($max)); + assert_eq!($name::accuracy(), $max); + assert_eq!($name::from_percent(0), $name::from_parts(Zero::zero())); + assert_eq!($name::from_percent(10), $name::from_parts($max / 10)); + assert_eq!($name::from_percent(100), $name::from_parts($max)); + } + + macro_rules! per_thing_mul_test { + ($num_type:tt) => { + // multiplication from all sort of from_percent + assert_eq!( + $name::from_percent(100) * $num_type::max_value(), + $num_type::max_value() + ); + assert_eq_error_rate!( + $name::from_percent(99) * $num_type::max_value(), + ((Into::::into($num_type::max_value()) * 99u32) / 100u32).as_u128() as $num_type, + 1, + ); + assert_eq!( + $name::from_percent(50) * $num_type::max_value(), + $num_type::max_value() / 2, + ); + assert_eq_error_rate!( + $name::from_percent(1) * $num_type::max_value(), + $num_type::max_value() / 100, + 1, + ); + assert_eq!($name::from_percent(0) * $num_type::max_value(), 0); + + // // multiplication with bounds + assert_eq!($name::one() * $num_type::max_value(), $num_type::max_value()); + assert_eq!($name::zero() * $num_type::max_value(), 0); + } + } + + #[test] + fn per_thing_mul_works() { + use primitive_types::U256; + + // accuracy test + assert_eq!($name::from_rational_approximation(1 as $type, 3) * 30 as $type, 10); + + $(per_thing_mul_test!($test_units);)* + } + + #[test] + fn per_thing_mul_rounds_to_nearest_number() { + assert_eq!($name::from_percent(33) * 10u64, 3); + assert_eq!($name::from_percent(34) * 10u64, 3); + assert_eq!($name::from_percent(35) * 10u64, 3); + assert_eq!($name::from_percent(36) * 10u64, 4); + assert_eq!($name::from_percent(36) * 10u64, 4); + } + + #[test] + fn per_thing_multiplication_with_large_number() { + use primitive_types::U256; + let max_minus_one = $max - 1; + assert_eq_error_rate!( + $name::from_parts(max_minus_one) * std::u128::MAX, + ((Into::::into(std::u128::MAX) * max_minus_one) / $max).as_u128(), + 1, + ); + } + + macro_rules! per_thing_from_rationale_approx_test { + ($num_type:tt) => { + // within accuracy boundary + assert_eq!( + $name::from_rational_approximation(1 as $num_type, 0), + $name::one(), + ); + assert_eq!( + $name::from_rational_approximation(1 as $num_type, 1), + $name::one(), + ); + assert_eq_error_rate!( + $name::from_rational_approximation(1 as $num_type, 3).0, + $name::from_parts($max / 3).0, + 2 + ); + assert_eq!( + $name::from_rational_approximation(1 as $num_type, 10), + $name::from_percent(10), + ); + assert_eq!( + $name::from_rational_approximation(1 as $num_type, 4), + $name::from_percent(25), + ); + assert_eq!( + $name::from_rational_approximation(1 as $num_type, 4), + $name::from_rational_approximation(2 as $num_type, 8), + ); + // no accurate anymore but won't overflow. + assert_eq!( + $name::from_rational_approximation( + $num_type::max_value() - 1, + $num_type::max_value() + ), + $name::one(), + ); + assert_eq_error_rate!( + $name::from_rational_approximation( + $num_type::max_value() / 3, + $num_type::max_value() + ).0, + $name::from_parts($max / 3).0, + 2 + ); + assert_eq!( + $name::from_rational_approximation(1, $num_type::max_value()), + $name::zero(), + ); + }; + } + + #[test] + fn per_thing_from_rationale_approx_works() { + // This is just to make sure something like Percent which _might_ get built from a + // u8 does not overflow in the context of this test. + let max_value = $max as $upper_type; + // almost at the edge + assert_eq!( + $name::from_rational_approximation($max - 1, $max + 1), + $name::from_parts($max - 2), + ); + assert_eq!( + $name::from_rational_approximation(1, $max-1), + $name::from_parts(1), + ); + assert_eq!( + $name::from_rational_approximation(1, $max), + $name::from_parts(1), + ); + assert_eq!( + $name::from_rational_approximation(2, 2 * $max - 1), + $name::from_parts(1), + ); + assert_eq!( + $name::from_rational_approximation(1, $max+1), + $name::zero(), + ); + assert_eq!( + $name::from_rational_approximation(3 * max_value / 2, 3 * max_value), + $name::from_percent(50), + ); + $(per_thing_from_rationale_approx_test!($test_units);)* + } + + #[test] + fn per_things_mul_operates_in_output_type() { + // assert_eq!($name::from_percent(50) * 100u32, 50u32); + assert_eq!($name::from_percent(50) * 100u64, 50u64); + assert_eq!($name::from_percent(50) * 100u128, 50u128); + } + + #[test] + fn per_thing_saturating_op_works() { + assert_eq!( + $name::from_percent(50).saturating_add($name::from_percent(40)), + $name::from_percent(90) + ); + assert_eq!( + $name::from_percent(50).saturating_add($name::from_percent(50)), + $name::from_percent(100) + ); + assert_eq!( + $name::from_percent(60).saturating_add($name::from_percent(50)), + $name::from_percent(100) + ); + + assert_eq!( + $name::from_percent(60).saturating_sub($name::from_percent(50)), + $name::from_percent(10) + ); + assert_eq!( + $name::from_percent(60).saturating_sub($name::from_percent(60)), + $name::from_percent(0) + ); + assert_eq!( + $name::from_percent(60).saturating_sub($name::from_percent(70)), + $name::from_percent(0) + ); + + assert_eq!( + $name::from_percent(50).saturating_mul($name::from_percent(50)), + $name::from_percent(25) + ); + assert_eq!( + $name::from_percent(20).saturating_mul($name::from_percent(20)), + $name::from_percent(4) + ); + assert_eq!( + $name::from_percent(10).saturating_mul($name::from_percent(10)), + $name::from_percent(1) + ); + } + + #[test] + fn per_thing_square_works() { + assert_eq!($name::from_percent(100).square(), $name::from_percent(100)); + assert_eq!($name::from_percent(50).square(), $name::from_percent(25)); + assert_eq!($name::from_percent(10).square(), $name::from_percent(1)); + assert_eq!( + $name::from_percent(2).square(), + $name::from_parts((4 * ($max as $upper_type) / 100 / 100) as $type) + ); + } + + #[test] + fn per_things_div_works() { + // normal + assert_eq!($name::from_percent(10) / $name::from_percent(20), + $name::from_percent(50) + ); + assert_eq!($name::from_percent(10) / $name::from_percent(10), + $name::from_percent(100) + ); + assert_eq!($name::from_percent(10) / $name::from_percent(0), + $name::from_percent(100) + ); + + // will not overflow + assert_eq!($name::from_percent(10) / $name::from_percent(5), + $name::from_percent(100) + ); + assert_eq!($name::from_percent(100) / $name::from_percent(50), + $name::from_percent(100) + ); + } + } + }; +} + +implement_per_thing!( + Percent, + test_per_cent, + [u32, u64, u128], + 100u8, + u8, + u16, + "_Percent_", +); +implement_per_thing!( + Permill, + test_permill, + [u32, u64, u128], + 1_000_000u32, + u32, + u64, + "_Parts per Million_", +); +implement_per_thing!( + Perbill, + test_perbill, + [u32, u64, u128], + 1_000_000_000u32, + u32, + u64, + "_Parts per Billion_", +); +implement_per_thing!( + Perquintill, + test_perquintill, + [u64, u128], + 1_000_000_000_000_000_000u64, + u64, + u128, + "_Parts per Quintillion_", +); diff --git a/core/sr-primitives/src/sr_arithmetic/rational128.rs b/core/sr-primitives/src/sr_arithmetic/rational128.rs new file mode 100644 index 0000000000000..fded808360b6f --- /dev/null +++ b/core/sr-primitives/src/sr_arithmetic/rational128.rs @@ -0,0 +1,462 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +use rstd::{cmp::Ordering, prelude::*}; +use crate::{helpers_128bit, traits::Zero}; + +/// A wrapper for any rational number with a 128 bit numerator and denominator. +#[derive(Clone, Copy, Default, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Rational128(u128, u128); + +impl Rational128 { + /// Nothing. + pub fn zero() -> Self { + Self(0, 1) + } + + /// If it is zero or not + pub fn is_zero(&self) -> bool { + self.0.is_zero() + } + + /// Build from a raw `n/d`. + pub fn from(n: u128, d: u128) -> Self { + Self(n, d.max(1)) + } + + /// Build from a raw `n/d`. This could lead to / 0 if not properly handled. + pub fn from_unchecked(n: u128, d: u128) -> Self { + Self(n, d) + } + + /// Return the numerator. + pub fn n(&self) -> u128 { + self.0 + } + + /// Return the denominator. + pub fn d(&self) -> u128 { + self.1 + } + + /// Convert `self` to a similar rational number where denominator is the given `den`. + // + /// This only returns if the result is accurate. `Err` is returned if the result cannot be + /// accurately calculated. + pub fn to_den(self, den: u128) -> Result { + if den == self.1 { + Ok(self) + } else { + helpers_128bit::multiply_by_rational(self.0, den, self.1).map(|n| Self(n, den)) + } + } + + /// Get the least common divisor of `self` and `other`. + /// + /// This only returns if the result is accurate. `Err` is returned if the result cannot be + /// accurately calculated. + pub fn lcm(&self, other: &Self) -> Result { + // this should be tested better: two large numbers that are almost the same. + if self.1 == other.1 { return Ok(self.1) } + let g = helpers_128bit::gcd(self.1, other.1); + helpers_128bit::multiply_by_rational(self.1 , other.1, g) + } + + /// A saturating add that assumes `self` and `other` have the same denominator. + pub fn lazy_saturating_add(self, other: Self) -> Self { + if other.is_zero() { + self + } else { + Self(self.0.saturating_add(other.0) ,self.1) + } + } + + /// A saturating subtraction that assumes `self` and `other` have the same denominator. + pub fn lazy_saturating_sub(self, other: Self) -> Self { + if other.is_zero() { + self + } else { + Self(self.0.saturating_sub(other.0) ,self.1) + } + } + + /// Addition. Simply tries to unify the denominators and add the numerators. + /// + /// Overflow might happen during any of the steps. Error is returned in such cases. + pub fn checked_add(self, other: Self) -> Result { + let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; + let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + let n = self_scaled.0.checked_add(other_scaled.0) + .ok_or("overflow while adding numerators")?; + Ok(Self(n, self_scaled.1)) + } + + /// Subtraction. Simply tries to unify the denominators and subtract the numerators. + /// + /// Overflow might happen during any of the steps. None is returned in such cases. + pub fn checked_sub(self, other: Self) -> Result { + let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; + let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; + + let n = self_scaled.0.checked_sub(other_scaled.0) + .ok_or("overflow while subtracting numerators")?; + Ok(Self(n, self_scaled.1)) + } +} + +impl PartialOrd for Rational128 { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Rational128 { + fn cmp(&self, other: &Self) -> Ordering { + // handle some edge cases. + if self.1 == other.1 { + self.0.cmp(&other.0) + } else if self.1.is_zero() { + Ordering::Greater + } else if other.1.is_zero() { + Ordering::Less + } else { + // Don't even compute gcd. + let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); + let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); + self_n.cmp(&other_n) + } + } +} + +impl PartialEq for Rational128 { + fn eq(&self, other: &Self) -> bool { + // handle some edge cases. + if self.1 == other.1 { + self.0.eq(&other.0) + } else { + let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); + let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); + self_n.eq(&other_n) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use super::helpers_128bit::*; + use rand::Rng; + + const MAX128: u128 = u128::max_value(); + const MAX64: u128 = u64::max_value() as u128; + const MAX64_2: u128 = 2 * u64::max_value() as u128; + + fn r(p: u128, q: u128) -> Rational128 { + Rational128(p, q) + } + + fn mul_div(a: u128, b: u128, c: u128) -> u128 { + use primitive_types::U256; + if a.is_zero() { return Zero::zero(); } + let c = c.max(1); + + // e for extended + let ae: U256 = a.into(); + let be: U256 = b.into(); + let ce: U256 = c.into(); + + let r = ae * be / ce; + if r > u128::max_value().into() { + a + } else { + r.as_u128() + } + } + + #[test] + fn truth_value_function_works() { + assert_eq!( + mul_div(2u128.pow(100), 8, 4), + 2u128.pow(101) + ); + assert_eq!( + mul_div(2u128.pow(100), 4, 8), + 2u128.pow(99) + ); + + // and it returns a if result cannot fit + assert_eq!(mul_div(MAX128 - 10, 2, 1), MAX128 - 10); + } + + #[test] + fn to_denom_works() { + // simple up and down + assert_eq!(r(1, 5).to_den(10), Ok(r(2, 10))); + assert_eq!(r(4, 10).to_den(5), Ok(r(2, 5))); + + // up and down with large numbers + assert_eq!(r(MAX128 - 10, MAX128).to_den(10), Ok(r(10, 10))); + assert_eq!(r(MAX128 / 2, MAX128).to_den(10), Ok(r(5, 10))); + + // large to perbill. This is very well needed for phragmen. + assert_eq!( + r(MAX128 / 2, MAX128).to_den(1000_000_000), + Ok(r(500_000_000, 1000_000_000)) + ); + + // large to large + assert_eq!(r(MAX128 / 2, MAX128).to_den(MAX128/2), Ok(r(MAX128/4, MAX128/2))); + } + + #[test] + fn gdc_works() { + assert_eq!(gcd(10, 5), 5); + assert_eq!(gcd(7, 22), 1); + } + + #[test] + fn lcm_works() { + // simple stuff + assert_eq!(r(3, 10).lcm(&r(4, 15)).unwrap(), 30); + assert_eq!(r(5, 30).lcm(&r(1, 7)).unwrap(), 210); + assert_eq!(r(5, 30).lcm(&r(1, 10)).unwrap(), 30); + + // large numbers + assert_eq!( + r(1_000_000_000, MAX128).lcm(&r(7_000_000_000, MAX128-1)), + Err("result cannot fit in u128"), + ); + assert_eq!( + r(1_000_000_000, MAX64).lcm(&r(7_000_000_000, MAX64-1)), + Ok(340282366920938463408034375210639556610), + ); + assert!(340282366920938463408034375210639556610 < MAX128); + assert!(340282366920938463408034375210639556610 == MAX64 * (MAX64 - 1)); + } + + #[test] + fn add_works() { + // works + assert_eq!(r(3, 10).checked_add(r(1, 10)).unwrap(), r(2, 5)); + assert_eq!(r(3, 10).checked_add(r(3, 7)).unwrap(), r(51, 70)); + + // errors + assert_eq!( + r(1, MAX128).checked_add(r(1, MAX128-1)), + Err("failed to scale to denominator"), + ); + assert_eq!( + r(7, MAX128).checked_add(r(MAX128, MAX128)), + Err("overflow while adding numerators"), + ); + assert_eq!( + r(MAX128, MAX128).checked_add(r(MAX128, MAX128)), + Err("overflow while adding numerators"), + ); + } + + #[test] + fn sub_works() { + // works + assert_eq!(r(3, 10).checked_sub(r(1, 10)).unwrap(), r(1, 5)); + assert_eq!(r(6, 10).checked_sub(r(3, 7)).unwrap(), r(12, 70)); + + // errors + assert_eq!( + r(2, MAX128).checked_sub(r(1, MAX128-1)), + Err("failed to scale to denominator"), + ); + assert_eq!( + r(7, MAX128).checked_sub(r(MAX128, MAX128)), + Err("overflow while subtracting numerators"), + ); + assert_eq!( + r(1, 10).checked_sub(r(2,10)), + Err("overflow while subtracting numerators"), + ); + } + + #[test] + fn ordering_and_eq_works() { + assert!(r(1, 2) > r(1, 3)); + assert!(r(1, 2) > r(2, 6)); + + assert!(r(1, 2) < r(6, 6)); + assert!(r(2, 1) > r(2, 6)); + + assert!(r(5, 10) == r(1, 2)); + assert!(r(1, 2) == r(1, 2)); + + assert!(r(1, 1490000000000200000) > r(1, 1490000000000200001)); + } + + #[test] + fn multiply_by_rational_works() { + assert_eq!(multiply_by_rational(7, 2, 3).unwrap(), 7 * 2 / 3); + assert_eq!(multiply_by_rational(7, 20, 30).unwrap(), 7 * 2 / 3); + assert_eq!(multiply_by_rational(20, 7, 30).unwrap(), 7 * 2 / 3); + + assert_eq!( + // MAX128 % 3 == 0 + multiply_by_rational(MAX128, 2, 3).unwrap(), + MAX128 / 3 * 2, + ); + assert_eq!( + // MAX128 % 7 == 3 + multiply_by_rational(MAX128, 5, 7).unwrap(), + (MAX128 / 7 * 5) + (3 * 5 / 7), + ); + assert_eq!( + // MAX128 % 7 == 3 + multiply_by_rational(MAX128, 11 , 13).unwrap(), + (MAX128 / 13 * 11) + (8 * 11 / 13), + ); + assert_eq!( + // MAX128 % 1000 == 455 + multiply_by_rational(MAX128, 555, 1000).unwrap(), + (MAX128 / 1000 * 555) + (455 * 555 / 1000), + ); + + assert_eq!( + multiply_by_rational(2 * MAX64 - 1, MAX64, MAX64).unwrap(), + 2 * MAX64 - 1, + ); + assert_eq!( + multiply_by_rational(2 * MAX64 - 1, MAX64 - 1, MAX64).unwrap(), + 2 * MAX64 - 3, + ); + + assert_eq!( + multiply_by_rational(MAX64 + 100, MAX64_2, MAX64_2 / 2).unwrap(), + (MAX64 + 100) * 2, + ); + assert_eq!( + multiply_by_rational(MAX64 + 100, MAX64_2 / 100, MAX64_2 / 200).unwrap(), + (MAX64 + 100) * 2, + ); + + assert_eq!( + multiply_by_rational(2u128.pow(66) - 1, 2u128.pow(65) - 1, 2u128.pow(65)).unwrap(), + 73786976294838206461, + ); + assert_eq!( + multiply_by_rational(1_000_000_000, MAX128 / 8, MAX128 / 2).unwrap(), + 250000000, + ); + } + + #[test] + fn multiply_by_rational_a_b_are_interchangeable() { + assert_eq!( + multiply_by_rational(10, MAX128, MAX128 / 2), + Ok(20), + ); + assert_eq!( + multiply_by_rational(MAX128, 10, MAX128 / 2), + Ok(20), + ); + } + + fn do_fuzz_multiply_by_rational( + iters: usize, + bits: u32, + maximum_error: u128, + do_print: bool, + bounded: bool, + mul_fn: F, + ) where F: Fn(u128, u128, u128) -> u128 { + let mut rng = rand::thread_rng(); + let mut average_diff = 0.0; + let upper_bound = 2u128.pow(bits); + + for _ in 0..iters { + let a = rng.gen_range(0u128, upper_bound); + let c = rng.gen_range(0u128, upper_bound); + let b = rng.gen_range( + 0u128, + if bounded { c } else { upper_bound } + ); + + let a: u128 = a.into(); + let b: u128 = b.into(); + let c: u128 = c.into(); + + let truth = mul_div(a, b, c); + let result = mul_fn(a, b, c); + let diff = truth.max(result) - truth.min(result); + let loss_ratio = diff as f64 / truth as f64; + average_diff += loss_ratio; + + if do_print && diff > maximum_error { + println!("++ Computed with more loss than expected: {} * {} / {}", a, b, c); + println!("++ Expected {}", truth); + println!("+++++++ Got {}", result); + } + } + + // print report + println!( + "## Fuzzed with {} numbers. Average error was {}", + iters, + average_diff / (iters as f64), + ); + } + + // TODO $# move into a proper fuzzer #3745 + const FUZZ_COUNT: usize = 100_000; + + #[test] + fn fuzz_multiply_by_rational_32() { + // if Err just return the truth value. We don't care about such cases. The point of this + // fuzzing is to make sure: if `multiply_by_rational` returns `Ok`, it must be 100% accurate + // returning `Err` is fine. + let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); + println!("\nInvariant: b < c"); + do_fuzz_multiply_by_rational(FUZZ_COUNT, 32, 0, false, true, f); + println!("every possibility"); + do_fuzz_multiply_by_rational(FUZZ_COUNT, 32, 0, false, false, f); + } + + #[test] + fn fuzz_multiply_by_rational_64() { + let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); + println!("\nInvariant: b < c"); + do_fuzz_multiply_by_rational(FUZZ_COUNT, 64, 0, false, true, f); + println!("every possibility"); + do_fuzz_multiply_by_rational(FUZZ_COUNT, 64, 0, false, false, f); + } + + #[test] + fn fuzz_multiply_by_rational_96() { + let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); + println!("\nInvariant: b < c"); + do_fuzz_multiply_by_rational(FUZZ_COUNT, 96, 0, false, true, f); + println!("every possibility"); + do_fuzz_multiply_by_rational(FUZZ_COUNT, 96, 0, false, false, f); + } + + #[test] + fn fuzz_multiply_by_rational_128() { + let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); + println!("\nInvariant: b < c"); + do_fuzz_multiply_by_rational(FUZZ_COUNT, 127, 0, false, true, f); + println!("every possibility"); + do_fuzz_multiply_by_rational(FUZZ_COUNT, 127, 0, false, false, f); + } +} \ No newline at end of file From 0bc870daafb854c6ab0b698d13fd81dec93ee2cb Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 17:10:07 +1300 Subject: [PATCH 02/63] Add some basic fuzzing --- core/sr-primitives/fuzzer/.gitignore | 3 + core/sr-primitives/fuzzer/Cargo.lock | 1506 +++++++++++++++++++++++++ core/sr-primitives/fuzzer/Cargo.toml | 14 + core/sr-primitives/fuzzer/src/main.rs | 86 ++ 4 files changed, 1609 insertions(+) create mode 100644 core/sr-primitives/fuzzer/.gitignore create mode 100644 core/sr-primitives/fuzzer/Cargo.lock create mode 100644 core/sr-primitives/fuzzer/Cargo.toml create mode 100644 core/sr-primitives/fuzzer/src/main.rs diff --git a/core/sr-primitives/fuzzer/.gitignore b/core/sr-primitives/fuzzer/.gitignore new file mode 100644 index 0000000000000..0fc8d54301e07 --- /dev/null +++ b/core/sr-primitives/fuzzer/.gitignore @@ -0,0 +1,3 @@ +hfuzz_target +hfuzz_workspace +target diff --git a/core/sr-primitives/fuzzer/Cargo.lock b/core/sr-primitives/fuzzer/Cargo.lock new file mode 100644 index 0000000000000..35818914771ba --- /dev/null +++ b/core/sr-primitives/fuzzer/Cargo.lock @@ -0,0 +1,1506 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "ahash" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "aho-corasick" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "arbitrary" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayref" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "autocfg" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "backtrace" +version = "0.3.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "base58" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitvec" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "blake2-rfc" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byte-slice-cast" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "c2-chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clear_on_drop" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "const-random" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "const-random-macro" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "constant_time_eq" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "curve25519-dalek" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ed25519-dalek" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "elastic-array" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "environmental" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "failure" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fixed-hash" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "fuzzer" +version = "0.1.0" +dependencies = [ + "arbitrary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-primitives 2.0.0", +] + +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "getrandom" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hash-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hashbrown" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "heapsize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "hmac" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hmac-drbg" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "honggfuzz" +version = "0.5.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arbitrary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-codec" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-serde" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "integer-sqrt" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "keccak" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.62" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libsecp256k1" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lock_api" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "malloc_size_of_derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memchr" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memory-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "memory_units" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "merlin" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "num-bigint" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-rational" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "once_cell" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "parity-scale-codec" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-util-mem" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-wasm" +version = "0.40.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "parking_lot" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste-impl" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pbkdf2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "primitive-types" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro2" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_jitter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_os" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "regex" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "regex-syntax" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-demangle" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc-hex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "schnorrkel" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "merlin 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "sr-io" +version = "2.0.0" +dependencies = [ + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 2.0.0", + "substrate-externalities 2.0.0", + "substrate-primitives 2.0.0", + "substrate-state-machine 2.0.0", + "substrate-trie 2.0.0", + "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sr-primitives" +version = "2.0.0" +dependencies = [ + "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-std 2.0.0", + "substrate-application-crypto 2.0.0", + "substrate-primitives 2.0.0", +] + +[[package]] +name = "sr-std" +version = "2.0.0" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "static_assertions" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "substrate-application-crypto" +version = "2.0.0" +dependencies = [ + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0", + "sr-std 2.0.0", + "substrate-primitives 2.0.0", +] + +[[package]] +name = "substrate-bip39" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-externalities" +version = "2.0.0" +dependencies = [ + "environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 2.0.0", + "substrate-primitives-storage 2.0.0", +] + +[[package]] +name = "substrate-panic-handler" +version = "2.0.0" +dependencies = [ + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-primitives" +version = "2.0.0" +dependencies = [ + "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ed25519-dalek 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-serde 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 2.0.0", + "substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-externalities 2.0.0", + "substrate-primitives-storage 2.0.0", + "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-primitives-storage" +version = "2.0.0" +dependencies = [ + "impl-serde 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 2.0.0", +] + +[[package]] +name = "substrate-state-machine" +version = "2.0.0" +dependencies = [ + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "substrate-externalities 2.0.0", + "substrate-panic-handler 2.0.0", + "substrate-primitives 2.0.0", + "substrate-trie 2.0.0", + "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "substrate-trie" +version = "2.0.0" +dependencies = [ + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 2.0.0", + "substrate-primitives 2.0.0", + "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "subtle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "subtle" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "syn" +version = "0.15.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synstructure" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thread_local" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tiny-bip39" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tiny-keccak" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "toml" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "trie-db" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "trie-root" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "twox-hash" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "typenum" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "uint" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasi" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasmi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmi-validation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmi-validation" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "zeroize" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "zeroize" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "b35dfc96a657c1842b4eb73180b65e37152d4b94d0eb5cb51708aee7826950b4" +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum arbitrary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4" +"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" +"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" +"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" +"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" +"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" +"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" +"checksum bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9633b74910e1870f50f5af189b08487195cdb83c0e27a71d6f64d5e09dd0538b" +"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" +"checksum byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7cbcbf18128ec71d8d4a0d054461ec59fff5b75b7d10a4c9b7c7cb1a379c3e77" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b641a8c9867e341f3295564203b1c250eb8ce6cb6126e007941f78c4d2ed7fe" +"checksum const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c750ec12b83377637110d5a57f5ae08e895b06c4b16e2bdbf1a94ef717428c59" +"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" +"checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +"checksum curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +"checksum ed25519-dalek 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d07e8b8a8386c3b89a7a4b329fdfa4cb545de2545e9e2ebbc3dd3929253e426" +"checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" +"checksum environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "34f8467a0284de039e6bd0e25c14519538462ba5beb548bb1f03e645097837a8" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +"checksum fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "516877b7b9a1cc2d0293cbce23cd6203f0edbfd4090e6ca4489fecb5aa73050e" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" +"checksum hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" +"checksum hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a" +"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" +"checksum hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" +"checksum honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)" = "24c27b4aa3049d6d10d8e33d52c9d03ca9aec18f8a449b246f8c4a5b0c10fb34" +"checksum impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fa0086251524c50fd53b32e7b05eb6d79e2f97221eaf0c53c0ca9c3096f21d3" +"checksum impl-serde 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bbb1ea6188aca47a0eaeeb330d8a82f16cd500f30b897062d23922568727333a" +"checksum impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6947b372790f8948f439bb6aaa6baabdf80be1a207a477ff072f83fb793e428f" +"checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" +"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63cc09b49bf0cc55885982347b174ad89855e97a12284d2c9dcc6da2e20c28f5" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35adee9ed962cf7d07d62cb58bc45029f3227f5b5b86246caa8632f06c187bc3" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" +"checksum memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ef49315991403ba5fa225a70399df5e115f57b274cb0b1b4bcd6e734fa5bd783" +"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" +"checksum merlin 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "de2d16d3b15fec5943d1144f861f61f279d165fdd60998ca262913b9bf1c8adb" +"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" +"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" +"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +"checksum parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "001fbbb956d8593f321c7a784f64d16b2c99b2657823976eea729006ad2c3668" +"checksum parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42af752f59119656fa3cb31e8852ed24e895b968c0bdb41847da7f0cea6d155f" +"checksum parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2005637ccf93dbb60c85081ccaaf3f945f573da48dcc79f27f9646caa3ec1dc" +"checksum parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1e39faaa292a687ea15120b1ac31899b13586446521df6c149e46f1584671e0f" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +"checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" +"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" +"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" +"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" +"checksum primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "83ef7b3b965c0eadcb6838f34f827e1dfb2939bdd5ebd43f9647e009b12b0371" +"checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" +"checksum proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "114cdf1f426eb7f550f01af5f53a33c0946156f6814aec939b3bd77e844f9a9d" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" +"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +"checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eacd8381b3c37840c9c9f40472af529e49975bdcbc24f83c31059fd6539023d3" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" +"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" +"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" +"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" +"checksum substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3be511be555a3633e71739a79e4ddff6a6aaa6579fa6114182a51d72c3eb93c5" +"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" +"checksum subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab3af2eb31c42e8f0ccf43548232556c42737e01a96db6e1777b0be108e79799" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" +"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c5676413eaeb1ea35300a0224416f57abc3bd251657e0fafc12c47ff98c060" +"checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" +"checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" +"checksum trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b62d27e8aa1c07414549ac872480ac82380bab39e730242ab08d82d7cc098a" +"checksum trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0b779f7c1c8fe9276365d9d5be5c4b5adeacf545117bb3f64c974305789c5c0b" +"checksum twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +"checksum uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8f0f47ed099f0db671ce82c66548c5de012e3c0cba3963514d1db15c7588701" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +"checksum wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f31d26deb2d9a37e6cfed420edce3ed604eab49735ba89035e13c98f9a528313" +"checksum wasmi-validation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc0356e3df56e639fc7f7d8a99741915531e27ed735d911ed83d7e1339c8188" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4090487fa66630f7b166fba2bbb525e247a5449f41c468cc1d98f8ae6ac03120" +"checksum zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "45af6a010d13e4cf5b54c94ba5a2b2eba5596b9e46bf5875612d332a1f2b3f86" diff --git a/core/sr-primitives/fuzzer/Cargo.toml b/core/sr-primitives/fuzzer/Cargo.toml new file mode 100644 index 0000000000000..b49d5480eebe6 --- /dev/null +++ b/core/sr-primitives/fuzzer/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "fuzzer" +version = "0.1.0" +authors = ["Ashley "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +honggfuzz = "0.5" +sr-primitives = { path = ".." } +arbitrary = "*" + +[workspace] \ No newline at end of file diff --git a/core/sr-primitives/fuzzer/src/main.rs b/core/sr-primitives/fuzzer/src/main.rs new file mode 100644 index 0000000000000..ea9c1a3c59085 --- /dev/null +++ b/core/sr-primitives/fuzzer/src/main.rs @@ -0,0 +1,86 @@ +use honggfuzz::fuzz; + +use sr_primitives::sr_arithmetic::biguint::{Single, BigUint}; +use std::convert::TryFrom; + +fn main() { + // Here you can parse `std::env::args and + // setup / initialize your project + + // You have full control over the loop but + // you're supposed to call `fuzz` ad vitam aeternam + loop { + // The fuzz macro gives an arbitrary object (see `arbitrary crate`) + // to a closure-like block of code. + // For performance reasons, it is recommended that you use the native type + // `&[u8]` when possible. + // Here, this slice will contain a "random" quantity of "random" data. + fuzz!(|data: (usize, usize, Vec, Vec)| { + let data = Data { + random_limb_len_1: data.0, + random_limb_len_2: data.1, + digits_1: data.2, + digits_2: data.3 + }; + + type S = u128; + run_with_data_set(4, 4, false, &data, |u, v| { + let ue = S::try_from(u.clone()).unwrap(); + let ve = S::try_from(v.clone()).unwrap(); + assert_eq!(u.cmp(&v), ue.cmp(&ve)); + assert_eq!(u.eq(&v), ue.eq(&ve)); + }); + }); + } +} + +struct Data { + random_limb_len_1: usize, + random_limb_len_2: usize, + digits_1: Vec, + digits_2: Vec +} + +fn run_with_data_set( + limbs_ub_1: usize, + limbs_ub_2: usize, + exact: bool, + data: &Data, + assertion: F, +) -> Option<()> + where + F: Fn(BigUint, BigUint) -> () +{ + let digits_len_1 = if exact { + limbs_ub_1 + } else { + check_between(data.random_limb_len_1, 1, limbs_ub_1)? + }; + + let digits_len_2 = if exact { + limbs_ub_2 + } else { + check_between(data.random_limb_len_2, 1, limbs_ub_2)? + }; + + let u = random_big_uint(digits_len_1, &data.digits_1)?; + let v = random_big_uint(digits_len_2, &data.digits_2)?; + assertion(u, v); + Some(()) +} + +fn check_between(value: usize, min: usize, max: usize) -> Option { + if value >= min && value < max { + Some(value) + } else { + None + } +} + +pub fn random_big_uint(size: usize, digits: &[Single]) -> Option { + if digits.len() != size { + return None; + } else { + Some(BigUint::from_limbs(digits)) + } +} \ No newline at end of file From b1a97933d3f194c4c80afcf4f401c55e287731cd Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 22:06:13 +1300 Subject: [PATCH 03/63] Add more tests --- core/sr-primitives/fuzzer/src/main.rs | 68 +++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/core/sr-primitives/fuzzer/src/main.rs b/core/sr-primitives/fuzzer/src/main.rs index ea9c1a3c59085..a698ce965d845 100644 --- a/core/sr-primitives/fuzzer/src/main.rs +++ b/core/sr-primitives/fuzzer/src/main.rs @@ -23,6 +23,7 @@ fn main() { digits_2: data.3 }; + // basic_random_ord_eq_works type S = u128; run_with_data_set(4, 4, false, &data, |u, v| { let ue = S::try_from(u.clone()).unwrap(); @@ -30,6 +31,73 @@ fn main() { assert_eq!(u.cmp(&v), ue.cmp(&ve)); assert_eq!(u.eq(&v), ue.eq(&ve)); }); + + // basic_random_add_works + //type S = u128; + run_with_data_set(3, 3, false, &data, |u, v| { + let expected = S::try_from(u.clone()).unwrap() + S::try_from(v.clone()).unwrap(); + let t = u.clone().add(&v); + assert_eq!( + S::try_from(t.clone()).unwrap(), expected, + "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + }); + + // basic_random_sub_works + //type S = u128; + run_with_data_set(4, 4, false, &data, |u, v| { + let expected = S::try_from(u.clone()).unwrap() + .checked_sub(S::try_from(v.clone()).unwrap()); + let t = u.clone().sub(&v); + if expected.is_none() { + assert!(t.is_err()) + } else { + let t = t.unwrap(); + let expected = expected.unwrap(); + assert_eq!( + S::try_from(t.clone()).unwrap(), expected, + "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + } + }); + + // basic_random_mul_works + //type S = u128; + run_with_data_set(2, 2, false, &data, |u, v| { + let expected = S::try_from(u.clone()).unwrap() * S::try_from(v.clone()).unwrap(); + let t = u.clone().mul(&v); + assert_eq!( + S::try_from(t.clone()).unwrap(), expected, + "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + }); + + // basic_random_div_works + //type S = u128; + run_with_data_set(4, 4, false, &data, |u, v| { + let ue = S::try_from(u.clone()).unwrap(); + let ve = S::try_from(v.clone()).unwrap(); + let (q, r) = (ue / ve, ue % ve); + if let Some((qq, rr)) = u.clone().div(&v, true) { + assert_eq!( + S::try_from(qq.clone()).unwrap(), q, + "{:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, + ); + assert_eq!( + S::try_from(rr.clone()).unwrap(), r, + "{:?} % {:?} ===> {:?} != {:?}", u, v, rr, r, + ); + } else if v.len() == 1 { + let qq = u.clone().div_unit(ve as Single); + assert_eq!( + S::try_from(qq.clone()).unwrap(), q, + "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, + ); + } else { + if v.msb() == 0 || v.msb() == 0 || u.len() <= v.len() {} // nada + else { panic!("div returned none for an unexpected reason"); } + } + }); }); } } From dc8cc41ae49e648e4ffcfdd68a2fb553a0925815 Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 22:32:04 +1300 Subject: [PATCH 04/63] Add printing to fuzzing --- core/sr-primitives/fuzzer/src/main.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/sr-primitives/fuzzer/src/main.rs b/core/sr-primitives/fuzzer/src/main.rs index a698ce965d845..b8a602d5bfb2f 100644 --- a/core/sr-primitives/fuzzer/src/main.rs +++ b/core/sr-primitives/fuzzer/src/main.rs @@ -77,6 +77,9 @@ fn main() { run_with_data_set(4, 4, false, &data, |u, v| { let ue = S::try_from(u.clone()).unwrap(); let ve = S::try_from(v.clone()).unwrap(); + if ve == 0 { + return; + } let (q, r) = (ue / ve, ue % ve); if let Some((qq, rr)) = u.clone().div(&v, true) { assert_eq!( @@ -133,6 +136,8 @@ fn run_with_data_set( let u = random_big_uint(digits_len_1, &data.digits_1)?; let v = random_big_uint(digits_len_2, &data.digits_2)?; + // this is easier than using lldb + println!("u: {:?}, v: {:?}", u, v); assertion(u, v); Some(()) } From ee2662508def64e6aca94b2e9257cb0a37bd9e3a Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 22:38:55 +1300 Subject: [PATCH 05/63] Clean things up --- core/sr-primitives/fuzzer/Cargo.toml | 8 +- .../fuzzer/src/{main.rs => biguint.rs} | 0 .../src/sr_arithmetic/biguint.rs | 115 ------------------ 3 files changed, 5 insertions(+), 118 deletions(-) rename core/sr-primitives/fuzzer/src/{main.rs => biguint.rs} (100%) diff --git a/core/sr-primitives/fuzzer/Cargo.toml b/core/sr-primitives/fuzzer/Cargo.toml index b49d5480eebe6..e6ff859f8b6db 100644 --- a/core/sr-primitives/fuzzer/Cargo.toml +++ b/core/sr-primitives/fuzzer/Cargo.toml @@ -4,11 +4,13 @@ version = "0.1.0" authors = ["Ashley "] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] honggfuzz = "0.5" sr-primitives = { path = ".." } arbitrary = "*" -[workspace] \ No newline at end of file +[workspace] + +[[bin]] +name = "biguint" +path = "src/biguint.rs" \ No newline at end of file diff --git a/core/sr-primitives/fuzzer/src/main.rs b/core/sr-primitives/fuzzer/src/biguint.rs similarity index 100% rename from core/sr-primitives/fuzzer/src/main.rs rename to core/sr-primitives/fuzzer/src/biguint.rs diff --git a/core/sr-primitives/src/sr_arithmetic/biguint.rs b/core/sr-primitives/src/sr_arithmetic/biguint.rs index f269207f32ac0..2a5140c4574ff 100644 --- a/core/sr-primitives/src/sr_arithmetic/biguint.rs +++ b/core/sr-primitives/src/sr_arithmetic/biguint.rs @@ -572,35 +572,6 @@ pub mod tests { #[cfg(feature = "bench")] use test::Bencher; - // TODO move into a proper fuzzer #3745 - const FUZZ_COUNT: usize = 100_000; - - pub fn random_big_uint(size: usize) -> BigUint { - let mut rng = rand::thread_rng(); - let digits = (0..size).map(|_| rng.gen_range(0, Single::max_value())).collect(); - BigUint { digits } - } - - fn run_with_data_set( - count: usize, - limbs_ub_1: usize, - limbs_ub_2: usize, - exact: bool, - assertion: F, - ) where - F: Fn(BigUint, BigUint) -> () - { - let mut rng = rand::thread_rng(); - for _ in 0..count { - let digits_len_1 = if exact { limbs_ub_1 } else { rng.gen_range(1, limbs_ub_1) }; - let digits_len_2 = if exact { limbs_ub_2 } else { rng.gen_range(1, limbs_ub_2) }; - - let u = random_big_uint(digits_len_1); - let v = random_big_uint(digits_len_2); - assertion(u, v); - } - } - fn with_limbs(n: usize) -> BigUint { BigUint { digits: vec![1; n] } } @@ -683,17 +654,6 @@ pub mod tests { assert!(BigUint { digits: vec![0, 1, 2, 1] } < BigUint { digits: vec![1, 2, 3] }); } - #[test] - fn basic_random_ord_eq_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { - let ue = S::try_from(u.clone()).unwrap(); - let ve = S::try_from(v.clone()).unwrap(); - assert_eq!(u.cmp(&v), ue.cmp(&ve)); - assert_eq!(u.eq(&v), ue.eq(&ve)); - }) - } - #[test] fn can_try_build_numbers_from_types() { use rstd::convert::TryFrom; @@ -721,19 +681,6 @@ pub mod tests { assert_eq!(c.digits, vec![0, 0]); } - #[test] - fn basic_random_add_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 3, 3, false, |u, v| { - let expected = S::try_from(u.clone()).unwrap() + S::try_from(v.clone()).unwrap(); - let t = u.clone().add(&v); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - }) - } - #[test] fn sub_negative_works() { assert_eq!( @@ -750,39 +697,6 @@ pub mod tests { ); } - #[test] - fn basic_random_sub_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { - let expected = S::try_from(u.clone()).unwrap() - .checked_sub(S::try_from(v.clone()).unwrap()); - let t = u.clone().sub(&v); - if expected.is_none() { - assert!(t.is_err()) - } else { - let t = t.unwrap(); - let expected = expected.unwrap(); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - } - }) - } - - #[test] - fn basic_random_mul_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 2, 2, false, |u, v| { - let expected = S::try_from(u.clone()).unwrap() * S::try_from(v.clone()).unwrap(); - let t = u.clone().mul(&v); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - }) - } - #[test] fn mul_always_appends_one_digit() { let a = BigUint::from(10 as Single); @@ -829,35 +743,6 @@ pub mod tests { } - #[test] - fn basic_random_div_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { - let ue = S::try_from(u.clone()).unwrap(); - let ve = S::try_from(v.clone()).unwrap(); - let (q, r) = (ue / ve, ue % ve); - if let Some((qq, rr)) = u.clone().div(&v, true) { - assert_eq!( - S::try_from(qq.clone()).unwrap(), q, - "{:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, - ); - assert_eq!( - S::try_from(rr.clone()).unwrap(), r, - "{:?} % {:?} ===> {:?} != {:?}", u, v, rr, r, - ); - } else if v.len() == 1 { - let qq = u.clone().div_unit(ve as Single); - assert_eq!( - S::try_from(qq.clone()).unwrap(), q, - "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, - ); - } else { - if v.msb() == 0 || v.msb() == 0 || u.len() <= v.len() {} // nada - else { panic!("div returned none for an unexpected reason"); } - } - }) - } - #[cfg(feature = "bench")] #[bench] fn bench_addition_2_digit(bencher: &mut Bencher) { From 38597b930ca154e94bb47bc881a286c8f2be091c Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 22:43:21 +1300 Subject: [PATCH 06/63] Remove arbitrary --- core/sr-primitives/fuzzer/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/core/sr-primitives/fuzzer/Cargo.toml b/core/sr-primitives/fuzzer/Cargo.toml index e6ff859f8b6db..7e43c67fc6b85 100644 --- a/core/sr-primitives/fuzzer/Cargo.toml +++ b/core/sr-primitives/fuzzer/Cargo.toml @@ -7,7 +7,6 @@ edition = "2018" [dependencies] honggfuzz = "0.5" sr-primitives = { path = ".." } -arbitrary = "*" [workspace] From c7c5888ebe3504daff233755b937127528272e25 Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 22:44:12 +1300 Subject: [PATCH 07/63] Remove comments --- core/sr-primitives/fuzzer/src/biguint.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/core/sr-primitives/fuzzer/src/biguint.rs b/core/sr-primitives/fuzzer/src/biguint.rs index b8a602d5bfb2f..0f4dd2ae80837 100644 --- a/core/sr-primitives/fuzzer/src/biguint.rs +++ b/core/sr-primitives/fuzzer/src/biguint.rs @@ -4,17 +4,7 @@ use sr_primitives::sr_arithmetic::biguint::{Single, BigUint}; use std::convert::TryFrom; fn main() { - // Here you can parse `std::env::args and - // setup / initialize your project - - // You have full control over the loop but - // you're supposed to call `fuzz` ad vitam aeternam loop { - // The fuzz macro gives an arbitrary object (see `arbitrary crate`) - // to a closure-like block of code. - // For performance reasons, it is recommended that you use the native type - // `&[u8]` when possible. - // Here, this slice will contain a "random" quantity of "random" data. fuzz!(|data: (usize, usize, Vec, Vec)| { let data = Data { random_limb_len_1: data.0, From cd2db5d9b961c7dbf4eab3adf74e530fcb439140 Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 22:52:05 +1300 Subject: [PATCH 08/63] More cleaning, fix small error that was causing a panic --- core/sr-primitives/fuzzer/src/biguint.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/core/sr-primitives/fuzzer/src/biguint.rs b/core/sr-primitives/fuzzer/src/biguint.rs index 0f4dd2ae80837..88b0cc94cc3f9 100644 --- a/core/sr-primitives/fuzzer/src/biguint.rs +++ b/core/sr-primitives/fuzzer/src/biguint.rs @@ -1,5 +1,4 @@ use honggfuzz::fuzz; - use sr_primitives::sr_arithmetic::biguint::{Single, BigUint}; use std::convert::TryFrom; @@ -34,7 +33,7 @@ fn main() { }); // basic_random_sub_works - //type S = u128; + // type S = u128; run_with_data_set(4, 4, false, &data, |u, v| { let expected = S::try_from(u.clone()).unwrap() .checked_sub(S::try_from(v.clone()).unwrap()); @@ -52,7 +51,7 @@ fn main() { }); // basic_random_mul_works - //type S = u128; + // type S = u128; run_with_data_set(2, 2, false, &data, |u, v| { let expected = S::try_from(u.clone()).unwrap() * S::try_from(v.clone()).unwrap(); let t = u.clone().mul(&v); @@ -63,7 +62,7 @@ fn main() { }); // basic_random_div_works - //type S = u128; + // type S = u128; run_with_data_set(4, 4, false, &data, |u, v| { let ue = S::try_from(u.clone()).unwrap(); let ve = S::try_from(v.clone()).unwrap(); @@ -87,7 +86,7 @@ fn main() { "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, ); } else { - if v.msb() == 0 || v.msb() == 0 || u.len() <= v.len() {} // nada + if v.msb() == 0 || u.msb() == 0 || u.len() <= v.len() {} // nada else { panic!("div returned none for an unexpected reason"); } } }); @@ -115,13 +114,13 @@ fn run_with_data_set( let digits_len_1 = if exact { limbs_ub_1 } else { - check_between(data.random_limb_len_1, 1, limbs_ub_1)? + value_between(data.random_limb_len_1, 1, limbs_ub_1)? }; let digits_len_2 = if exact { limbs_ub_2 } else { - check_between(data.random_limb_len_2, 1, limbs_ub_2)? + value_between(data.random_limb_len_2, 1, limbs_ub_2)? }; let u = random_big_uint(digits_len_1, &data.digits_1)?; @@ -132,7 +131,7 @@ fn run_with_data_set( Some(()) } -fn check_between(value: usize, min: usize, max: usize) -> Option { +fn value_between(value: usize, min: usize, max: usize) -> Option { if value >= min && value < max { Some(value) } else { @@ -140,9 +139,9 @@ fn check_between(value: usize, min: usize, max: usize) -> Option { } } -pub fn random_big_uint(size: usize, digits: &[Single]) -> Option { +fn random_big_uint(size: usize, digits: &[Single]) -> Option { if digits.len() != size { - return None; + None } else { Some(BigUint::from_limbs(digits)) } From 8a0ef6bfd9fb49d3c4822d2d24480135d3e0473b Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 23:34:06 +1300 Subject: [PATCH 09/63] Add rational128 --- core/sr-primitives/fuzzer/Cargo.lock | 2 +- core/sr-primitives/fuzzer/Cargo.toml | 7 +- core/sr-primitives/fuzzer/src/biguint.rs | 12 +- core/sr-primitives/fuzzer/src/rational128.rs | 119 +++++++++++++++++++ core/sr-primitives/fuzzer/src/util.rs | 9 ++ 5 files changed, 139 insertions(+), 10 deletions(-) create mode 100644 core/sr-primitives/fuzzer/src/rational128.rs create mode 100644 core/sr-primitives/fuzzer/src/util.rs diff --git a/core/sr-primitives/fuzzer/Cargo.lock b/core/sr-primitives/fuzzer/Cargo.lock index 35818914771ba..aea7646bda68f 100644 --- a/core/sr-primitives/fuzzer/Cargo.lock +++ b/core/sr-primitives/fuzzer/Cargo.lock @@ -279,8 +279,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "fuzzer" version = "0.1.0" dependencies = [ - "arbitrary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "sr-primitives 2.0.0", ] diff --git a/core/sr-primitives/fuzzer/Cargo.toml b/core/sr-primitives/fuzzer/Cargo.toml index 7e43c67fc6b85..9d585c7280487 100644 --- a/core/sr-primitives/fuzzer/Cargo.toml +++ b/core/sr-primitives/fuzzer/Cargo.toml @@ -7,9 +7,14 @@ edition = "2018" [dependencies] honggfuzz = "0.5" sr-primitives = { path = ".." } +primitive-types = "0.5.1" [workspace] [[bin]] name = "biguint" -path = "src/biguint.rs" \ No newline at end of file +path = "src/biguint.rs" + +[[bin]] +name = "rational128" +path = "src/rational128.rs" \ No newline at end of file diff --git a/core/sr-primitives/fuzzer/src/biguint.rs b/core/sr-primitives/fuzzer/src/biguint.rs index 88b0cc94cc3f9..2e63edddc2e20 100644 --- a/core/sr-primitives/fuzzer/src/biguint.rs +++ b/core/sr-primitives/fuzzer/src/biguint.rs @@ -2,6 +2,10 @@ use honggfuzz::fuzz; use sr_primitives::sr_arithmetic::biguint::{Single, BigUint}; use std::convert::TryFrom; +mod util; + +use util::value_between; + fn main() { loop { fuzz!(|data: (usize, usize, Vec, Vec)| { @@ -131,14 +135,6 @@ fn run_with_data_set( Some(()) } -fn value_between(value: usize, min: usize, max: usize) -> Option { - if value >= min && value < max { - Some(value) - } else { - None - } -} - fn random_big_uint(size: usize, digits: &[Single]) -> Option { if digits.len() != size { None diff --git a/core/sr-primitives/fuzzer/src/rational128.rs b/core/sr-primitives/fuzzer/src/rational128.rs new file mode 100644 index 0000000000000..407f3d0b4a97d --- /dev/null +++ b/core/sr-primitives/fuzzer/src/rational128.rs @@ -0,0 +1,119 @@ +use honggfuzz::fuzz; +use sr_primitives::{ + helpers_128bit::multiply_by_rational, + traits::Zero +}; + +mod util; + +use util::value_between; + +fn main() { + loop { + fuzz!(|data: ([u8; 16], [u8; 16], [u8; 16])| { + let data = Data { + a: u128::from_be_bytes(data.0), + b: u128::from_be_bytes(data.1), + c: u128::from_be_bytes(data.2) + }; + + fuzz_multiply_by_rational_32(&data); + }) + } +} + +struct Data { + a: u128, + b: u128, + c: u128 +} + +fn do_fuzz_multiply_by_rational( + bits: u32, + maximum_error: u128, + do_print: bool, + bounded: bool, + data: &Data, +) -> Option<()> { + let mut average_diff = 0.0; + let upper_bound = 2u128.pow(bits); + + let a = value_between(data.a, 0u128, upper_bound)?; + let c = value_between(data.c, 0u128, upper_bound)?; + let b = value_between( + data.b, + 0u128, + if bounded { c } else { upper_bound } + )?; + + let a: u128 = a.into(); + let b: u128 = b.into(); + let c: u128 = c.into(); + + let truth = mul_div(a, b, c); + let result = mul_fn(a, b, c); + let diff = truth.max(result) - truth.min(result); + let loss_ratio = diff as f64 / truth as f64; + average_diff += loss_ratio; + + if do_print && diff > maximum_error { + println!("++ Computed with more loss than expected: {} * {} / {}", a, b, c); + println!("++ Expected {}", truth); + println!("+++++++ Got {}", result); + } + + Some(()) +} + +fn mul_div(a: u128, b: u128, c: u128) -> u128 { + use primitive_types::U256; + if a.is_zero() { return Zero::zero(); } + let c = c.max(1); + + // e for extended + let ae: U256 = a.into(); + let be: U256 = b.into(); + let ce: U256 = c.into(); + + let r = ae * be / ce; + if r > u128::max_value().into() { + a + } else { + r.as_u128() + } +} + +// if Err just return the truth value. We don't care about such cases. The point of this +// fuzzing is to make sure: if `multiply_by_rational` returns `Ok`, it must be 100% accurate +// returning `Err` is fine. +fn mul_fn(a: u128, b: u128, c: u128) -> u128 { + multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)) +} + +fn fuzz_multiply_by_rational_32(data: &Data) { + println!("\nInvariant: b < c"); + do_fuzz_multiply_by_rational(32, 0, false, true, data); + println!("every possibility"); + do_fuzz_multiply_by_rational(32, 0, false, false, data); +} + +fn fuzz_multiply_by_rational_64(data: &Data) { + println!("\nInvariant: b < c"); + do_fuzz_multiply_by_rational( 64, 0, false, true, data); + println!("every possibility"); + do_fuzz_multiply_by_rational( 64, 0, false, false, data); +} + +fn fuzz_multiply_by_rational_96(data: &Data) { + println!("\nInvariant: b < c"); + do_fuzz_multiply_by_rational( 96, 0, false, true, data); + println!("every possibility"); + do_fuzz_multiply_by_rational( 96, 0, false, false, data); +} + +fn fuzz_multiply_by_rational_128(data: &Data) { + println!("\nInvariant: b < c"); + do_fuzz_multiply_by_rational( 127, 0, false, true, data); + println!("every possibility"); + do_fuzz_multiply_by_rational( 127, 0, false, false, data); +} \ No newline at end of file diff --git a/core/sr-primitives/fuzzer/src/util.rs b/core/sr-primitives/fuzzer/src/util.rs new file mode 100644 index 0000000000000..534417cb6d717 --- /dev/null +++ b/core/sr-primitives/fuzzer/src/util.rs @@ -0,0 +1,9 @@ +use std::cmp::PartialOrd; + +pub fn value_between(value: T, min: T, max: T) -> Option { + if value >= min && value < max { + Some(value) + } else { + None + } +} From 562cdff384a51f4702e8c6334e5a34d319f6cd72 Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 23:39:36 +1300 Subject: [PATCH 10/63] Remove old random tests --- core/sr-primitives/fuzzer/src/rational128.rs | 6 +- .../src/sr_arithmetic/rational128.rs | 88 ------------------- 2 files changed, 3 insertions(+), 91 deletions(-) diff --git a/core/sr-primitives/fuzzer/src/rational128.rs b/core/sr-primitives/fuzzer/src/rational128.rs index 407f3d0b4a97d..f2b63f92c8069 100644 --- a/core/sr-primitives/fuzzer/src/rational128.rs +++ b/core/sr-primitives/fuzzer/src/rational128.rs @@ -18,6 +18,9 @@ fn main() { }; fuzz_multiply_by_rational_32(&data); + fuzz_multiply_by_rational_64(&data); + fuzz_multiply_by_rational_96(&data); + fuzz_multiply_by_rational_128(&data); }) } } @@ -35,7 +38,6 @@ fn do_fuzz_multiply_by_rational( bounded: bool, data: &Data, ) -> Option<()> { - let mut average_diff = 0.0; let upper_bound = 2u128.pow(bits); let a = value_between(data.a, 0u128, upper_bound)?; @@ -53,8 +55,6 @@ fn do_fuzz_multiply_by_rational( let truth = mul_div(a, b, c); let result = mul_fn(a, b, c); let diff = truth.max(result) - truth.min(result); - let loss_ratio = diff as f64 / truth as f64; - average_diff += loss_ratio; if do_print && diff > maximum_error { println!("++ Computed with more loss than expected: {} * {} / {}", a, b, c); diff --git a/core/sr-primitives/src/sr_arithmetic/rational128.rs b/core/sr-primitives/src/sr_arithmetic/rational128.rs index fded808360b6f..a3a719e66b612 100644 --- a/core/sr-primitives/src/sr_arithmetic/rational128.rs +++ b/core/sr-primitives/src/sr_arithmetic/rational128.rs @@ -161,7 +161,6 @@ impl PartialEq for Rational128 { mod tests { use super::*; use super::helpers_128bit::*; - use rand::Rng; const MAX128: u128 = u128::max_value(); const MAX64: u128 = u64::max_value() as u128; @@ -372,91 +371,4 @@ mod tests { Ok(20), ); } - - fn do_fuzz_multiply_by_rational( - iters: usize, - bits: u32, - maximum_error: u128, - do_print: bool, - bounded: bool, - mul_fn: F, - ) where F: Fn(u128, u128, u128) -> u128 { - let mut rng = rand::thread_rng(); - let mut average_diff = 0.0; - let upper_bound = 2u128.pow(bits); - - for _ in 0..iters { - let a = rng.gen_range(0u128, upper_bound); - let c = rng.gen_range(0u128, upper_bound); - let b = rng.gen_range( - 0u128, - if bounded { c } else { upper_bound } - ); - - let a: u128 = a.into(); - let b: u128 = b.into(); - let c: u128 = c.into(); - - let truth = mul_div(a, b, c); - let result = mul_fn(a, b, c); - let diff = truth.max(result) - truth.min(result); - let loss_ratio = diff as f64 / truth as f64; - average_diff += loss_ratio; - - if do_print && diff > maximum_error { - println!("++ Computed with more loss than expected: {} * {} / {}", a, b, c); - println!("++ Expected {}", truth); - println!("+++++++ Got {}", result); - } - } - - // print report - println!( - "## Fuzzed with {} numbers. Average error was {}", - iters, - average_diff / (iters as f64), - ); - } - - // TODO $# move into a proper fuzzer #3745 - const FUZZ_COUNT: usize = 100_000; - - #[test] - fn fuzz_multiply_by_rational_32() { - // if Err just return the truth value. We don't care about such cases. The point of this - // fuzzing is to make sure: if `multiply_by_rational` returns `Ok`, it must be 100% accurate - // returning `Err` is fine. - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 32, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 32, 0, false, false, f); - } - - #[test] - fn fuzz_multiply_by_rational_64() { - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 64, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 64, 0, false, false, f); - } - - #[test] - fn fuzz_multiply_by_rational_96() { - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 96, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 96, 0, false, false, f); - } - - #[test] - fn fuzz_multiply_by_rational_128() { - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 127, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 127, 0, false, false, f); - } } \ No newline at end of file From c66f8822b03d0e08a1733942ab9c7a76ac26c47c Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 23:43:07 +1300 Subject: [PATCH 11/63] introduce panic --- core/sr-primitives/fuzzer/src/rational128.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/sr-primitives/fuzzer/src/rational128.rs b/core/sr-primitives/fuzzer/src/rational128.rs index f2b63f92c8069..0fef5124fd111 100644 --- a/core/sr-primitives/fuzzer/src/rational128.rs +++ b/core/sr-primitives/fuzzer/src/rational128.rs @@ -60,6 +60,7 @@ fn do_fuzz_multiply_by_rational( println!("++ Computed with more loss than expected: {} * {} / {}", a, b, c); println!("++ Expected {}", truth); println!("+++++++ Got {}", result); + panic!(); } Some(()) From 7adc99dde7a54ba9bd05dcb546570f22ddf06911 Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 23:47:38 +1300 Subject: [PATCH 12/63] fuzzing should panic properly --- core/sr-primitives/fuzzer/src/rational128.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/core/sr-primitives/fuzzer/src/rational128.rs b/core/sr-primitives/fuzzer/src/rational128.rs index 0fef5124fd111..482b90537973f 100644 --- a/core/sr-primitives/fuzzer/src/rational128.rs +++ b/core/sr-primitives/fuzzer/src/rational128.rs @@ -33,8 +33,6 @@ struct Data { fn do_fuzz_multiply_by_rational( bits: u32, - maximum_error: u128, - do_print: bool, bounded: bool, data: &Data, ) -> Option<()> { @@ -56,7 +54,7 @@ fn do_fuzz_multiply_by_rational( let result = mul_fn(a, b, c); let diff = truth.max(result) - truth.min(result); - if do_print && diff > maximum_error { + if diff > 0 { println!("++ Computed with more loss than expected: {} * {} / {}", a, b, c); println!("++ Expected {}", truth); println!("+++++++ Got {}", result); @@ -93,28 +91,28 @@ fn mul_fn(a: u128, b: u128, c: u128) -> u128 { fn fuzz_multiply_by_rational_32(data: &Data) { println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(32, 0, false, true, data); + do_fuzz_multiply_by_rational(32, true, data); println!("every possibility"); - do_fuzz_multiply_by_rational(32, 0, false, false, data); + do_fuzz_multiply_by_rational(32, false, data); } fn fuzz_multiply_by_rational_64(data: &Data) { println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational( 64, 0, false, true, data); + do_fuzz_multiply_by_rational( 64, true, data); println!("every possibility"); - do_fuzz_multiply_by_rational( 64, 0, false, false, data); + do_fuzz_multiply_by_rational( 64, false, data); } fn fuzz_multiply_by_rational_96(data: &Data) { println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational( 96, 0, false, true, data); + do_fuzz_multiply_by_rational( 96, true, data); println!("every possibility"); - do_fuzz_multiply_by_rational( 96, 0, false, false, data); + do_fuzz_multiply_by_rational( 96, false, data); } fn fuzz_multiply_by_rational_128(data: &Data) { println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational( 127, 0, false, true, data); + do_fuzz_multiply_by_rational( 127, true, data); println!("every possibility"); - do_fuzz_multiply_by_rational( 127, 0, false, false, data); + do_fuzz_multiply_by_rational( 127, false, data); } \ No newline at end of file From c28ae3f948ff5a71f6e0be428ef4de97215122ea Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 23:56:55 +1300 Subject: [PATCH 13/63] Bit of cleanup --- core/sr-primitives/fuzzer/src/rational128.rs | 50 +++++--------------- 1 file changed, 12 insertions(+), 38 deletions(-) diff --git a/core/sr-primitives/fuzzer/src/rational128.rs b/core/sr-primitives/fuzzer/src/rational128.rs index 482b90537973f..44f04ec3779de 100644 --- a/core/sr-primitives/fuzzer/src/rational128.rs +++ b/core/sr-primitives/fuzzer/src/rational128.rs @@ -17,10 +17,17 @@ fn main() { c: u128::from_be_bytes(data.2) }; - fuzz_multiply_by_rational_32(&data); - fuzz_multiply_by_rational_64(&data); - fuzz_multiply_by_rational_96(&data); - fuzz_multiply_by_rational_128(&data); + do_fuzz_multiply_by_rational(32, true, &data); + do_fuzz_multiply_by_rational(32, false, &data); + + do_fuzz_multiply_by_rational(64, true, &data); + do_fuzz_multiply_by_rational(64, false, &data); + + do_fuzz_multiply_by_rational(96, true, &data); + do_fuzz_multiply_by_rational(96, false, &data); + + do_fuzz_multiply_by_rational(128, true, &data); + do_fuzz_multiply_by_rational(128, false, &data); }) } } @@ -46,15 +53,10 @@ fn do_fuzz_multiply_by_rational( if bounded { c } else { upper_bound } )?; - let a: u128 = a.into(); - let b: u128 = b.into(); - let c: u128 = c.into(); - let truth = mul_div(a, b, c); let result = mul_fn(a, b, c); - let diff = truth.max(result) - truth.min(result); - if diff > 0 { + if truth != result { println!("++ Computed with more loss than expected: {} * {} / {}", a, b, c); println!("++ Expected {}", truth); println!("+++++++ Got {}", result); @@ -87,32 +89,4 @@ fn mul_div(a: u128, b: u128, c: u128) -> u128 { // returning `Err` is fine. fn mul_fn(a: u128, b: u128, c: u128) -> u128 { multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)) -} - -fn fuzz_multiply_by_rational_32(data: &Data) { - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(32, true, data); - println!("every possibility"); - do_fuzz_multiply_by_rational(32, false, data); -} - -fn fuzz_multiply_by_rational_64(data: &Data) { - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational( 64, true, data); - println!("every possibility"); - do_fuzz_multiply_by_rational( 64, false, data); -} - -fn fuzz_multiply_by_rational_96(data: &Data) { - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational( 96, true, data); - println!("every possibility"); - do_fuzz_multiply_by_rational( 96, false, data); -} - -fn fuzz_multiply_by_rational_128(data: &Data) { - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational( 127, true, data); - println!("every possibility"); - do_fuzz_multiply_by_rational( 127, false, data); } \ No newline at end of file From 77a8cbbab353c4e9fa1fd86d96854a6cc841994b Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 12:26:43 +0100 Subject: [PATCH 14/63] Add a test uncovered via fuzzing that fails! --- core/sr-primitives/src/sr_arithmetic/biguint.rs | 3 +-- core/sr-primitives/src/sr_arithmetic/rational128.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/core/sr-primitives/src/sr_arithmetic/biguint.rs b/core/sr-primitives/src/sr_arithmetic/biguint.rs index 2a5140c4574ff..d89abf0561211 100644 --- a/core/sr-primitives/src/sr_arithmetic/biguint.rs +++ b/core/sr-primitives/src/sr_arithmetic/biguint.rs @@ -568,7 +568,6 @@ impl From for BigUint { #[cfg(test)] pub mod tests { use super::*; - use rand::Rng; #[cfg(feature = "bench")] use test::Bencher; @@ -812,4 +811,4 @@ pub mod tests { let _ = a.clone().div(&b, true); }); } -} \ No newline at end of file +} diff --git a/core/sr-primitives/src/sr_arithmetic/rational128.rs b/core/sr-primitives/src/sr_arithmetic/rational128.rs index a3a719e66b612..c9af4269ee4b7 100644 --- a/core/sr-primitives/src/sr_arithmetic/rational128.rs +++ b/core/sr-primitives/src/sr_arithmetic/rational128.rs @@ -371,4 +371,12 @@ mod tests { Ok(20), ); } -} \ No newline at end of file + + #[test] + fn multiply_by_rational_fuzzed_equation() { + assert_eq!( + multiply_by_rational(154742576605164960401588224, 9223376310179529214, 549756068598), + Ok(2596149632101417846585204209223679) + ); + } +} From 1fe1a9f3caa19e4ea4c76b3de2ba357742541ab2 Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 12:52:17 +0100 Subject: [PATCH 15/63] Few small changes --- core/sr-primitives/fuzzer/src/rational128.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/core/sr-primitives/fuzzer/src/rational128.rs b/core/sr-primitives/fuzzer/src/rational128.rs index 44f04ec3779de..89489ede05c07 100644 --- a/core/sr-primitives/fuzzer/src/rational128.rs +++ b/core/sr-primitives/fuzzer/src/rational128.rs @@ -25,9 +25,9 @@ fn main() { do_fuzz_multiply_by_rational(96, true, &data); do_fuzz_multiply_by_rational(96, false, &data); - - do_fuzz_multiply_by_rational(128, true, &data); - do_fuzz_multiply_by_rational(128, false, &data); + + do_fuzz_multiply_by_rational(127, true, &data); + do_fuzz_multiply_by_rational(127, false, &data); }) } } @@ -54,7 +54,10 @@ fn do_fuzz_multiply_by_rational( )?; let truth = mul_div(a, b, c); - let result = mul_fn(a, b, c); + // if Err just use the truth value. We don't care about such cases. The point of this + // fuzzing is to make sure: if `multiply_by_rational` returns `Ok`, it must be 100% accurate + // returning `Err` is fine. + let result = multiply_by_rational(a, b, c).unwrap_or(truth); if truth != result { println!("++ Computed with more loss than expected: {} * {} / {}", a, b, c); @@ -83,10 +86,3 @@ fn mul_div(a: u128, b: u128, c: u128) -> u128 { r.as_u128() } } - -// if Err just return the truth value. We don't care about such cases. The point of this -// fuzzing is to make sure: if `multiply_by_rational` returns `Ok`, it must be 100% accurate -// returning `Err` is fine. -fn mul_fn(a: u128, b: u128, c: u128) -> u128 { - multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)) -} \ No newline at end of file From 40c0708197bb5a9d451e22282ff64b1657278303 Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 11 Oct 2019 21:23:44 +0100 Subject: [PATCH 16/63] Move sr-arithmetic to its own crate --- Cargo.lock | 19 +- Cargo.toml | 1 + core/sr-arithmetic/Cargo.toml | 31 +++ .../fuzzer/.gitignore | 0 .../fuzzer/Cargo.lock | 0 .../fuzzer/Cargo.toml | 0 .../fuzzer/src/biguint.rs | 0 .../fuzzer/src/rational128.rs | 0 .../fuzzer/src/util.rs | 0 .../src}/biguint.rs | 2 +- .../src}/fixed64.rs | 4 +- .../src}/helpers_128bit.rs | 4 +- .../mod.rs => sr-arithmetic/src/lib.rs} | 3 +- .../src}/parts_per_x.rs | 39 ++- .../src}/rational128.rs | 3 +- core/sr-arithmetic/src/traits.rs | 262 ++++++++++++++++++ core/sr-primitives/Cargo.toml | 5 +- core/sr-primitives/src/curve.rs | 2 +- core/sr-primitives/src/generic/header.rs | 3 +- core/sr-primitives/src/lib.rs | 38 +-- core/sr-primitives/src/traits.rs | 197 +------------ core/sr-primitives/src/weights.rs | 3 +- 22 files changed, 367 insertions(+), 249 deletions(-) create mode 100644 core/sr-arithmetic/Cargo.toml rename core/{sr-primitives => sr-arithmetic}/fuzzer/.gitignore (100%) rename core/{sr-primitives => sr-arithmetic}/fuzzer/Cargo.lock (100%) rename core/{sr-primitives => sr-arithmetic}/fuzzer/Cargo.toml (100%) rename core/{sr-primitives => sr-arithmetic}/fuzzer/src/biguint.rs (100%) rename core/{sr-primitives => sr-arithmetic}/fuzzer/src/rational128.rs (100%) rename core/{sr-primitives => sr-arithmetic}/fuzzer/src/util.rs (100%) rename core/{sr-primitives/src/sr_arithmetic => sr-arithmetic/src}/biguint.rs (99%) rename core/{sr-primitives/src/sr_arithmetic => sr-arithmetic/src}/fixed64.rs (99%) rename core/{sr-primitives/src/sr_arithmetic => sr-arithmetic/src}/helpers_128bit.rs (99%) rename core/{sr-primitives/src/sr_arithmetic/mod.rs => sr-arithmetic/src/lib.rs} (95%) rename core/{sr-primitives/src/sr_arithmetic => sr-arithmetic/src}/parts_per_x.rs (94%) rename core/{sr-primitives/src/sr_arithmetic => sr-arithmetic/src}/rational128.rs (99%) create mode 100644 core/sr-arithmetic/src/traits.rs diff --git a/Cargo.lock b/Cargo.lock index 6e7dea9d1d8bc..e816e4f0aed83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3808,6 +3808,22 @@ dependencies = [ "trybuild 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sr-arithmetic" +version = "2.0.0" +dependencies = [ + "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-std 2.0.0", + "substrate-offchain 2.0.0", +] + [[package]] name = "sr-io" version = "2.0.0" @@ -3829,15 +3845,14 @@ name = "sr-primitives" version = "2.0.0" dependencies = [ "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-arithmetic 2.0.0", "sr-io 2.0.0", "sr-std 2.0.0", "substrate-application-crypto 2.0.0", diff --git a/Cargo.toml b/Cargo.toml index 7e34a0bd6ccd0..4080813ad4529 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ members = [ "core/service/test", "core/session", "core/sr-api-macros", + "core/sr-arithmetic", "core/sr-io", "core/sr-primitives", "core/sr-staking-primitives", diff --git a/core/sr-arithmetic/Cargo.toml b/core/sr-arithmetic/Cargo.toml new file mode 100644 index 0000000000000..0ee0619851cc6 --- /dev/null +++ b/core/sr-arithmetic/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "sr-arithmetic" +version = "2.0.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +num-traits = { version = "0.2.8", default-features = false } +serde = { version = "1.0.101", optional = true, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } +rstd = { package = "sr-std", path = "../sr-std", default-features = false } +paste = "0.1.6" +rand = { version = "0.7.2", optional = true } +integer-sqrt = "0.1.2" + +[dev-dependencies] +serde_json = "1.0.41" +primitive-types = "0.5.1" +rand = "0.7.2" +substrate-offchain = { path = "../offchain" } + +[features] +bench = [] +default = ["std"] +std = [ + "serde", + "num-traits/std", + "rstd/std", + "codec/std", + "rand", +] diff --git a/core/sr-primitives/fuzzer/.gitignore b/core/sr-arithmetic/fuzzer/.gitignore similarity index 100% rename from core/sr-primitives/fuzzer/.gitignore rename to core/sr-arithmetic/fuzzer/.gitignore diff --git a/core/sr-primitives/fuzzer/Cargo.lock b/core/sr-arithmetic/fuzzer/Cargo.lock similarity index 100% rename from core/sr-primitives/fuzzer/Cargo.lock rename to core/sr-arithmetic/fuzzer/Cargo.lock diff --git a/core/sr-primitives/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml similarity index 100% rename from core/sr-primitives/fuzzer/Cargo.toml rename to core/sr-arithmetic/fuzzer/Cargo.toml diff --git a/core/sr-primitives/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs similarity index 100% rename from core/sr-primitives/fuzzer/src/biguint.rs rename to core/sr-arithmetic/fuzzer/src/biguint.rs diff --git a/core/sr-primitives/fuzzer/src/rational128.rs b/core/sr-arithmetic/fuzzer/src/rational128.rs similarity index 100% rename from core/sr-primitives/fuzzer/src/rational128.rs rename to core/sr-arithmetic/fuzzer/src/rational128.rs diff --git a/core/sr-primitives/fuzzer/src/util.rs b/core/sr-arithmetic/fuzzer/src/util.rs similarity index 100% rename from core/sr-primitives/fuzzer/src/util.rs rename to core/sr-arithmetic/fuzzer/src/util.rs diff --git a/core/sr-primitives/src/sr_arithmetic/biguint.rs b/core/sr-arithmetic/src/biguint.rs similarity index 99% rename from core/sr-primitives/src/sr_arithmetic/biguint.rs rename to core/sr-arithmetic/src/biguint.rs index d89abf0561211..32daf53e0c16c 100644 --- a/core/sr-primitives/src/sr_arithmetic/biguint.rs +++ b/core/sr-arithmetic/src/biguint.rs @@ -16,7 +16,7 @@ //! Infinite precision unsigned integer for substrate runtime. -use crate::traits::Zero; +use num_traits::Zero; use rstd::{cmp::Ordering, ops, prelude::*, cell::RefCell, convert::TryFrom}; // A sensible value for this would be half of the dword size of the host machine. Since the diff --git a/core/sr-primitives/src/sr_arithmetic/fixed64.rs b/core/sr-arithmetic/src/fixed64.rs similarity index 99% rename from core/sr-primitives/src/sr_arithmetic/fixed64.rs rename to core/sr-arithmetic/src/fixed64.rs index 62bebb002340a..5e2fccc1f3f5e 100644 --- a/core/sr-primitives/src/sr_arithmetic/fixed64.rs +++ b/core/sr-arithmetic/src/fixed64.rs @@ -22,7 +22,7 @@ use codec::{Encode, Decode}; use crate::{ Perbill, traits::{ - SaturatedConversion, CheckedSub, CheckedAdd, Bounded, UniqueSaturatedInto, Saturating, + SaturatedConversion, CheckedSub, CheckedAdd, Bounded, UniqueSaturatedInto, Saturating } }; @@ -203,4 +203,4 @@ mod tests { saturating_mul_acc_test!(u64); saturating_mul_acc_test!(u128); } -} \ No newline at end of file +} diff --git a/core/sr-primitives/src/sr_arithmetic/helpers_128bit.rs b/core/sr-arithmetic/src/helpers_128bit.rs similarity index 99% rename from core/sr-primitives/src/sr_arithmetic/helpers_128bit.rs rename to core/sr-arithmetic/src/helpers_128bit.rs index b820dca141457..e8e1f448ab87b 100644 --- a/core/sr-primitives/src/sr_arithmetic/helpers_128bit.rs +++ b/core/sr-arithmetic/src/helpers_128bit.rs @@ -20,7 +20,7 @@ //! multiplication implementation provided there. use crate::biguint; -use crate::traits::Zero; +use num_traits::Zero; use rstd::{cmp::{min, max}, convert::TryInto}; /// Helper gcd function used in Rational128 implementation. @@ -100,4 +100,4 @@ pub fn multiply_by_rational(a: u128, b: u128, c: u128) -> Result { + assert!( + ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), + "{:?} != {:?} (with error rate {:?})", + $x, + $y, + $error, + ); + }; +} + macro_rules! implement_per_thing { ($name:ident, $test_mod:ident, [$($test_units:tt),+], $max:tt, $type:ty, $upper_type:ty, $title:expr $(,)?) => { /// A fixed point representation of a number between in the range [0, 1]. @@ -210,7 +241,7 @@ macro_rules! implement_per_thing { } #[derive(Encode, Decode, PartialEq, Eq, Debug)] - struct WithCompact { + struct WithCompact { data: T, } @@ -233,10 +264,10 @@ macro_rules! implement_per_thing { (<$type>::max_value(), <$type>::max_value().encode().len() + 1) ]; for &(n, l) in &tests { - let compact: crate::codec::Compact<$name> = $name(n).into(); + let compact: codec::Compact<$name> = $name(n).into(); let encoded = compact.encode(); assert_eq!(encoded.len(), l); - let decoded = >::decode(&mut & encoded[..]) + let decoded = >::decode(&mut & encoded[..]) .unwrap(); let per_thingy: $name = decoded.into(); assert_eq!(per_thingy, $name(n)); diff --git a/core/sr-primitives/src/sr_arithmetic/rational128.rs b/core/sr-arithmetic/src/rational128.rs similarity index 99% rename from core/sr-primitives/src/sr_arithmetic/rational128.rs rename to core/sr-arithmetic/src/rational128.rs index c9af4269ee4b7..4ba1be77a5a88 100644 --- a/core/sr-primitives/src/sr_arithmetic/rational128.rs +++ b/core/sr-arithmetic/src/rational128.rs @@ -15,7 +15,8 @@ // along with Substrate. If not, see . use rstd::{cmp::Ordering, prelude::*}; -use crate::{helpers_128bit, traits::Zero}; +use crate::helpers_128bit; +use num_traits::Zero; /// A wrapper for any rational number with a 128 bit numerator and denominator. #[derive(Clone, Copy, Default, Eq)] diff --git a/core/sr-arithmetic/src/traits.rs b/core/sr-arithmetic/src/traits.rs new file mode 100644 index 0000000000000..4d1703d3b5c74 --- /dev/null +++ b/core/sr-arithmetic/src/traits.rs @@ -0,0 +1,262 @@ +// Copyright 2017-2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! Primitives for the runtime modules. + +use rstd::prelude::*; +use rstd::{self, convert::{TryFrom, TryInto}}; +//use crate::codec::{Codec, Encode, Decode, HasCompact}; +//use crate::generic::{Digest, DigestItem}; +//use crate::weights::DispatchInfo; +use codec::HasCompact; +pub use integer_sqrt::IntegerSquareRoot; +pub use num_traits::{ + Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, + CheckedShl, CheckedShr +}; +use rstd::ops::{ + Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, + RemAssign, Shl, Shr +}; + +/// A lazy value. +pub trait Lazy { + /// Get a reference to the underlying value. + /// + /// This will compute the value if the function is invoked for the first time. + fn get(&mut self) -> &T; +} + +impl<'a> Lazy<[u8]> for &'a [u8] { + fn get(&mut self) -> &[u8] { &**self } +} + +/// Extensible conversion trait. Generic over both source and destination types. +pub trait Convert { + /// Make conversion. + fn convert(a: A) -> B; +} + +impl Convert for () { + fn convert(_: A) -> B { Default::default() } +} + +/// A meta trait for arithmetic. +/// +/// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to +/// be able to represent at least `u32` values without loss, hence the trait implies `From` +/// and smaller ints. All other conversions are fallible. +pub trait SimpleArithmetic: + Zero + One + IntegerSquareRoot + + From + From + From + TryInto + TryInto + TryInto + + TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + + UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + + UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + + Add + AddAssign + + Sub + SubAssign + + Mul + MulAssign + + Div + DivAssign + + Rem + RemAssign + + Shl + Shr + + CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + + Saturating + PartialOrd + Ord + Bounded + + HasCompact + Sized +{} +impl + From + From + TryInto + TryInto + TryInto + + TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + + UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + + UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + + UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + + Add + AddAssign + + Sub + SubAssign + + Mul + MulAssign + + Div + DivAssign + + Rem + RemAssign + + Shl + Shr + + CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + + Saturating + PartialOrd + Ord + Bounded + + HasCompact + Sized +> SimpleArithmetic for T {} + +/// Just like `From` except that if the source value is too big to fit into the destination type +/// then it'll saturate the destination. +pub trait UniqueSaturatedFrom: Sized { + /// Convert from a value of `T` into an equivalent instance of `Self`. + fn unique_saturated_from(t: T) -> Self; +} + +/// Just like `Into` except that if the source value is too big to fit into the destination type +/// then it'll saturate the destination. +pub trait UniqueSaturatedInto: Sized { + /// Consume self to return an equivalent value of `T`. + fn unique_saturated_into(self) -> T; +} + +impl + Bounded + Sized> UniqueSaturatedFrom for S { + fn unique_saturated_from(t: T) -> Self { + S::try_from(t).unwrap_or_else(|_| Bounded::max_value()) + } +} + +impl + Sized> UniqueSaturatedInto for S { + fn unique_saturated_into(self) -> T { + self.try_into().unwrap_or_else(|_| Bounded::max_value()) + } +} + +/// Simple trait to use checked mul and max value to give a saturated mul operation over +/// supported types. +pub trait Saturating { + /// Saturated addition - if the product can't fit in the type then just use max-value. + fn saturating_add(self, o: Self) -> Self; + + /// Saturated subtraction - if the product can't fit in the type then just use max-value. + fn saturating_sub(self, o: Self) -> Self; + + /// Saturated multiply - if the product can't fit in the type then just use max-value. + fn saturating_mul(self, o: Self) -> Self; +} + +impl Saturating for T { + fn saturating_add(self, o: Self) -> Self { + ::saturating_add(self, o) + } + fn saturating_sub(self, o: Self) -> Self { + ::saturating_sub(self, o) + } + fn saturating_mul(self, o: Self) -> Self { + self.checked_mul(&o).unwrap_or_else(Bounded::max_value) + } +} + +/// Convenience type to work around the highly unergonomic syntax needed +/// to invoke the functions of overloaded generic traits, in this case +/// `SaturatedFrom` and `SaturatedInto`. +pub trait SaturatedConversion { + /// Convert from a value of `T` into an equivalent instance of `Self`. + /// + /// This just uses `UniqueSaturatedFrom` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn saturated_from(t: T) -> Self where Self: UniqueSaturatedFrom { + >::unique_saturated_from(t) + } + + /// Consume self to return an equivalent value of `T`. + /// + /// This just uses `UniqueSaturatedInto` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn saturated_into(self) -> T where Self: UniqueSaturatedInto { + >::unique_saturated_into(self) + } +} +impl SaturatedConversion for T {} + +/// Convenience type to work around the highly unergonomic syntax needed +/// to invoke the functions of overloaded generic traits, in this case +/// `TryFrom` and `TryInto`. +pub trait CheckedConversion { + /// Convert from a value of `T` into an equivalent instance of `Option`. + /// + /// This just uses `TryFrom` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn checked_from(t: T) -> Option where Self: TryFrom { + >::try_from(t).ok() + } + /// Consume self to return `Some` equivalent value of `Option`. + /// + /// This just uses `TryInto` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn checked_into(self) -> Option where Self: TryInto { + >::try_into(self).ok() + } +} +impl CheckedConversion for T {} + +/// Multiply and divide by a number that isn't necessarily the same type. Basically just the same +/// as `Mul` and `Div` except it can be used for all basic numeric types. +pub trait Scale { + /// The output type of the product of `self` and `Other`. + type Output; + + /// @return the product of `self` and `other`. + fn mul(self, other: Other) -> Self::Output; + + /// @return the integer division of `self` and `other`. + fn div(self, other: Other) -> Self::Output; + + /// @return the modulo remainder of `self` and `other`. + fn rem(self, other: Other) -> Self::Output; +} +macro_rules! impl_scale { + ($self:ty, $other:ty) => { + impl Scale<$other> for $self { + type Output = Self; + fn mul(self, other: $other) -> Self::Output { self * (other as Self) } + fn div(self, other: $other) -> Self::Output { self / (other as Self) } + fn rem(self, other: $other) -> Self::Output { self % (other as Self) } + } + } +} +impl_scale!(u128, u128); +impl_scale!(u128, u64); +impl_scale!(u128, u32); +impl_scale!(u128, u16); +impl_scale!(u128, u8); +impl_scale!(u64, u64); +impl_scale!(u64, u32); +impl_scale!(u64, u16); +impl_scale!(u64, u8); +impl_scale!(u32, u32); +impl_scale!(u32, u16); +impl_scale!(u32, u8); +impl_scale!(u16, u16); +impl_scale!(u16, u8); +impl_scale!(u8, u8); + +/// Trait for things that can be clear (have no bits set). For numeric types, essentially the same +/// as `Zero`. +pub trait Clear { + /// True iff no bits are set. + fn is_clear(&self) -> bool; + + /// Return the value of Self that is clear. + fn clear() -> Self; +} + +impl Clear for T { + fn is_clear(&self) -> bool { *self == Self::clear() } + fn clear() -> Self { Default::default() } +} + +/// A meta trait for all bit ops. +pub trait SimpleBitOps: + Sized + Clear + + rstd::ops::BitOr + + rstd::ops::BitXor + + rstd::ops::BitAnd +{} +impl + + rstd::ops::BitXor + + rstd::ops::BitAnd +> SimpleBitOps for T {} diff --git a/core/sr-primitives/Cargo.toml b/core/sr-primitives/Cargo.toml index ac6e8685e2baf..85b9cbbcbcf10 100644 --- a/core/sr-primitives/Cargo.toml +++ b/core/sr-primitives/Cargo.toml @@ -5,12 +5,11 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -num-traits = { version = "0.2.8", default-features = false } -integer-sqrt = "0.1.2" serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } primitives = { package = "substrate-primitives", path = "../primitives", default-features = false } app-crypto = { package = "substrate-application-crypto", path = "../application-crypto", default-features = false } +arithmetic = { package = "sr-arithmetic", path = "../sr-arithmetic", default-features = false } rstd = { package = "sr-std", path = "../sr-std", default-features = false } runtime_io = { package = "sr-io", path = "../sr-io", default-features = false } log = { version = "0.4.8", optional = true } @@ -28,7 +27,6 @@ substrate-offchain = { path = "../offchain" } bench = [] default = ["std"] std = [ - "num-traits/std", "serde", "log", "rstd/std", @@ -36,5 +34,6 @@ std = [ "codec/std", "primitives/std", "app-crypto/std", + "arithmetic/std", "rand", ] diff --git a/core/sr-primitives/src/curve.rs b/core/sr-primitives/src/curve.rs index dc6316bd470c7..e6c75a18a635e 100644 --- a/core/sr-primitives/src/curve.rs +++ b/core/sr-primitives/src/curve.rs @@ -16,7 +16,7 @@ //! Provides some utilities to define a piecewise linear function. -use crate::{Perbill, traits::{SimpleArithmetic, SaturatedConversion}}; +use arithmetic::{Perbill, traits::{SimpleArithmetic, SaturatedConversion}}; use core::ops::Sub; /// Piecewise Linear function in [0, 1] -> [0, 1]. diff --git a/core/sr-primitives/src/generic/header.rs b/core/sr-primitives/src/generic/header.rs index e9a8405fe21b0..5a0726641bf10 100644 --- a/core/sr-primitives/src/generic/header.rs +++ b/core/sr-primitives/src/generic/header.rs @@ -21,8 +21,9 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "std")] use log::debug; use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef, Error}; +use arithmetic::traits::SimpleArithmetic; use crate::traits::{ - self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, Hash as HashT, MaybeSerializeDebug, + self, Member, SimpleBitOps, MaybeDisplay, Hash as HashT, MaybeSerializeDebug, MaybeSerializeDebugButNotDeserialize }; use crate::generic::Digest; diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 7032560d0f6b1..c584ea721a168 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -51,7 +51,6 @@ pub mod testing; pub mod curve; pub mod generic; pub mod offchain; -pub mod sr_arithmetic; pub mod traits; pub mod transaction_validity; pub mod weights; @@ -64,14 +63,14 @@ pub use primitives::{TypeId, crypto::{key_types, KeyTypeId, CryptoType}}; pub use app_crypto::RuntimeAppPublic; /// Re-export top-level arithmetic stuff. -pub use sr_arithmetic::{ +pub use arithmetic::{ Perquintill, Perbill, Permill, Percent, Rational128, Fixed64 }; /// Re-export 128 bit helpers. -pub use sr_arithmetic::helpers_128bit; +pub use arithmetic::helpers_128bit; /// Re-export big_uint stiff. -pub use sr_arithmetic::biguint; +pub use arithmetic::biguint; /// An abstraction over justification for a block's validity under a consensus algorithm. /// @@ -529,37 +528,6 @@ macro_rules! impl_outer_config { } } -/// Checks that `$x` is equal to `$y` with an error rate of `$error`. -/// -/// # Example -/// -/// ```rust -/// # fn main() { -/// sr_primitives::assert_eq_error_rate!(10, 10, 0); -/// sr_primitives::assert_eq_error_rate!(10, 11, 1); -/// sr_primitives::assert_eq_error_rate!(12, 10, 2); -/// # } -/// ``` -/// -/// ```rust,should_panic -/// # fn main() { -/// sr_primitives::assert_eq_error_rate!(12, 10, 1); -/// # } -/// ``` -#[macro_export] -#[cfg(feature = "std")] -macro_rules! assert_eq_error_rate { - ($x:expr, $y:expr, $error:expr $(,)?) => { - assert!( - ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), - "{:?} != {:?} (with error rate {:?})", - $x, - $y, - $error, - ); - }; -} - /// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized /// correctly. #[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 10c2e806584ba..b249589ecf60e 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -17,28 +17,20 @@ //! Primitives for the runtime modules. use rstd::prelude::*; -use rstd::{self, result, marker::PhantomData, convert::{TryFrom, TryInto}}; +use rstd::{self, result, marker::PhantomData}; use runtime_io; #[cfg(feature = "std")] use std::fmt::{Debug, Display}; #[cfg(feature = "std")] use serde::{Serialize, Deserialize, de::DeserializeOwned}; use primitives::{self, Hasher, Blake2Hasher, TypeId}; -use crate::codec::{Codec, Encode, Decode, HasCompact}; +use crate::codec::{Codec, Encode, Decode}; use crate::transaction_validity::{ ValidTransaction, TransactionValidity, TransactionValidityError, UnknownTransaction, }; +pub use arithmetic::traits::*; use crate::generic::{Digest, DigestItem}; use crate::weights::DispatchInfo; -pub use integer_sqrt::IntegerSquareRoot; -pub use num_traits::{ - Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, - CheckedShl, CheckedShr -}; -use rstd::ops::{ - Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign, - RemAssign, Shl, Shr -}; use app_crypto::AppKey; use impl_trait_for_tuples::impl_for_tuples; @@ -192,189 +184,6 @@ impl Convert for Identity { fn convert(a: T) -> T { a } } -/// A structure that performs standard conversion using the standard Rust conversion traits. -pub struct ConvertInto; -impl> Convert for ConvertInto { - fn convert(a: A) -> B { a.into() } -} - -/// A meta trait for arithmetic. -/// -/// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to -/// be able to represent at least `u32` values without loss, hence the trait implies `From` -/// and smaller ints. All other conversions are fallible. -pub trait SimpleArithmetic: - Zero + One + IntegerSquareRoot + - From + From + From + TryInto + TryInto + TryInto + - TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + - UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + - UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + - Add + AddAssign + - Sub + SubAssign + - Mul + MulAssign + - Div + DivAssign + - Rem + RemAssign + - Shl + Shr + - CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + - Saturating + PartialOrd + Ord + Bounded + - HasCompact + Sized -{} -impl + From + From + TryInto + TryInto + TryInto + - TryFrom + TryInto + TryFrom + TryInto + TryFrom + TryInto + - UniqueSaturatedInto + UniqueSaturatedInto + UniqueSaturatedInto + - UniqueSaturatedFrom + UniqueSaturatedInto + UniqueSaturatedFrom + - UniqueSaturatedInto + UniqueSaturatedFrom + UniqueSaturatedInto + - Add + AddAssign + - Sub + SubAssign + - Mul + MulAssign + - Div + DivAssign + - Rem + RemAssign + - Shl + Shr + - CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + - Saturating + PartialOrd + Ord + Bounded + - HasCompact + Sized -> SimpleArithmetic for T {} - -/// Just like `From` except that if the source value is too big to fit into the destination type -/// then it'll saturate the destination. -pub trait UniqueSaturatedFrom: Sized { - /// Convert from a value of `T` into an equivalent instance of `Self`. - fn unique_saturated_from(t: T) -> Self; -} - -/// Just like `Into` except that if the source value is too big to fit into the destination type -/// then it'll saturate the destination. -pub trait UniqueSaturatedInto: Sized { - /// Consume self to return an equivalent value of `T`. - fn unique_saturated_into(self) -> T; -} - -impl + Bounded + Sized> UniqueSaturatedFrom for S { - fn unique_saturated_from(t: T) -> Self { - S::try_from(t).unwrap_or_else(|_| Bounded::max_value()) - } -} - -impl + Sized> UniqueSaturatedInto for S { - fn unique_saturated_into(self) -> T { - self.try_into().unwrap_or_else(|_| Bounded::max_value()) - } -} - -/// Simple trait to use checked mul and max value to give a saturated mul operation over -/// supported types. -pub trait Saturating { - /// Saturated addition - if the product can't fit in the type then just use max-value. - fn saturating_add(self, o: Self) -> Self; - - /// Saturated subtraction - if the product can't fit in the type then just use max-value. - fn saturating_sub(self, o: Self) -> Self; - - /// Saturated multiply - if the product can't fit in the type then just use max-value. - fn saturating_mul(self, o: Self) -> Self; -} - -impl Saturating for T { - fn saturating_add(self, o: Self) -> Self { - ::saturating_add(self, o) - } - fn saturating_sub(self, o: Self) -> Self { - ::saturating_sub(self, o) - } - fn saturating_mul(self, o: Self) -> Self { - self.checked_mul(&o).unwrap_or_else(Bounded::max_value) - } -} - -/// Convenience type to work around the highly unergonomic syntax needed -/// to invoke the functions of overloaded generic traits, in this case -/// `SaturatedFrom` and `SaturatedInto`. -pub trait SaturatedConversion { - /// Convert from a value of `T` into an equivalent instance of `Self`. - /// - /// This just uses `UniqueSaturatedFrom` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn saturated_from(t: T) -> Self where Self: UniqueSaturatedFrom { - >::unique_saturated_from(t) - } - - /// Consume self to return an equivalent value of `T`. - /// - /// This just uses `UniqueSaturatedInto` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn saturated_into(self) -> T where Self: UniqueSaturatedInto { - >::unique_saturated_into(self) - } -} -impl SaturatedConversion for T {} - -/// Convenience type to work around the highly unergonomic syntax needed -/// to invoke the functions of overloaded generic traits, in this case -/// `TryFrom` and `TryInto`. -pub trait CheckedConversion { - /// Convert from a value of `T` into an equivalent instance of `Option`. - /// - /// This just uses `TryFrom` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn checked_from(t: T) -> Option where Self: TryFrom { - >::try_from(t).ok() - } - /// Consume self to return `Some` equivalent value of `Option`. - /// - /// This just uses `TryInto` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn checked_into(self) -> Option where Self: TryInto { - >::try_into(self).ok() - } -} -impl CheckedConversion for T {} - -/// Multiply and divide by a number that isn't necessarily the same type. Basically just the same -/// as `Mul` and `Div` except it can be used for all basic numeric types. -pub trait Scale { - /// The output type of the product of `self` and `Other`. - type Output; - - /// @return the product of `self` and `other`. - fn mul(self, other: Other) -> Self::Output; - - /// @return the integer division of `self` and `other`. - fn div(self, other: Other) -> Self::Output; - - /// @return the modulo remainder of `self` and `other`. - fn rem(self, other: Other) -> Self::Output; -} -macro_rules! impl_scale { - ($self:ty, $other:ty) => { - impl Scale<$other> for $self { - type Output = Self; - fn mul(self, other: $other) -> Self::Output { self * (other as Self) } - fn div(self, other: $other) -> Self::Output { self / (other as Self) } - fn rem(self, other: $other) -> Self::Output { self % (other as Self) } - } - } -} -impl_scale!(u128, u128); -impl_scale!(u128, u64); -impl_scale!(u128, u32); -impl_scale!(u128, u16); -impl_scale!(u128, u8); -impl_scale!(u64, u64); -impl_scale!(u64, u32); -impl_scale!(u64, u16); -impl_scale!(u64, u8); -impl_scale!(u32, u32); -impl_scale!(u32, u16); -impl_scale!(u32, u8); -impl_scale!(u16, u16); -impl_scale!(u16, u8); -impl_scale!(u8, u8); /// Trait for things that can be clear (have no bits set). For numeric types, essentially the same /// as `Zero`. diff --git a/core/sr-primitives/src/weights.rs b/core/sr-primitives/src/weights.rs index 28f1b2fe0cfc4..0acb29db4a659 100644 --- a/core/sr-primitives/src/weights.rs +++ b/core/sr-primitives/src/weights.rs @@ -23,11 +23,10 @@ //! Note that the decl_module macro _cannot_ enforce this and will simply fail if an invalid struct //! (something that does not implement `Weighable`) is passed in. -use crate::{Fixed64, traits::Saturating}; +use arithmetic::{Fixed64, traits::{Saturating, Bounded}}; use crate::codec::{Encode, Decode}; pub use crate::transaction_validity::TransactionPriority; -use crate::traits::Bounded; /// Numeric range of a transaction weight. pub type Weight = u32; From c7f534525920b850be41c9fba8a0048c95355cf8 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 12 Oct 2019 09:59:31 +1300 Subject: [PATCH 17/63] Fix fuzzing --- core/sr-arithmetic/Cargo.toml | 2 +- core/sr-arithmetic/fuzzer/Cargo.lock | 983 +------------------ core/sr-arithmetic/fuzzer/Cargo.toml | 2 +- core/sr-arithmetic/fuzzer/src/biguint.rs | 2 +- core/sr-arithmetic/fuzzer/src/rational128.rs | 2 +- 5 files changed, 6 insertions(+), 985 deletions(-) diff --git a/core/sr-arithmetic/Cargo.toml b/core/sr-arithmetic/Cargo.toml index 0ee0619851cc6..7b617fac86d48 100644 --- a/core/sr-arithmetic/Cargo.toml +++ b/core/sr-arithmetic/Cargo.toml @@ -23,7 +23,7 @@ substrate-offchain = { path = "../offchain" } bench = [] default = ["std"] std = [ - "serde", + "serde", "num-traits/std", "rstd/std", "codec/std", diff --git a/core/sr-arithmetic/fuzzer/Cargo.lock b/core/sr-arithmetic/fuzzer/Cargo.lock index aea7646bda68f..fcf668aa0c024 100644 --- a/core/sr-arithmetic/fuzzer/Cargo.lock +++ b/core/sr-arithmetic/fuzzer/Cargo.lock @@ -1,31 +1,10 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "ahash" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "aho-corasick" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "arbitrary" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "arrayref" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "arrayvec" version = "0.4.12" @@ -39,31 +18,6 @@ name = "autocfg" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "backtrace" -version = "0.3.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base58" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "1.2.0" @@ -74,44 +28,11 @@ name = "bitvec" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "blake2-rfc" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "block-padding" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "byte-slice-cast" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "byteorder" version = "1.3.2" @@ -126,24 +47,11 @@ dependencies = [ "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "cc" -version = "1.0.45" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "clear_on_drop" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cloudabi" version = "0.0.3" @@ -152,119 +60,17 @@ dependencies = [ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "const-random" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "const-random-macro" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "constant_time_eq" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "crunchy" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "crypto-mac" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "curve25519-dalek" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ed25519-dalek" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "elastic-array" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "environmental" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "failure" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "failure_derive" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "fixed-hash" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -281,15 +87,7 @@ version = "0.1.0" dependencies = [ "honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-primitives 2.0.0", -] - -[[package]] -name = "generic-array" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-arithmetic 2.0.0", ] [[package]] @@ -302,69 +100,6 @@ dependencies = [ "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "hash-db" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "hash256-std-hasher" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hashbrown" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hashbrown" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "heapsize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hex" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "hmac" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "hmac-drbg" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "honggfuzz" version = "0.5.45" @@ -383,34 +118,11 @@ dependencies = [ "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "impl-serde" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "impl-trait-for-tuples" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "integer-sqrt" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "keccak" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "lazy_static" version = "1.4.0" @@ -421,59 +133,6 @@ name = "libc" version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libsecp256k1" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lock_api" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lock_api" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "log" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "malloc_size_of_derive" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "memchr" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "memmap" version = "0.7.0" @@ -483,67 +142,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "memory-db" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "memory_units" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "merlin" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "nodrop" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "num-bigint" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-integer" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-rational" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num-traits" version = "0.2.8" @@ -552,19 +155,6 @@ dependencies = [ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "once_cell" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "parity-scale-codec" version = "1.0.6" @@ -588,66 +178,6 @@ dependencies = [ "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parity-util-mem" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-wasm" -version = "0.40.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "parking_lot" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "paste" version = "0.1.6" @@ -668,15 +198,6 @@ dependencies = [ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "pbkdf2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ppv-lite86" version = "0.2.5" @@ -689,7 +210,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -755,24 +275,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.7.2" @@ -785,15 +287,6 @@ dependencies = [ "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand_chacha" version = "0.2.1" @@ -824,14 +317,6 @@ dependencies = [ "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand_hc" version = "0.2.0" @@ -840,88 +325,6 @@ dependencies = [ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "redox_syscall" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "regex" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "regex-syntax" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-demangle" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "rustc-hex" version = "2.0.1" @@ -935,32 +338,6 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "schnorrkel" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "merlin 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scopeguard" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "semver" version = "0.9.0" @@ -993,53 +370,16 @@ dependencies = [ ] [[package]] -name = "sha2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "smallvec" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "sr-io" -version = "2.0.0" -dependencies = [ - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-externalities 2.0.0", - "substrate-primitives 2.0.0", - "substrate-state-machine 2.0.0", - "substrate-trie 2.0.0", - "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sr-primitives" +name = "sr-arithmetic" version = "2.0.0" dependencies = [ - "impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", "sr-std 2.0.0", - "substrate-application-crypto 2.0.0", - "substrate-primitives 2.0.0", ] [[package]] @@ -1054,130 +394,6 @@ name = "static_assertions" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "substrate-application-crypto" -version = "2.0.0" -dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-io 2.0.0", - "sr-std 2.0.0", - "substrate-primitives 2.0.0", -] - -[[package]] -name = "substrate-bip39" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-externalities" -version = "2.0.0" -dependencies = [ - "environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-primitives-storage 2.0.0", -] - -[[package]] -name = "substrate-panic-handler" -version = "2.0.0" -dependencies = [ - "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-primitives" -version = "2.0.0" -dependencies = [ - "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ed25519-dalek 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-serde 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-externalities 2.0.0", - "substrate-primitives-storage 2.0.0", - "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-primitives-storage" -version = "2.0.0" -dependencies = [ - "impl-serde 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", -] - -[[package]] -name = "substrate-state-machine" -version = "2.0.0" -dependencies = [ - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "substrate-externalities 2.0.0", - "substrate-panic-handler 2.0.0", - "substrate-primitives 2.0.0", - "substrate-trie 2.0.0", - "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "substrate-trie" -version = "2.0.0" -dependencies = [ - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", - "substrate-primitives 2.0.0", - "trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "subtle" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "subtle" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "syn" version = "0.15.44" @@ -1198,47 +414,6 @@ dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "synstructure" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tiny-bip39" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tiny-keccak" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "toml" version = "0.5.3" @@ -1247,39 +422,6 @@ dependencies = [ "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "trie-db" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "trie-root" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "twox-hash" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "typenum" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "uint" version = "0.8.1" @@ -1305,27 +447,6 @@ name = "wasi" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "wasmi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmi-validation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasmi-validation" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "winapi" version = "0.3.8" @@ -1345,100 +466,33 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "zeroize" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "zeroize" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [metadata] -"checksum ahash 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "b35dfc96a657c1842b4eb73180b65e37152d4b94d0eb5cb51708aee7826950b4" -"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum arbitrary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4" -"checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" "checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" -"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" -"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" "checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" "checksum bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9633b74910e1870f50f5af189b08487195cdb83c0e27a71d6f64d5e09dd0538b" -"checksum blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6d530bdd2d52966a6d03b7a964add7ae1a288d25214066fd4b600f0f796400" -"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" "checksum byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7cbcbf18128ec71d8d4a0d054461ec59fff5b75b7d10a4c9b7c7cb1a379c3e77" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" -"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum const-random 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7b641a8c9867e341f3295564203b1c250eb8ce6cb6126e007941f78c4d2ed7fe" -"checksum const-random-macro 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c750ec12b83377637110d5a57f5ae08e895b06c4b16e2bdbf1a94ef717428c59" -"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120" "checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -"checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" -"checksum curve25519-dalek 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b7dcd30ba50cdf88b55b033456138b7c0ac4afdc436d82e1b79f370f24cc66d" -"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -"checksum ed25519-dalek 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d07e8b8a8386c3b89a7a4b329fdfa4cb545de2545e9e2ebbc3dd3929253e426" -"checksum elastic-array 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "073be79b6538296faf81c631872676600616073817dd9a440c477ad09b408983" -"checksum environmental 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "34f8467a0284de039e6bd0e25c14519538462ba5beb548bb1f03e645097837a8" -"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" -"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "516877b7b9a1cc2d0293cbce23cd6203f0edbfd4090e6ca4489fecb5aa73050e" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" -"checksum hash-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" -"checksum hash256-std-hasher 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" -"checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" -"checksum hashbrown 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a" -"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" -"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" -"checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" -"checksum hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" "checksum honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)" = "24c27b4aa3049d6d10d8e33d52c9d03ca9aec18f8a449b246f8c4a5b0c10fb34" "checksum impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fa0086251524c50fd53b32e7b05eb6d79e2f97221eaf0c53c0ca9c3096f21d3" -"checksum impl-serde 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bbb1ea6188aca47a0eaeeb330d8a82f16cd500f30b897062d23922568727333a" -"checksum impl-trait-for-tuples 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6947b372790f8948f439bb6aaa6baabdf80be1a207a477ff072f83fb793e428f" "checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" -"checksum keccak 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" -"checksum libsecp256k1 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "63cc09b49bf0cc55885982347b174ad89855e97a12284d2c9dcc6da2e20c28f5" -"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35adee9ed962cf7d07d62cb58bc45029f3227f5b5b86246caa8632f06c187bc3" -"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -"checksum memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ef49315991403ba5fa225a70399df5e115f57b274cb0b1b4bcd6e734fa5bd783" -"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" -"checksum merlin 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "de2d16d3b15fec5943d1144f861f61f279d165fdd60998ca262913b9bf1c8adb" "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" -"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum once_cell 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "532c29a261168a45ce28948f9537ddd7a5dd272cc513b3017b1e82a88f962c37" -"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "001fbbb956d8593f321c7a784f64d16b2c99b2657823976eea729006ad2c3668" "checksum parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42af752f59119656fa3cb31e8852ed24e895b968c0bdb41847da7f0cea6d155f" -"checksum parity-util-mem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2005637ccf93dbb60c85081ccaaf3f945f573da48dcc79f27f9646caa3ec1dc" -"checksum parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1e39faaa292a687ea15120b1ac31899b13586446521df6c149e46f1584671e0f" -"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" "checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" -"checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "83ef7b3b965c0eadcb6838f34f827e1dfb2939bdd5ebd43f9647e009b12b0371" "checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" @@ -1448,59 +502,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" -"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" -"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum schnorrkel 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eacd8381b3c37840c9c9f40472af529e49975bdcbc24f83c31059fd6539023d3" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" "checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" -"checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d" -"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum substrate-bip39 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3be511be555a3633e71739a79e4ddff6a6aaa6579fa6114182a51d72c3eb93c5" -"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" -"checksum subtle 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab3af2eb31c42e8f0ccf43548232556c42737e01a96db6e1777b0be108e79799" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" "checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c5676413eaeb1ea35300a0224416f57abc3bd251657e0fafc12c47ff98c060" -"checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" "checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" -"checksum trie-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d0b62d27e8aa1c07414549ac872480ac82380bab39e730242ab08d82d7cc098a" -"checksum trie-root 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0b779f7c1c8fe9276365d9d5be5c4b5adeacf545117bb3f64c974305789c5c0b" -"checksum twox-hash 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" -"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8f0f47ed099f0db671ce82c66548c5de012e3c0cba3963514d1db15c7588701" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -"checksum wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f31d26deb2d9a37e6cfed420edce3ed604eab49735ba89035e13c98f9a528313" -"checksum wasmi-validation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc0356e3df56e639fc7f7d8a99741915531e27ed735d911ed83d7e1339c8188" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum zeroize 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4090487fa66630f7b166fba2bbb525e247a5449f41c468cc1d98f8ae6ac03120" -"checksum zeroize 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "45af6a010d13e4cf5b54c94ba5a2b2eba5596b9e46bf5875612d332a1f2b3f86" diff --git a/core/sr-arithmetic/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml index 9d585c7280487..2fdfbf5b66c75 100644 --- a/core/sr-arithmetic/fuzzer/Cargo.toml +++ b/core/sr-arithmetic/fuzzer/Cargo.toml @@ -6,7 +6,7 @@ edition = "2018" [dependencies] honggfuzz = "0.5" -sr-primitives = { path = ".." } +sr-arithmetic = { path = ".." } primitive-types = "0.5.1" [workspace] diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 2e63edddc2e20..698fcc37b0250 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -1,5 +1,5 @@ use honggfuzz::fuzz; -use sr_primitives::sr_arithmetic::biguint::{Single, BigUint}; +use sr_arithmetic::biguint::{Single, BigUint}; use std::convert::TryFrom; mod util; diff --git a/core/sr-arithmetic/fuzzer/src/rational128.rs b/core/sr-arithmetic/fuzzer/src/rational128.rs index 89489ede05c07..29d90f05a87a1 100644 --- a/core/sr-arithmetic/fuzzer/src/rational128.rs +++ b/core/sr-arithmetic/fuzzer/src/rational128.rs @@ -1,5 +1,5 @@ use honggfuzz::fuzz; -use sr_primitives::{ +use sr_arithmetic::{ helpers_128bit::multiply_by_rational, traits::Zero }; From 20813dd8923dabfe38b3c7f1b727c8f073a1a863 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 12 Oct 2019 10:04:19 +1300 Subject: [PATCH 18/63] Got rid of fuzzer Cargo.lock --- Cargo.lock | 36 ++ Cargo.toml | 1 + core/sr-arithmetic/fuzzer/Cargo.lock | 527 --------------------------- core/sr-arithmetic/fuzzer/Cargo.toml | 4 +- 4 files changed, 38 insertions(+), 530 deletions(-) delete mode 100644 core/sr-arithmetic/fuzzer/Cargo.lock diff --git a/Cargo.lock b/Cargo.lock index e816e4f0aed83..880a3e3104186 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,6 +92,11 @@ dependencies = [ "xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arbitrary" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arc-swap" version = "0.3.11" @@ -1261,6 +1266,16 @@ dependencies = [ "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "honggfuzz" +version = "0.5.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arbitrary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "http" version = "0.1.18" @@ -2163,6 +2178,15 @@ dependencies = [ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memmap" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "memoffset" version = "0.5.1" @@ -3824,6 +3848,15 @@ dependencies = [ "substrate-offchain 2.0.0", ] +[[package]] +name = "sr-arithmetic-fuzzer" +version = "0.1.0" +dependencies = [ + "honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-arithmetic 2.0.0", +] + [[package]] name = "sr-io" version = "2.0.0" @@ -6621,6 +6654,7 @@ dependencies = [ "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ansi_term 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" "checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d" +"checksum arbitrary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4" "checksum arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4662175ead9cd84451d5c35070517777949a2ed84551764129cedb88384841" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" @@ -6757,6 +6791,7 @@ dependencies = [ "checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" "checksum hmac-drbg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4fe727d41d2eec0a6574d887914347e5ff96a3b87177817e2a9820c5c87fecc2" "checksum hmac-drbg 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e570451493f10f6581b48cdd530413b63ea9e780f544bfd3bdcaa0d89d1a7b" +"checksum honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)" = "24c27b4aa3049d6d10d8e33d52c9d03ca9aec18f8a449b246f8c4a5b0c10fb34" "checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" @@ -6833,6 +6868,7 @@ dependencies = [ "checksum malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35adee9ed962cf7d07d62cb58bc45029f3227f5b5b86246caa8632f06c187bc3" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" "checksum memory-db 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ef49315991403ba5fa225a70399df5e115f57b274cb0b1b4bcd6e734fa5bd783" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" diff --git a/Cargo.toml b/Cargo.toml index 4080813ad4529..d1e10d8e850f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,7 @@ members = [ "core/session", "core/sr-api-macros", "core/sr-arithmetic", + "core/sr-arithmetic/fuzzer", "core/sr-io", "core/sr-primitives", "core/sr-staking-primitives", diff --git a/core/sr-arithmetic/fuzzer/Cargo.lock b/core/sr-arithmetic/fuzzer/Cargo.lock deleted file mode 100644 index fcf668aa0c024..0000000000000 --- a/core/sr-arithmetic/fuzzer/Cargo.lock +++ /dev/null @@ -1,527 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "arbitrary" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "arrayvec" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "autocfg" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitflags" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "bitvec" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byte-slice-cast" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "c2-chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fixed-hash" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "fuzzer" -version = "0.1.0" -dependencies = [ - "honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-arithmetic 2.0.0", -] - -[[package]] -name = "getrandom" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "honggfuzz" -version = "0.5.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arbitrary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "impl-codec" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "integer-sqrt" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "libc" -version = "0.2.62" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memmap" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "num-traits" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-scale-codec" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "paste" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "paste-impl" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "primitive-types" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-crate" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "proc-macro2" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_chacha" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc-hex" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive" -version = "1.0.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "sr-arithmetic" -version = "2.0.0" -dependencies = [ - "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "sr-std 2.0.0", -] - -[[package]] -name = "sr-std" -version = "2.0.0" -dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "static_assertions" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "toml" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "uint" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "wasi" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[metadata] -"checksum arbitrary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "64cf76cb6e2222ed0ea86b2b0ee2f71c96ec6edd5af42e84d59160e91b836ec4" -"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" -"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" -"checksum bitvec 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9633b74910e1870f50f5af189b08487195cdb83c0e27a71d6f64d5e09dd0538b" -"checksum byte-slice-cast 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7cbcbf18128ec71d8d4a0d054461ec59fff5b75b7d10a4c9b7c7cb1a379c3e77" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -"checksum fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "516877b7b9a1cc2d0293cbce23cd6203f0edbfd4090e6ca4489fecb5aa73050e" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" -"checksum honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)" = "24c27b4aa3049d6d10d8e33d52c9d03ca9aec18f8a449b246f8c4a5b0c10fb34" -"checksum impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3fa0086251524c50fd53b32e7b05eb6d79e2f97221eaf0c53c0ca9c3096f21d3" -"checksum integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea155abb3ba6f382a75f1418988c05fe82959ed9ce727de427f9cfd425b0c903" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" -"checksum memmap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" -"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "001fbbb956d8593f321c7a784f64d16b2c99b2657823976eea729006ad2c3668" -"checksum parity-scale-codec-derive 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42af752f59119656fa3cb31e8852ed24e895b968c0bdb41847da7f0cea6d155f" -"checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" -"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" -"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" -"checksum primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "83ef7b3b965c0eadcb6838f34f827e1dfb2939bdd5ebd43f9647e009b12b0371" -"checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" -"checksum proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "114cdf1f426eb7f550f01af5f53a33c0946156f6814aec939b3bd77e844f9a9d" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" -"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" -"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "403bb3a286107a04825a5f82e1270acc1e14028d3d554d7a1e08914549575ab8" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" -"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" -"checksum static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c19be23126415861cb3a23e501d34a708f7f9b2183c5252d690941c2e69199d5" -"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -"checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724" -"checksum uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8f0f47ed099f0db671ce82c66548c5de012e3c0cba3963514d1db15c7588701" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/core/sr-arithmetic/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml index 2fdfbf5b66c75..b26d8633b2881 100644 --- a/core/sr-arithmetic/fuzzer/Cargo.toml +++ b/core/sr-arithmetic/fuzzer/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "fuzzer" +name = "sr-arithmetic-fuzzer" version = "0.1.0" authors = ["Ashley "] edition = "2018" @@ -9,8 +9,6 @@ honggfuzz = "0.5" sr-arithmetic = { path = ".." } primitive-types = "0.5.1" -[workspace] - [[bin]] name = "biguint" path = "src/biguint.rs" From 4aa7dd543cbb7252374c67865f0ff5740f0c2854 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 12 Oct 2019 10:24:40 +1300 Subject: [PATCH 19/63] Added no_std --- core/sr-arithmetic/fuzzer/src/biguint.rs | 18 +++++------------- core/sr-arithmetic/src/lib.rs | 2 ++ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 698fcc37b0250..35d84a1ba0762 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -6,6 +6,8 @@ mod util; use util::value_between; +type S = u128; + fn main() { loop { fuzz!(|data: (usize, usize, Vec, Vec)| { @@ -16,8 +18,6 @@ fn main() { digits_2: data.3 }; - // basic_random_ord_eq_works - type S = u128; run_with_data_set(4, 4, false, &data, |u, v| { let ue = S::try_from(u.clone()).unwrap(); let ve = S::try_from(v.clone()).unwrap(); @@ -25,8 +25,6 @@ fn main() { assert_eq!(u.eq(&v), ue.eq(&ve)); }); - // basic_random_add_works - //type S = u128; run_with_data_set(3, 3, false, &data, |u, v| { let expected = S::try_from(u.clone()).unwrap() + S::try_from(v.clone()).unwrap(); let t = u.clone().add(&v); @@ -36,8 +34,6 @@ fn main() { ); }); - // basic_random_sub_works - // type S = u128; run_with_data_set(4, 4, false, &data, |u, v| { let expected = S::try_from(u.clone()).unwrap() .checked_sub(S::try_from(v.clone()).unwrap()); @@ -54,8 +50,6 @@ fn main() { } }); - // basic_random_mul_works - // type S = u128; run_with_data_set(2, 2, false, &data, |u, v| { let expected = S::try_from(u.clone()).unwrap() * S::try_from(v.clone()).unwrap(); let t = u.clone().mul(&v); @@ -65,8 +59,6 @@ fn main() { ); }); - // basic_random_div_works - // type S = u128; run_with_data_set(4, 4, false, &data, |u, v| { let ue = S::try_from(u.clone()).unwrap(); let ve = S::try_from(v.clone()).unwrap(); @@ -127,15 +119,15 @@ fn run_with_data_set( value_between(data.random_limb_len_2, 1, limbs_ub_2)? }; - let u = random_big_uint(digits_len_1, &data.digits_1)?; - let v = random_big_uint(digits_len_2, &data.digits_2)?; + let u = big_uint_of_size(digits_len_1, &data.digits_1)?; + let v = big_uint_of_size(digits_len_2, &data.digits_2)?; // this is easier than using lldb println!("u: {:?}, v: {:?}", u, v); assertion(u, v); Some(()) } -fn random_big_uint(size: usize, digits: &[Single]) -> Option { +fn big_uint_of_size(size: usize, digits: &[Single]) -> Option { if digits.len() != size { None } else { diff --git a/core/sr-arithmetic/src/lib.rs b/core/sr-arithmetic/src/lib.rs index ed7603de4a04b..1c454e822bebb 100644 --- a/core/sr-arithmetic/src/lib.rs +++ b/core/sr-arithmetic/src/lib.rs @@ -16,6 +16,8 @@ //! Minimal fixed point arithmetic primitives and types for runtime. +#![cfg_attr(not(feature = "std"), no_std)] + pub mod biguint; pub mod helpers_128bit; pub mod traits; From e8cbb1d81030cc6868e8b1d143eeb5b34eaeb0af Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 12 Oct 2019 10:37:23 +1300 Subject: [PATCH 20/63] re-export assert_eq_error_rate --- core/sr-primitives/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index c584ea721a168..0a62f7504f0e3 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -69,8 +69,11 @@ pub use arithmetic::{ }; /// Re-export 128 bit helpers. pub use arithmetic::helpers_128bit; -/// Re-export big_uint stiff. +/// Re-export big_uint stuff. pub use arithmetic::biguint; +/// Re-export error rate macro. +#[cfg(feature = "std")] +pub use arithmetic::assert_eq_error_rate; /// An abstraction over justification for a block's validity under a consensus algorithm. /// From f4c51548c20148ce253bb3c9f0e49d93099e7b39 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 12 Oct 2019 10:46:25 +1300 Subject: [PATCH 21/63] bump impl and spec version --- node/runtime/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 70b1b8f16a7cb..d594014092b14 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -84,8 +84,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to equal spec_version. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 175, - impl_version: 175, + spec_version: 176, + impl_version: 176, apis: RUNTIME_API_VERSIONS, }; From 85f8487cbb40376f7a58a90e354e64bd982b3cf7 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 12 Oct 2019 11:14:04 +1300 Subject: [PATCH 22/63] re add convert into --- core/sr-primitives/src/traits.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index b249589ecf60e..f5112c1d1ab2f 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -178,6 +178,12 @@ impl Convert for () { fn convert(_: A) -> B { Default::default() } } +/// A structure that performs standard conversion using the standard Rust conversion traits. +pub struct ConvertInto; +impl> Convert for ConvertInto { + fn convert(a: A) -> B { a.into() } +} + /// A structure that performs identity conversion. pub struct Identity; impl Convert for Identity { From 03dd42ed538fd1148f88e2260dffcb7d15c296d0 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 12 Oct 2019 13:08:50 +1300 Subject: [PATCH 23/63] Add an ignore to the test --- core/sr-arithmetic/src/rational128.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/sr-arithmetic/src/rational128.rs b/core/sr-arithmetic/src/rational128.rs index 4ba1be77a5a88..706d6a5eba83c 100644 --- a/core/sr-arithmetic/src/rational128.rs +++ b/core/sr-arithmetic/src/rational128.rs @@ -374,6 +374,7 @@ mod tests { } #[test] + #[ignore] fn multiply_by_rational_fuzzed_equation() { assert_eq!( multiply_by_rational(154742576605164960401588224, 9223376310179529214, 549756068598), From aeb6a1d4541cea53709608d7b8a43efbfa6ec8e5 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 12 Oct 2019 13:34:22 +1300 Subject: [PATCH 24/63] Enabled benchmarking --- core/sr-arithmetic/fuzzer/src/rational128.rs | 74 +++++--------------- core/sr-arithmetic/src/biguint.rs | 8 +++ core/sr-arithmetic/src/lib.rs | 4 ++ core/sr-arithmetic/src/parts_per_x.rs | 8 +-- 4 files changed, 32 insertions(+), 62 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/src/rational128.rs b/core/sr-arithmetic/fuzzer/src/rational128.rs index 29d90f05a87a1..454c022b72c20 100644 --- a/core/sr-arithmetic/fuzzer/src/rational128.rs +++ b/core/sr-arithmetic/fuzzer/src/rational128.rs @@ -4,71 +4,29 @@ use sr_arithmetic::{ traits::Zero }; -mod util; - -use util::value_between; - fn main() { loop { fuzz!(|data: ([u8; 16], [u8; 16], [u8; 16])| { - let data = Data { - a: u128::from_be_bytes(data.0), - b: u128::from_be_bytes(data.1), - c: u128::from_be_bytes(data.2) - }; - - do_fuzz_multiply_by_rational(32, true, &data); - do_fuzz_multiply_by_rational(32, false, &data); - - do_fuzz_multiply_by_rational(64, true, &data); - do_fuzz_multiply_by_rational(64, false, &data); - - do_fuzz_multiply_by_rational(96, true, &data); - do_fuzz_multiply_by_rational(96, false, &data); - - do_fuzz_multiply_by_rational(127, true, &data); - do_fuzz_multiply_by_rational(127, false, &data); + let (a_bytes, b_bytes, c_bytes) = data; + let (a, b, c) = (u128::from_be_bytes(a_bytes), u128::from_be_bytes(b_bytes), u128::from_be_bytes(c_bytes)); + + println!("++ Equation: {} * {} / {}", a, b, c); + + let truth = mul_div(a, b, c); + // if Err just use the truth value. We don't care about such cases. The point of this + // fuzzing is to make sure: if `multiply_by_rational` returns `Ok`, it must be 100% accurate + // returning `Err` is fine. + let result = multiply_by_rational(a, b, c).unwrap_or(truth); + + if truth != result { + println!("++ Expected {}", truth); + println!("+++++++ Got {}", result); + panic!(); + } }) } } -struct Data { - a: u128, - b: u128, - c: u128 -} - -fn do_fuzz_multiply_by_rational( - bits: u32, - bounded: bool, - data: &Data, -) -> Option<()> { - let upper_bound = 2u128.pow(bits); - - let a = value_between(data.a, 0u128, upper_bound)?; - let c = value_between(data.c, 0u128, upper_bound)?; - let b = value_between( - data.b, - 0u128, - if bounded { c } else { upper_bound } - )?; - - let truth = mul_div(a, b, c); - // if Err just use the truth value. We don't care about such cases. The point of this - // fuzzing is to make sure: if `multiply_by_rational` returns `Ok`, it must be 100% accurate - // returning `Err` is fine. - let result = multiply_by_rational(a, b, c).unwrap_or(truth); - - if truth != result { - println!("++ Computed with more loss than expected: {} * {} / {}", a, b, c); - println!("++ Expected {}", truth); - println!("+++++++ Got {}", result); - panic!(); - } - - Some(()) -} - fn mul_div(a: u128, b: u128, c: u128) -> u128 { use primitive_types::U256; if a.is_zero() { return Zero::zero(); } diff --git a/core/sr-arithmetic/src/biguint.rs b/core/sr-arithmetic/src/biguint.rs index 32daf53e0c16c..c9858d11c45d3 100644 --- a/core/sr-arithmetic/src/biguint.rs +++ b/core/sr-arithmetic/src/biguint.rs @@ -742,6 +742,14 @@ pub mod tests { } + #[cfg(feature = "bench")] + fn random_big_uint(size: usize) -> BigUint { + use rand::Rng; + let mut rng = rand::thread_rng(); + let digits = (0..size).map(|_| rng.gen_range(0, Single::max_value())).collect(); + BigUint { digits } + } + #[cfg(feature = "bench")] #[bench] fn bench_addition_2_digit(bencher: &mut Bencher) { diff --git a/core/sr-arithmetic/src/lib.rs b/core/sr-arithmetic/src/lib.rs index 1c454e822bebb..638fe3e8a064a 100644 --- a/core/sr-arithmetic/src/lib.rs +++ b/core/sr-arithmetic/src/lib.rs @@ -18,6 +18,10 @@ #![cfg_attr(not(feature = "std"), no_std)] +// to allow benchmarking +#![cfg_attr(feature = "bench", feature(test))] +#[cfg(feature = "bench")] extern crate test; + pub mod biguint; pub mod helpers_128bit; pub mod traits; diff --git a/core/sr-arithmetic/src/parts_per_x.rs b/core/sr-arithmetic/src/parts_per_x.rs index 2f0418fc68314..bde18d739bc30 100644 --- a/core/sr-arithmetic/src/parts_per_x.rs +++ b/core/sr-arithmetic/src/parts_per_x.rs @@ -12,15 +12,15 @@ use crate::traits::{SaturatedConversion, UniqueSaturatedInto, Saturating}; /// /// ```rust /// # fn main() { -/// sr_primitives::assert_eq_error_rate!(10, 10, 0); -/// sr_primitives::assert_eq_error_rate!(10, 11, 1); -/// sr_primitives::assert_eq_error_rate!(12, 10, 2); +/// sr_arithmetic::assert_eq_error_rate!(10, 10, 0); +/// sr_arithmetic::assert_eq_error_rate!(10, 11, 1); +/// sr_arithmetic::assert_eq_error_rate!(12, 10, 2); /// # } /// ``` /// /// ```rust,should_panic /// # fn main() { -/// sr_primitives::assert_eq_error_rate!(12, 10, 1); +/// sr_arithmetic::assert_eq_error_rate!(12, 10, 1); /// # } /// ``` #[macro_export] From 117f818b36084e154128de8efafa152e559aefb6 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 12 Oct 2019 13:53:27 +1300 Subject: [PATCH 25/63] Reindent --- core/sr-arithmetic/Cargo.toml | 2 +- core/sr-arithmetic/fuzzer/.gitignore | 1 - core/sr-arithmetic/fuzzer/Cargo.toml | 2 +- core/sr-arithmetic/fuzzer/src/biguint.rs | 216 +++++++++---------- core/sr-arithmetic/fuzzer/src/rational128.rs | 15 +- 5 files changed, 119 insertions(+), 117 deletions(-) diff --git a/core/sr-arithmetic/Cargo.toml b/core/sr-arithmetic/Cargo.toml index 7b617fac86d48..ce2fa3734f661 100644 --- a/core/sr-arithmetic/Cargo.toml +++ b/core/sr-arithmetic/Cargo.toml @@ -23,7 +23,7 @@ substrate-offchain = { path = "../offchain" } bench = [] default = ["std"] std = [ - "serde", + "serde", "num-traits/std", "rstd/std", "codec/std", diff --git a/core/sr-arithmetic/fuzzer/.gitignore b/core/sr-arithmetic/fuzzer/.gitignore index 0fc8d54301e07..3ebcb104d4a50 100644 --- a/core/sr-arithmetic/fuzzer/.gitignore +++ b/core/sr-arithmetic/fuzzer/.gitignore @@ -1,3 +1,2 @@ hfuzz_target hfuzz_workspace -target diff --git a/core/sr-arithmetic/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml index b26d8633b2881..ae20812223278 100644 --- a/core/sr-arithmetic/fuzzer/Cargo.toml +++ b/core/sr-arithmetic/fuzzer/Cargo.toml @@ -15,4 +15,4 @@ path = "src/biguint.rs" [[bin]] name = "rational128" -path = "src/rational128.rs" \ No newline at end of file +path = "src/rational128.rs" diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 35d84a1ba0762..484b0db87585c 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -1,5 +1,5 @@ use honggfuzz::fuzz; -use sr_arithmetic::biguint::{Single, BigUint}; +use sr_arithmetic::biguint::{BigUint, Single}; use std::convert::TryFrom; mod util; @@ -9,128 +9,128 @@ use util::value_between; type S = u128; fn main() { - loop { - fuzz!(|data: (usize, usize, Vec, Vec)| { - let data = Data { - random_limb_len_1: data.0, - random_limb_len_2: data.1, - digits_1: data.2, - digits_2: data.3 - }; + loop { + fuzz!(|data: (usize, usize, Vec, Vec)| { + let data = Data { + random_limb_len_1: data.0, + random_limb_len_2: data.1, + digits_1: data.2, + digits_2: data.3, + }; - run_with_data_set(4, 4, false, &data, |u, v| { - let ue = S::try_from(u.clone()).unwrap(); - let ve = S::try_from(v.clone()).unwrap(); - assert_eq!(u.cmp(&v), ue.cmp(&ve)); - assert_eq!(u.eq(&v), ue.eq(&ve)); - }); + run_with_data_set(4, 4, false, &data, |u, v| { + let ue = S::try_from(u.clone()).unwrap(); + let ve = S::try_from(v.clone()).unwrap(); + assert_eq!(u.cmp(&v), ue.cmp(&ve)); + assert_eq!(u.eq(&v), ue.eq(&ve)); + }); - run_with_data_set(3, 3, false, &data, |u, v| { - let expected = S::try_from(u.clone()).unwrap() + S::try_from(v.clone()).unwrap(); - let t = u.clone().add(&v); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - }); + run_with_data_set(3, 3, false, &data, |u, v| { + let expected = S::try_from(u.clone()).unwrap() + S::try_from(v.clone()).unwrap(); + let t = u.clone().add(&v); + assert_eq!( + S::try_from(t.clone()).unwrap(), expected, + "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + }); - run_with_data_set(4, 4, false, &data, |u, v| { - let expected = S::try_from(u.clone()).unwrap() - .checked_sub(S::try_from(v.clone()).unwrap()); - let t = u.clone().sub(&v); - if expected.is_none() { - assert!(t.is_err()) - } else { - let t = t.unwrap(); - let expected = expected.unwrap(); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - } - }); + run_with_data_set(4, 4, false, &data, |u, v| { + let expected = S::try_from(u.clone()) + .unwrap() + .checked_sub(S::try_from(v.clone()).unwrap()); + let t = u.clone().sub(&v); + if expected.is_none() { + assert!(t.is_err()) + } else { + let t = t.unwrap(); + let expected = expected.unwrap(); + assert_eq!( + S::try_from(t.clone()).unwrap(), expected, + "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + } + }); - run_with_data_set(2, 2, false, &data, |u, v| { - let expected = S::try_from(u.clone()).unwrap() * S::try_from(v.clone()).unwrap(); - let t = u.clone().mul(&v); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - }); + run_with_data_set(2, 2, false, &data, |u, v| { + let expected = S::try_from(u.clone()).unwrap() * S::try_from(v.clone()).unwrap(); + let t = u.clone().mul(&v); + assert_eq!( + S::try_from(t.clone()).unwrap(), expected, + "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, + ); + }); - run_with_data_set(4, 4, false, &data, |u, v| { - let ue = S::try_from(u.clone()).unwrap(); - let ve = S::try_from(v.clone()).unwrap(); - if ve == 0 { - return; - } - let (q, r) = (ue / ve, ue % ve); - if let Some((qq, rr)) = u.clone().div(&v, true) { - assert_eq!( - S::try_from(qq.clone()).unwrap(), q, - "{:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, - ); - assert_eq!( - S::try_from(rr.clone()).unwrap(), r, - "{:?} % {:?} ===> {:?} != {:?}", u, v, rr, r, - ); - } else if v.len() == 1 { - let qq = u.clone().div_unit(ve as Single); - assert_eq!( - S::try_from(qq.clone()).unwrap(), q, - "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, - ); - } else { - if v.msb() == 0 || u.msb() == 0 || u.len() <= v.len() {} // nada - else { panic!("div returned none for an unexpected reason"); } - } - }); - }); - } + run_with_data_set(4, 4, false, &data, |u, v| { + let ue = S::try_from(u.clone()).unwrap(); + let ve = S::try_from(v.clone()).unwrap(); + if ve == 0 { + return; + } + let (q, r) = (ue / ve, ue % ve); + if let Some((qq, rr)) = u.clone().div(&v, true) { + assert_eq!( + S::try_from(qq.clone()).unwrap(), q, + "{:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, + ); + assert_eq!( + S::try_from(rr.clone()).unwrap(), r, + "{:?} % {:?} ===> {:?} != {:?}", u, v, rr, r, + ); + } else if v.len() == 1 { + let qq = u.clone().div_unit(ve as Single); + assert_eq!( + S::try_from(qq.clone()).unwrap(), q, + "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, + ); + } else if v.msb() != 0 && u.msb() != 0 && u.len() > v.len() { + panic!("div returned none for an unexpected reason"); + } + }); + }); + } } struct Data { - random_limb_len_1: usize, - random_limb_len_2: usize, - digits_1: Vec, - digits_2: Vec + random_limb_len_1: usize, + random_limb_len_2: usize, + digits_1: Vec, + digits_2: Vec, } fn run_with_data_set( - limbs_ub_1: usize, - limbs_ub_2: usize, - exact: bool, - data: &Data, - assertion: F, + limbs_ub_1: usize, + limbs_ub_2: usize, + exact: bool, + data: &Data, + assertion: F, ) -> Option<()> - where - F: Fn(BigUint, BigUint) -> () + where + F: Fn(BigUint, BigUint) -> (), { - let digits_len_1 = if exact { - limbs_ub_1 - } else { - value_between(data.random_limb_len_1, 1, limbs_ub_1)? - }; + let digits_len_1 = if exact { + limbs_ub_1 + } else { + value_between(data.random_limb_len_1, 1, limbs_ub_1)? + }; - let digits_len_2 = if exact { - limbs_ub_2 - } else { - value_between(data.random_limb_len_2, 1, limbs_ub_2)? - }; + let digits_len_2 = if exact { + limbs_ub_2 + } else { + value_between(data.random_limb_len_2, 1, limbs_ub_2)? + }; - let u = big_uint_of_size(digits_len_1, &data.digits_1)?; - let v = big_uint_of_size(digits_len_2, &data.digits_2)?; - // this is easier than using lldb - println!("u: {:?}, v: {:?}", u, v); - assertion(u, v); - Some(()) + let u = big_uint_of_size(digits_len_1, &data.digits_1)?; + let v = big_uint_of_size(digits_len_2, &data.digits_2)?; + // this is easier than using lldb + println!("u: {:?}, v: {:?}", u, v); + assertion(u, v); + Some(()) } fn big_uint_of_size(size: usize, digits: &[Single]) -> Option { - if digits.len() != size { - None - } else { - Some(BigUint::from_limbs(digits)) - } -} \ No newline at end of file + if digits.len() != size { + None + } else { + Some(BigUint::from_limbs(digits)) + } +} diff --git a/core/sr-arithmetic/fuzzer/src/rational128.rs b/core/sr-arithmetic/fuzzer/src/rational128.rs index 454c022b72c20..c67cf4826d0a7 100644 --- a/core/sr-arithmetic/fuzzer/src/rational128.rs +++ b/core/sr-arithmetic/fuzzer/src/rational128.rs @@ -1,14 +1,15 @@ use honggfuzz::fuzz; -use sr_arithmetic::{ - helpers_128bit::multiply_by_rational, - traits::Zero -}; +use sr_arithmetic::{helpers_128bit::multiply_by_rational, traits::Zero}; fn main() { loop { fuzz!(|data: ([u8; 16], [u8; 16], [u8; 16])| { let (a_bytes, b_bytes, c_bytes) = data; - let (a, b, c) = (u128::from_be_bytes(a_bytes), u128::from_be_bytes(b_bytes), u128::from_be_bytes(c_bytes)); + let (a, b, c) = ( + u128::from_be_bytes(a_bytes), + u128::from_be_bytes(b_bytes), + u128::from_be_bytes(c_bytes), + ); println!("++ Equation: {} * {} / {}", a, b, c); @@ -29,7 +30,9 @@ fn main() { fn mul_div(a: u128, b: u128, c: u128) -> u128 { use primitive_types::U256; - if a.is_zero() { return Zero::zero(); } + if a.is_zero() { + return Zero::zero(); + } let c = c.max(1); // e for extended From 458edbd23d4e19a507c794300f7f98781f50cb96 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sun, 13 Oct 2019 01:12:09 +1300 Subject: [PATCH 26/63] Clean up biguint fuzzer --- core/sr-arithmetic/fuzzer/src/biguint.rs | 58 ++++++------------------ 1 file changed, 14 insertions(+), 44 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 484b0db87585c..425fc5058799b 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -10,22 +10,17 @@ type S = u128; fn main() { loop { - fuzz!(|data: (usize, usize, Vec, Vec)| { - let data = Data { - random_limb_len_1: data.0, - random_limb_len_2: data.1, - digits_1: data.2, - digits_2: data.3, - }; + fuzz!(|data: (Vec, Vec)| { + let (digits_u, digits_v) = data; - run_with_data_set(4, 4, false, &data, |u, v| { + run_with_data_set(4, &digits_u, &digits_v, |u, v| { let ue = S::try_from(u.clone()).unwrap(); let ve = S::try_from(v.clone()).unwrap(); assert_eq!(u.cmp(&v), ue.cmp(&ve)); assert_eq!(u.eq(&v), ue.eq(&ve)); }); - run_with_data_set(3, 3, false, &data, |u, v| { + run_with_data_set(3, &digits_u, &digits_v, |u, v| { let expected = S::try_from(u.clone()).unwrap() + S::try_from(v.clone()).unwrap(); let t = u.clone().add(&v); assert_eq!( @@ -34,7 +29,7 @@ fn main() { ); }); - run_with_data_set(4, 4, false, &data, |u, v| { + run_with_data_set(4, &digits_u, &digits_v, |u, v| { let expected = S::try_from(u.clone()) .unwrap() .checked_sub(S::try_from(v.clone()).unwrap()); @@ -51,7 +46,7 @@ fn main() { } }); - run_with_data_set(2, 2, false, &data, |u, v| { + run_with_data_set(2, &digits_u, &digits_v, |u, v| { let expected = S::try_from(u.clone()).unwrap() * S::try_from(v.clone()).unwrap(); let t = u.clone().mul(&v); assert_eq!( @@ -60,7 +55,7 @@ fn main() { ); }); - run_with_data_set(4, 4, false, &data, |u, v| { + run_with_data_set(4, &digits_u, &digits_v, |u, v| { let ue = S::try_from(u.clone()).unwrap(); let ve = S::try_from(v.clone()).unwrap(); if ve == 0 { @@ -90,47 +85,22 @@ fn main() { } } -struct Data { - random_limb_len_1: usize, - random_limb_len_2: usize, - digits_1: Vec, - digits_2: Vec, -} - fn run_with_data_set( - limbs_ub_1: usize, - limbs_ub_2: usize, - exact: bool, - data: &Data, + max_limbs: usize, + digits_u: &[Single], digits_v: &[Single], assertion: F, ) -> Option<()> where F: Fn(BigUint, BigUint) -> (), { - let digits_len_1 = if exact { - limbs_ub_1 - } else { - value_between(data.random_limb_len_1, 1, limbs_ub_1)? - }; - - let digits_len_2 = if exact { - limbs_ub_2 - } else { - value_between(data.random_limb_len_2, 1, limbs_ub_2)? - }; + // Ensure that `1 <= num_digits < max_limbs`. + value_between(digits_u.len(), 1, max_limbs)?; + value_between(digits_v.len(), 1, max_limbs)?; - let u = big_uint_of_size(digits_len_1, &data.digits_1)?; - let v = big_uint_of_size(digits_len_2, &data.digits_2)?; + let u = BigUint::from_limbs(digits_u); + let v = BigUint::from_limbs(digits_v); // this is easier than using lldb println!("u: {:?}, v: {:?}", u, v); assertion(u, v); Some(()) } - -fn big_uint_of_size(size: usize, digits: &[Single]) -> Option { - if digits.len() != size { - None - } else { - Some(BigUint::from_limbs(digits)) - } -} From 419bc5a2744ca24e1eb1668526d97daa91107078 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sun, 13 Oct 2019 13:44:50 +1300 Subject: [PATCH 27/63] Clean up biguint more --- core/sr-arithmetic/fuzzer/src/biguint.rs | 23 +++++++++++++---------- core/sr-arithmetic/fuzzer/src/util.rs | 9 --------- 2 files changed, 13 insertions(+), 19 deletions(-) delete mode 100644 core/sr-arithmetic/fuzzer/src/util.rs diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 425fc5058799b..499252e534737 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -2,10 +2,6 @@ use honggfuzz::fuzz; use sr_arithmetic::biguint::{BigUint, Single}; use std::convert::TryFrom; -mod util; - -use util::value_between; - type S = u128; fn main() { @@ -89,18 +85,25 @@ fn run_with_data_set( max_limbs: usize, digits_u: &[Single], digits_v: &[Single], assertion: F, -) -> Option<()> +) where F: Fn(BigUint, BigUint) -> (), { // Ensure that `1 <= num_digits < max_limbs`. - value_between(digits_u.len(), 1, max_limbs)?; - value_between(digits_v.len(), 1, max_limbs)?; + let valid = value_between(digits_u.len(), 1, max_limbs) && + value_between(digits_v.len(), 1, max_limbs); + if !valid { + return; + } let u = BigUint::from_limbs(digits_u); let v = BigUint::from_limbs(digits_v); // this is easier than using lldb - println!("u: {:?}, v: {:?}", u, v); - assertion(u, v); - Some(()) + // println!("u: {:?}, v: {:?}", u, v); + + assertion(u, v) } + +fn value_between(value: usize, min: usize, max: usize) -> bool { + min <= value && value <= max +} \ No newline at end of file diff --git a/core/sr-arithmetic/fuzzer/src/util.rs b/core/sr-arithmetic/fuzzer/src/util.rs deleted file mode 100644 index 534417cb6d717..0000000000000 --- a/core/sr-arithmetic/fuzzer/src/util.rs +++ /dev/null @@ -1,9 +0,0 @@ -use std::cmp::PartialOrd; - -pub fn value_between(value: T, min: T, max: T) -> Option { - if value >= min && value < max { - Some(value) - } else { - None - } -} From 89f6b063f4d29fd537f49ae7d4b3859e317804d5 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sun, 13 Oct 2019 14:35:24 +1300 Subject: [PATCH 28/63] shuffle sr-primitives/traits about --- core/sr-primitives/src/traits.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index f5112c1d1ab2f..72cccf3a3acb8 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -178,18 +178,17 @@ impl Convert for () { fn convert(_: A) -> B { Default::default() } } -/// A structure that performs standard conversion using the standard Rust conversion traits. -pub struct ConvertInto; -impl> Convert for ConvertInto { - fn convert(a: A) -> B { a.into() } -} - /// A structure that performs identity conversion. pub struct Identity; impl Convert for Identity { fn convert(a: T) -> T { a } } +/// A structure that performs standard conversion using the standard Rust conversion traits. +pub struct ConvertInto; +impl> Convert for ConvertInto { + fn convert(a: A) -> B { a.into() } +} /// Trait for things that can be clear (have no bits set). For numeric types, essentially the same /// as `Zero`. From 8fb2890b3f734a17769edf61d0aef7e43faa0ce8 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sun, 13 Oct 2019 15:14:33 +1300 Subject: [PATCH 29/63] Remove unused dependencies --- Cargo.lock | 4 ---- core/sr-arithmetic/Cargo.toml | 5 ----- core/sr-primitives/Cargo.toml | 1 - 3 files changed, 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 880a3e3104186..f7f7718b9f2ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3839,13 +3839,10 @@ dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 2.0.0", - "substrate-offchain 2.0.0", ] [[package]] @@ -3881,7 +3878,6 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/core/sr-arithmetic/Cargo.toml b/core/sr-arithmetic/Cargo.toml index ce2fa3734f661..5516b1fa02d28 100644 --- a/core/sr-arithmetic/Cargo.toml +++ b/core/sr-arithmetic/Cargo.toml @@ -9,15 +9,11 @@ num-traits = { version = "0.2.8", default-features = false } serde = { version = "1.0.101", optional = true, features = ["derive"] } codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"] } rstd = { package = "sr-std", path = "../sr-std", default-features = false } -paste = "0.1.6" -rand = { version = "0.7.2", optional = true } integer-sqrt = "0.1.2" [dev-dependencies] -serde_json = "1.0.41" primitive-types = "0.5.1" rand = "0.7.2" -substrate-offchain = { path = "../offchain" } [features] bench = [] @@ -27,5 +23,4 @@ std = [ "num-traits/std", "rstd/std", "codec/std", - "rand", ] diff --git a/core/sr-primitives/Cargo.toml b/core/sr-primitives/Cargo.toml index 85b9cbbcbcf10..249b89acee965 100644 --- a/core/sr-primitives/Cargo.toml +++ b/core/sr-primitives/Cargo.toml @@ -19,7 +19,6 @@ impl-trait-for-tuples = "0.1.2" [dev-dependencies] serde_json = "1.0.41" -primitive-types = "0.5.1" rand = "0.7.2" substrate-offchain = { path = "../offchain" } From 5eb310a872a662235601086df2e1e0d3ae717224 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sun, 13 Oct 2019 15:15:37 +1300 Subject: [PATCH 30/63] Apply clippy suggestions --- core/sr-arithmetic/src/biguint.rs | 21 ++++++++++----------- core/sr-arithmetic/src/fixed64.rs | 6 +++--- core/sr-arithmetic/src/helpers_128bit.rs | 10 +++++----- core/sr-arithmetic/src/parts_per_x.rs | 14 +++++++------- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/core/sr-arithmetic/src/biguint.rs b/core/sr-arithmetic/src/biguint.rs index c9858d11c45d3..1b168fca6b780 100644 --- a/core/sr-arithmetic/src/biguint.rs +++ b/core/sr-arithmetic/src/biguint.rs @@ -44,8 +44,7 @@ pub fn split(a: Double) -> (Single, Single) { pub fn mul_single(a: Single, b: Single) -> Double { let a: Double = a.into(); let b: Double = b.into(); - let r = a * b; - r + a * b } /// Assumed as a given primitive. @@ -91,7 +90,7 @@ impl BigUint { /// Raw constructor from custom limbs. If `limbs` is empty, `Zero::zero()` implementation is /// used. pub fn from_limbs(limbs: &[Single]) -> Self { - if limbs.len() > 0 { + if !limbs.is_empty() { Self { digits: limbs.to_vec() } } else { Zero::zero() @@ -117,7 +116,7 @@ impl BigUint { return self.digits.get(j).cloned(); } } - return None; + None } /// A naive setter for limb at `index`. Note that the order is lsb -> msb. @@ -291,8 +290,8 @@ impl BigUint { let mut out = Self::with_capacity(n); let mut r: Single = 0; // PROOF: (B-1) * B + (B-1) still fits in double - let with_r = |x: Double, r: Single| { r as Double * B + x }; - for d in (0..=n-1).rev() { + let with_r = |x: Double, r: Single| { Double::from(r) * B + x }; + for d in (0..n).rev() { let (q, rr) = div_single(with_r(self.get(d).into(), r), other) ; out.set(d, q as Single); r = rr; @@ -353,13 +352,13 @@ impl BigUint { * B + Double::from(self_norm.get(j + n - 1)); let divisor = other_norm.get(n - 1); - div_single(dividend, divisor.into()) + div_single(dividend, divisor) }; // D3.1 test qhat // replace qhat and rhat with RefCells. This helps share state with the closure let qhat = RefCell::new(qhat); - let rhat = RefCell::new(rhat as Double); + let rhat = RefCell::new(Double::from(rhat)); let test = || { // decrease qhat if it is bigger than the base (B) @@ -367,13 +366,13 @@ impl BigUint { let rhat_local = *rhat.borrow(); let predicate_1 = qhat_local >= B; let predicate_2 = { - let lhs = qhat_local * other_norm.get(n - 2) as Double; - let rhs = B * rhat_local + self_norm.get(j + n - 2) as Double; + let lhs = qhat_local * Double::from(other_norm.get(n - 2)); + let rhs = B * rhat_local + Double::from(self_norm.get(j + n - 2)); lhs > rhs }; if predicate_1 || predicate_2 { *qhat.borrow_mut() -= 1; - *rhat.borrow_mut() += other_norm.get(n - 1) as Double; + *rhat.borrow_mut() += Double::from(other_norm.get(n - 1)); true } else { false diff --git a/core/sr-arithmetic/src/fixed64.rs b/core/sr-arithmetic/src/fixed64.rs index 5e2fccc1f3f5e..a5fadeb4679e9 100644 --- a/core/sr-arithmetic/src/fixed64.rs +++ b/core/sr-arithmetic/src/fixed64.rs @@ -59,16 +59,16 @@ impl Fixed64 { /// Note that this might be lossy. pub fn from_rational(n: i64, d: u64) -> Self { Self( - ((n as i128).saturating_mul(DIV as i128) / (d as i128).max(1)) + (i128::from(n).saturating_mul(i128::from(DIV)) / i128::from(d).max(1)) .try_into() - .unwrap_or(Bounded::max_value()) + .unwrap_or_else(|_| Bounded::max_value()) ) } /// Performs a saturated multiply and accumulate by unsigned number. /// /// Returns a saturated `int + (self * int)`. - pub fn saturated_multiply_accumulate(&self, int: N) -> N + pub fn saturated_multiply_accumulate(self, int: N) -> N where N: TryFrom + From + UniqueSaturatedInto + Bounded + Clone + Saturating + ops::Rem + ops::Div + ops::Mul + diff --git a/core/sr-arithmetic/src/helpers_128bit.rs b/core/sr-arithmetic/src/helpers_128bit.rs index e8e1f448ab87b..00d25d4029f59 100644 --- a/core/sr-arithmetic/src/helpers_128bit.rs +++ b/core/sr-arithmetic/src/helpers_128bit.rs @@ -21,7 +21,7 @@ use crate::biguint; use num_traits::Zero; -use rstd::{cmp::{min, max}, convert::TryInto}; +use rstd::{cmp::{min, max}, convert::TryInto, mem}; /// Helper gcd function used in Rational128 implementation. pub fn gcd(a: u128, b: u128) -> u128 { @@ -61,16 +61,16 @@ pub fn to_big_uint(x: u128) -> biguint::BigUint { /// cannot be safely casted back to u128. /// /// Invariant: c must be greater than or equal to 1. -pub fn multiply_by_rational(a: u128, b: u128, c: u128) -> Result { +pub fn multiply_by_rational(mut a: u128, mut b: u128, c: u128) -> Result { if a.is_zero() || b.is_zero() { return Ok(Zero::zero()); } let c = c.max(1); // a and b are interchangeable by definition in this function. It always helps to assume the // bigger of which is being multiplied by a `0 < b/c < 1`. Hence, a should be the bigger and // b the smaller one. - let t = a; - let a = a.max(b); - let b = t.min(b); + if b > a { + mem::swap(&mut a, &mut b); + } if let Some(x) = a.checked_mul(b) { // This is the safest way to go. Try it. diff --git a/core/sr-arithmetic/src/parts_per_x.rs b/core/sr-arithmetic/src/parts_per_x.rs index bde18d739bc30..0c0e9a2d6e0bf 100644 --- a/core/sr-arithmetic/src/parts_per_x.rs +++ b/core/sr-arithmetic/src/parts_per_x.rs @@ -80,7 +80,7 @@ macro_rules! implement_per_thing { pub fn square(self) -> Self { // both can be safely casted and multiplied. let p: $upper_type = self.0 as $upper_type * self.0 as $upper_type; - let q: $upper_type = $max as $upper_type * $max as $upper_type; + let q: $upper_type = <$upper_type>::from($max) * <$upper_type>::from($max); Self::from_rational_approximation(p, q) } @@ -124,7 +124,7 @@ macro_rules! implement_per_thing { // fit in $upper_type. This is guaranteed by the macro tests. let part = p_reduce as $upper_type - * ($max as $upper_type) + * <$upper_type>::from($max) / q_reduce as $upper_type; $name(part as $type) @@ -142,7 +142,7 @@ macro_rules! implement_per_thing { fn saturating_mul(self, rhs: Self) -> Self { let a = self.0 as $upper_type; let b = rhs.0 as $upper_type; - let m = $max as $upper_type; + let m = <$upper_type>::from($max); let parts = a * b / m; // This will always fit into $type. Self::from_parts(parts as $type) @@ -233,11 +233,11 @@ macro_rules! implement_per_thing { // needed for `from_rational_approximation` assert!(2 * $max < <$type>::max_value()); - assert!(($max as $upper_type) < <$upper_type>::max_value()); + assert!(<$upper_type>::from($max) < <$upper_type>::max_value()); // for something like percent they can be the same. assert!((<$type>::max_value() as $upper_type) <= <$upper_type>::max_value()); - assert!(($max as $upper_type).checked_mul($max.into()).is_some()); + assert!(<$upper_type>::from($max).checked_mul($max.into()).is_some()); } #[derive(Encode, Decode, PartialEq, Eq, Debug)] @@ -399,7 +399,7 @@ macro_rules! implement_per_thing { fn per_thing_from_rationale_approx_works() { // This is just to make sure something like Percent which _might_ get built from a // u8 does not overflow in the context of this test. - let max_value = $max as $upper_type; + let max_value = <$upper_type>::from($max); // almost at the edge assert_eq!( $name::from_rational_approximation($max - 1, $max + 1), @@ -484,7 +484,7 @@ macro_rules! implement_per_thing { assert_eq!($name::from_percent(10).square(), $name::from_percent(1)); assert_eq!( $name::from_percent(2).square(), - $name::from_parts((4 * ($max as $upper_type) / 100 / 100) as $type) + $name::from_parts((4 * <$upper_type>::from($max) / 100 / 100) as $type) ); } From 316f5621d9db1e1bbc4c0052054556d344582712 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sun, 13 Oct 2019 19:27:58 +1300 Subject: [PATCH 31/63] upgrade primitive-types versions --- core/sr-arithmetic/Cargo.toml | 2 +- core/sr-arithmetic/fuzzer/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sr-arithmetic/Cargo.toml b/core/sr-arithmetic/Cargo.toml index 5516b1fa02d28..d98404db9492e 100644 --- a/core/sr-arithmetic/Cargo.toml +++ b/core/sr-arithmetic/Cargo.toml @@ -12,7 +12,7 @@ rstd = { package = "sr-std", path = "../sr-std", default-features = false } integer-sqrt = "0.1.2" [dev-dependencies] -primitive-types = "0.5.1" +primitive-types = "0.6.0" rand = "0.7.2" [features] diff --git a/core/sr-arithmetic/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml index ae20812223278..188b3a69354f7 100644 --- a/core/sr-arithmetic/fuzzer/Cargo.toml +++ b/core/sr-arithmetic/fuzzer/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] honggfuzz = "0.5" sr-arithmetic = { path = ".." } -primitive-types = "0.5.1" +primitive-types = "0.6" [[bin]] name = "biguint" From ac9a2f2c620d3c7a67bc566418ac8434f8eed022 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sun, 13 Oct 2019 20:27:59 +1300 Subject: [PATCH 32/63] Run tests against num-bigint --- Cargo.lock | 40 +++++++++++- core/sr-arithmetic/fuzzer/Cargo.toml | 2 + core/sr-arithmetic/fuzzer/src/biguint.rs | 80 +++++++++++++++++++++++- core/sr-arithmetic/src/biguint.rs | 4 ++ 4 files changed, 122 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f7f7718b9f2ea..c8ae57eaea04b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -893,6 +893,17 @@ dependencies = [ "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fixed-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "static_assertions 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fixedbitset" version = "0.1.9" @@ -2642,6 +2653,16 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-bigint" +version = "0.2.3" +source = "git+https://github.com/expenses/num-bigint?branch=as-slice#66cbc96158015d498340365012ec7d3b7bd3f052" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-bigint" version = "0.2.3" @@ -3025,6 +3046,16 @@ dependencies = [ "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "primitive-types" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fixed-hash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "impl-codec 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-crate" version = "0.1.4" @@ -3839,7 +3870,7 @@ dependencies = [ "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-scale-codec 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "sr-std 2.0.0", @@ -3850,7 +3881,9 @@ name = "sr-arithmetic-fuzzer" version = "0.1.0" dependencies = [ "honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)", - "primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (git+https://github.com/expenses/num-bigint?branch=as-slice)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-arithmetic 2.0.0", ] @@ -6743,6 +6776,7 @@ dependencies = [ "checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" "checksum finality-grandpa 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9681c1f75941ea47584573dd2bc10558b2067d460612945887e00744e43393be" "checksum fixed-hash 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "516877b7b9a1cc2d0293cbce23cd6203f0edbfd4090e6ca4489fecb5aa73050e" +"checksum fixed-hash 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6357b15872f8126e4ea7cf79d579473f132ccd2de239494ad1bf4aa892faea68" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" @@ -6884,6 +6918,7 @@ dependencies = [ "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum nohash-hasher 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4e657a6ec97f9a3ba46f6f7034ea6db9fcd5b71d25ef1074b7bc03da49be0e8e" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +"checksum num-bigint 0.2.3 (git+https://github.com/expenses/num-bigint?branch=as-slice)" = "" "checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" @@ -6927,6 +6962,7 @@ dependencies = [ "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" "checksum primitive-types 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "83ef7b3b965c0eadcb6838f34f827e1dfb2939bdd5ebd43f9647e009b12b0371" +"checksum primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97b5a08dda18910f056e5c2060c034e77cab18e0bd7d895e44f03207af4c71d5" "checksum proc-macro-crate 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" "checksum proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "114cdf1f426eb7f550f01af5f53a33c0946156f6814aec939b3bd77e844f9a9d" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" diff --git a/core/sr-arithmetic/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml index 188b3a69354f7..f9a0369bcf412 100644 --- a/core/sr-arithmetic/fuzzer/Cargo.toml +++ b/core/sr-arithmetic/fuzzer/Cargo.toml @@ -8,6 +8,8 @@ edition = "2018" honggfuzz = "0.5" sr-arithmetic = { path = ".." } primitive-types = "0.6" +num-bigint = { git = "https://github.com/expenses/num-bigint", branch = "as-slice" } +num-traits = "*" [[bin]] name = "biguint" diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 499252e534737..58c189ba79731 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -1,13 +1,14 @@ use honggfuzz::fuzz; use sr_arithmetic::biguint::{BigUint, Single}; use std::convert::TryFrom; +use num_traits::ops::checked::CheckedDiv; type S = u128; fn main() { loop { - fuzz!(|data: (Vec, Vec)| { - let (digits_u, digits_v) = data; + fuzz!(|data: (Vec, Vec, bool)| { + let (mut digits_u, mut digits_v, rem) = data; run_with_data_set(4, &digits_u, &digits_v, |u, v| { let ue = S::try_from(u.clone()).unwrap(); @@ -77,6 +78,64 @@ fn main() { panic!("div returned none for an unexpected reason"); } }); + + // Test against num_bigint + + let u = BigUint::from_limbs(&digits_u); + let v = BigUint::from_limbs(&digits_v); + + digits_u.reverse(); + digits_v.reverse(); + + let num_u = num_bigint::BigUint::new(digits_u); + let num_v = num_bigint::BigUint::new(digits_v); + + // Equality + + assert_biguints_eq(&u, &num_u); + assert_biguints_eq(&v, &num_v); + + // Addition + + let mut w = u.clone().add(&v); + let mut num_w = num_u.clone() + &num_v; + + assert_biguints_eq(&w, &num_w); + + // Subtraction + + if let Ok(w) = u.clone().sub(&v) { + num_w = num_u.clone() - &num_v; + + assert_biguints_eq(&w, &num_w); + } + + // Multiplication + + w = u.clone().mul(&v); + num_w = num_u.clone() * &num_v; + + assert_biguints_eq(&w, &num_w); + + // Division + + if v.len() == 1 && v.get(0) != 0 { + w = u.clone().div_unit(v.get(0)); + num_w = num_u.clone() / &num_v; + assert_biguints_eq(&w, &num_w); + } else { + let w = u.clone().div(&v, rem).map(|(w, _)| w); + let num_w = num_u.clone().checked_div(&num_v); + + // assert that the division was checked equally: + // assert_eq!(w.is_some(), num_w.is_some()); + + if let Some(w) = w { + if let Some(num_w) = num_w { + assert_biguints_eq(&w, &num_w); + } + } + } }); } } @@ -106,4 +165,21 @@ fn run_with_data_set( fn value_between(value: usize, min: usize, max: usize) -> bool { min <= value && value <= max +} + +fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) { + println!("arithmetic: {:?}", a); + println!("num-bigint: {:?}", b); + + let mut a = a.as_slice(); + + while !a.is_empty() && a[0] == 0 { + a = &a[1..]; + } + + let mut a = a.to_vec(); + + a.reverse(); + + assert_eq!(&(*a), b.as_slice()); } \ No newline at end of file diff --git a/core/sr-arithmetic/src/biguint.rs b/core/sr-arithmetic/src/biguint.rs index 1b168fca6b780..e4436f8181347 100644 --- a/core/sr-arithmetic/src/biguint.rs +++ b/core/sr-arithmetic/src/biguint.rs @@ -97,6 +97,10 @@ impl BigUint { } } + pub fn as_slice(&self) -> &[Single] { + &self.digits + } + /// Number of limbs. pub fn len(&self) -> usize { self.digits.len() } From 5a2121337fa423426817e15e8fd930fb1929ad48 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sun, 13 Oct 2019 21:53:41 +1300 Subject: [PATCH 33/63] Get rid of allocation in assert_biguints_eq --- core/sr-arithmetic/fuzzer/src/biguint.rs | 36 +++++++++--------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 58c189ba79731..70ac516a3ab8d 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -97,31 +97,31 @@ fn main() { // Addition - let mut w = u.clone().add(&v); - let mut num_w = num_u.clone() + &num_v; + let w = u.clone().add(&v); + let num_w = num_u.clone() + &num_v; assert_biguints_eq(&w, &num_w); // Subtraction if let Ok(w) = u.clone().sub(&v) { - num_w = num_u.clone() - &num_v; + let num_w = num_u.clone() - &num_v; assert_biguints_eq(&w, &num_w); } // Multiplication - w = u.clone().mul(&v); - num_w = num_u.clone() * &num_v; + let w = u.clone().mul(&v); + let num_w = num_u.clone() * &num_v; assert_biguints_eq(&w, &num_w); // Division if v.len() == 1 && v.get(0) != 0 { - w = u.clone().div_unit(v.get(0)); - num_w = num_u.clone() / &num_v; + let w = u.clone().div_unit(v.get(0)); + let num_w = num_u.clone() / &num_v; assert_biguints_eq(&w, &num_w); } else { let w = u.clone().div(&v, rem).map(|(w, _)| w); @@ -131,9 +131,7 @@ fn main() { // assert_eq!(w.is_some(), num_w.is_some()); if let Some(w) = w { - if let Some(num_w) = num_w { - assert_biguints_eq(&w, &num_w); - } + assert_biguints_eq(&w, &num_w.unwrap()); } } }); @@ -168,18 +166,10 @@ fn value_between(value: usize, min: usize, max: usize) -> bool { } fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) { - println!("arithmetic: {:?}", a); - println!("num-bigint: {:?}", b); + // `BigUint` doesn't check the input in `from_limbs` so we skip any leading 0s. + let a_iter = a.as_slice().iter().skip_while(|&&i| i == 0); + // the `num-bigint` `BigUint` is little endian whereas our `BigUint` is big endian. + let b_iter = b.as_slice().iter().rev(); - let mut a = a.as_slice(); - - while !a.is_empty() && a[0] == 0 { - a = &a[1..]; - } - - let mut a = a.to_vec(); - - a.reverse(); - - assert_eq!(&(*a), b.as_slice()); + assert!(a_iter.eq(b_iter), "arithmetic: {:?}\nnum-bigint: {:?}", a, b); } \ No newline at end of file From 2123d00f7b035790a45940cfe9bc48a462d71ad5 Mon Sep 17 00:00:00 2001 From: Ashley Date: Mon, 14 Oct 2019 17:47:56 +1300 Subject: [PATCH 34/63] Add an optimisation to multiply_by_rational --- core/sr-arithmetic/src/helpers_128bit.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/core/sr-arithmetic/src/helpers_128bit.rs b/core/sr-arithmetic/src/helpers_128bit.rs index 00d25d4029f59..10cc94ae777e6 100644 --- a/core/sr-arithmetic/src/helpers_128bit.rs +++ b/core/sr-arithmetic/src/helpers_128bit.rs @@ -61,9 +61,9 @@ pub fn to_big_uint(x: u128) -> biguint::BigUint { /// cannot be safely casted back to u128. /// /// Invariant: c must be greater than or equal to 1. -pub fn multiply_by_rational(mut a: u128, mut b: u128, c: u128) -> Result { +pub fn multiply_by_rational(mut a: u128, mut b: u128, mut c: u128) -> Result { if a.is_zero() || b.is_zero() { return Ok(Zero::zero()); } - let c = c.max(1); + c = c.max(1); // a and b are interchangeable by definition in this function. It always helps to assume the // bigger of which is being multiplied by a `0 < b/c < 1`. Hence, a should be the bigger and @@ -72,6 +72,15 @@ pub fn multiply_by_rational(mut a: u128, mut b: u128, c: u128) -> Result Date: Tue, 15 Oct 2019 11:28:56 +1300 Subject: [PATCH 35/63] rename parts_per_x -> per_things --- core/sr-arithmetic/src/lib.rs | 4 ++-- core/sr-arithmetic/src/{parts_per_x.rs => per_things.rs} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename core/sr-arithmetic/src/{parts_per_x.rs => per_things.rs} (100%) diff --git a/core/sr-arithmetic/src/lib.rs b/core/sr-arithmetic/src/lib.rs index 638fe3e8a064a..e95a13eb3f915 100644 --- a/core/sr-arithmetic/src/lib.rs +++ b/core/sr-arithmetic/src/lib.rs @@ -25,10 +25,10 @@ pub mod biguint; pub mod helpers_128bit; pub mod traits; -mod parts_per_x; +mod per_things; mod fixed64; mod rational128; pub use fixed64::Fixed64; -pub use parts_per_x::{Percent, Permill, Perbill, Perquintill}; +pub use per_things::{Percent, Permill, Perbill, Perquintill}; pub use rational128::Rational128; diff --git a/core/sr-arithmetic/src/parts_per_x.rs b/core/sr-arithmetic/src/per_things.rs similarity index 100% rename from core/sr-arithmetic/src/parts_per_x.rs rename to core/sr-arithmetic/src/per_things.rs From 2acc34647cd816af18745dc352670d22538dc0c2 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 11:30:59 +1300 Subject: [PATCH 36/63] Change fuzzer cargo.toml --- Cargo.lock | 2 +- core/sr-arithmetic/fuzzer/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c54a5025a68c2..dea9ea42d3826 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3888,7 +3888,7 @@ dependencies = [ [[package]] name = "sr-arithmetic-fuzzer" -version = "0.1.0" +version = "2.0.0" dependencies = [ "honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.3 (git+https://github.com/expenses/num-bigint?branch=as-slice)", diff --git a/core/sr-arithmetic/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml index f9a0369bcf412..149ab2764919a 100644 --- a/core/sr-arithmetic/fuzzer/Cargo.toml +++ b/core/sr-arithmetic/fuzzer/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "sr-arithmetic-fuzzer" -version = "0.1.0" -authors = ["Ashley "] +version = "2.0.0" +authors = ["Parity Technologies "] edition = "2018" [dependencies] From 38650cf6ea48ea0c4b871a700c6122e7d3e76942 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 11:35:39 +1300 Subject: [PATCH 37/63] Remove allocation from BigUint PartialEq impl --- core/sr-arithmetic/fuzzer/src/biguint.rs | 9 +++++++-- core/sr-arithmetic/src/biguint.rs | 7 +------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 70ac516a3ab8d..b00a71ca715b6 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -87,14 +87,19 @@ fn main() { digits_u.reverse(); digits_v.reverse(); - let num_u = num_bigint::BigUint::new(digits_u); - let num_v = num_bigint::BigUint::new(digits_v); + let num_u = num_bigint::BigUint::new(digits_u.clone()); + let num_v = num_bigint::BigUint::new(digits_v.clone()); // Equality assert_biguints_eq(&u, &num_u); assert_biguints_eq(&v, &num_v); + if digits_u == digits_v { + assert_eq!(u, v); + assert_eq!(num_u, num_v); + } + // Addition let w = u.clone().add(&v); diff --git a/core/sr-arithmetic/src/biguint.rs b/core/sr-arithmetic/src/biguint.rs index e4436f8181347..b12dd9d8d32c9 100644 --- a/core/sr-arithmetic/src/biguint.rs +++ b/core/sr-arithmetic/src/biguint.rs @@ -452,12 +452,7 @@ impl rstd::fmt::Debug for BigUint { impl PartialEq for BigUint { fn eq(&self, other: &Self) -> bool { - // sadly, we have to reallocate here as strip mutably uses self. - let mut lhs = self.clone(); - let mut rhs = other.clone(); - lhs.lstrip(); - rhs.lstrip(); - lhs.digits.eq(&rhs.digits) + self.cmp(other) == Ordering::Equal } } From a377d3eab86f3329e5c5c6e90397047d09d17d57 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 11:36:57 +1300 Subject: [PATCH 38/63] Remove accidental indentation --- core/sr-arithmetic/src/biguint.rs | 52 +++++++++++++++---------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/core/sr-arithmetic/src/biguint.rs b/core/sr-arithmetic/src/biguint.rs index b12dd9d8d32c9..7bb38d32fec97 100644 --- a/core/sr-arithmetic/src/biguint.rs +++ b/core/sr-arithmetic/src/biguint.rs @@ -520,40 +520,40 @@ impl Zero for BigUint { } macro_rules! impl_try_from_number_for { - ($([$type:ty, $len:expr]),+) => { - $( - impl TryFrom for $type { - type Error = &'static str; - fn try_from(mut value: BigUint) -> Result<$type, Self::Error> { - value.lstrip(); - let error_message = concat!("cannot fit a number into ", stringify!($type)); - if value.len() * SHIFT > $len { - Err(error_message) - } else { - let mut acc: $type = Zero::zero(); - for (i, d) in value.digits.iter().rev().cloned().enumerate() { - let d: $type = d.into(); - acc += d << (SHIFT * i); - } - Ok(acc) + ($([$type:ty, $len:expr]),+) => { + $( + impl TryFrom for $type { + type Error = &'static str; + fn try_from(mut value: BigUint) -> Result<$type, Self::Error> { + value.lstrip(); + let error_message = concat!("cannot fit a number into ", stringify!($type)); + if value.len() * SHIFT > $len { + Err(error_message) + } else { + let mut acc: $type = Zero::zero(); + for (i, d) in value.digits.iter().rev().cloned().enumerate() { + let d: $type = d.into(); + acc += d << (SHIFT * i); } + Ok(acc) } } - )* - }; - } + } + )* + }; +} // can only be implemented for sizes bigger than two limb. impl_try_from_number_for!([u128, 128], [u64, 64]); macro_rules! impl_from_for_smaller_than_word { - ($($type:ty),+) => { - $(impl From<$type> for BigUint { - fn from(a: $type) -> Self { - Self { digits: vec! [a.into()] } - } - })* - } + ($($type:ty),+) => { + $(impl From<$type> for BigUint { + fn from(a: $type) -> Self { + Self { digits: vec! [a.into()] } + } + })* } +} impl_from_for_smaller_than_word!(u8, u16, Single); impl From for BigUint { From ae25a410b1d108af6e8459c72c05f7b2aa075e73 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 11:46:25 +1300 Subject: [PATCH 39/63] Renmove Lazy and Convert traits --- core/sr-arithmetic/src/traits.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/core/sr-arithmetic/src/traits.rs b/core/sr-arithmetic/src/traits.rs index 4d1703d3b5c74..2a4e972eb7af7 100644 --- a/core/sr-arithmetic/src/traits.rs +++ b/core/sr-arithmetic/src/traits.rs @@ -32,28 +32,6 @@ use rstd::ops::{ RemAssign, Shl, Shr }; -/// A lazy value. -pub trait Lazy { - /// Get a reference to the underlying value. - /// - /// This will compute the value if the function is invoked for the first time. - fn get(&mut self) -> &T; -} - -impl<'a> Lazy<[u8]> for &'a [u8] { - fn get(&mut self) -> &[u8] { &**self } -} - -/// Extensible conversion trait. Generic over both source and destination types. -pub trait Convert { - /// Make conversion. - fn convert(a: A) -> B; -} - -impl Convert for () { - fn convert(_: A) -> B { Default::default() } -} - /// A meta trait for arithmetic. /// /// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to From 20a04884fc030f02b2dbc91440d395c774498b0e Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 11:47:16 +1300 Subject: [PATCH 40/63] Copy assert_eq_error_rate macro back to sr-primitives --- core/sr-arithmetic/src/per_things.rs | 21 ++---------------- core/sr-primitives/src/lib.rs | 32 +++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/core/sr-arithmetic/src/per_things.rs b/core/sr-arithmetic/src/per_things.rs index 0c0e9a2d6e0bf..8252d64aeb96a 100644 --- a/core/sr-arithmetic/src/per_things.rs +++ b/core/sr-arithmetic/src/per_things.rs @@ -6,24 +6,7 @@ use rstd::{ops, prelude::*, convert::TryInto}; use codec::{Encode, Decode}; use crate::traits::{SaturatedConversion, UniqueSaturatedInto, Saturating}; -/// Checks that `$x` is equal to `$y` with an error rate of `$error`. -/// -/// # Example -/// -/// ```rust -/// # fn main() { -/// sr_arithmetic::assert_eq_error_rate!(10, 10, 0); -/// sr_arithmetic::assert_eq_error_rate!(10, 11, 1); -/// sr_arithmetic::assert_eq_error_rate!(12, 10, 2); -/// # } -/// ``` -/// -/// ```rust,should_panic -/// # fn main() { -/// sr_arithmetic::assert_eq_error_rate!(12, 10, 1); -/// # } -/// ``` -#[macro_export] +/// Copied from `sr-primitives` and documented there. #[cfg(feature = "std")] macro_rules! assert_eq_error_rate { ($x:expr, $y:expr, $error:expr $(,)?) => { @@ -222,7 +205,7 @@ macro_rules! implement_per_thing { mod $test_mod { use codec::{Encode, Decode}; use super::{$name, Saturating}; - use crate::{assert_eq_error_rate, traits::Zero}; + use crate::traits::Zero; #[test] diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 0a62f7504f0e3..9ec8fed2e37d7 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -71,9 +71,6 @@ pub use arithmetic::{ pub use arithmetic::helpers_128bit; /// Re-export big_uint stuff. pub use arithmetic::biguint; -/// Re-export error rate macro. -#[cfg(feature = "std")] -pub use arithmetic::assert_eq_error_rate; /// An abstraction over justification for a block's validity under a consensus algorithm. /// @@ -531,6 +528,35 @@ macro_rules! impl_outer_config { } } +/// Checks that `$x` is equal to `$y` with an error rate of `$error`. +/// +/// # Example +/// +/// ```rust +/// # fn main() { +/// sr_primitives::assert_eq_error_rate!(10, 10, 0); +/// sr_primitives::assert_eq_error_rate!(10, 11, 1); +/// sr_primitives::assert_eq_error_rate!(12, 10, 2); +/// # } +/// ``` +/// +/// ```rust,should_panic +/// # fn main() { +/// sr_primitives::assert_eq_error_rate!(12, 10, 1); +/// # } +/// ``` +#[cfg(feature = "std")] +macro_rules! assert_eq_error_rate { + ($x:expr, $y:expr, $error:expr $(,)?) => { + assert!( + ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), + "{:?} != {:?} (with error rate {:?})", + $x, + $y, + $error, + ); + }; +} /// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized /// correctly. #[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] From 17933d1e154f5414b92e86f5244100bd605d5e0e Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 11:58:52 +1300 Subject: [PATCH 41/63] Add documentation to fuzzers --- core/sr-arithmetic/fuzzer/src/biguint.rs | 28 ++++++++++++++++++++ core/sr-arithmetic/fuzzer/src/rational128.rs | 28 ++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index b00a71ca715b6..2ea9c63e4f7e1 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -1,3 +1,31 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Running +//! Running this fuzzer can be done with `cargo hfuzz run biguint`. `honggfuzz` CLI options can +//! be used by setting `HFUZZ_RUN_ARGS`, such as `-n 4` to use 4 threads. +//! +//! # Debugging a panic +//! Once a panic is found, it can be debugged with +//! `cargo hfuzz run-debug biguint hfuzz_workspace/biguint/*.fuzz`. +//! +//! # More infomation +//! More information about `honggfuzz` can be found +//! [here](https://docs.rs/honggfuzz/0.5.45/honggfuzz/). + use honggfuzz::fuzz; use sr_arithmetic::biguint::{BigUint, Single}; use std::convert::TryFrom; diff --git a/core/sr-arithmetic/fuzzer/src/rational128.rs b/core/sr-arithmetic/fuzzer/src/rational128.rs index c67cf4826d0a7..1457d62d861d1 100644 --- a/core/sr-arithmetic/fuzzer/src/rational128.rs +++ b/core/sr-arithmetic/fuzzer/src/rational128.rs @@ -1,3 +1,31 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . + +//! # Running +//! Running this fuzzer can be done with `cargo hfuzz run rational128`. `honggfuzz` CLI options can +//! be used by setting `HFUZZ_RUN_ARGS`, such as `-n 4` to use 4 threads. +//! +//! # Debugging a panic +//! Once a panic is found, it can be debugged with +//! `cargo hfuzz run-debug rational128 hfuzz_workspace/rational128/*.fuzz`. +//! +//! # More infomation +//! More information about `honggfuzz` can be found +//! [here](https://docs.rs/honggfuzz/0.5.45/honggfuzz/). + use honggfuzz::fuzz; use sr_arithmetic::{helpers_128bit::multiply_by_rational, traits::Zero}; From 7c80be9e8958f55531836611ea112d56fffe3a81 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 12:01:18 +1300 Subject: [PATCH 42/63] fix sr-primitives assert_eq_error_rate --- core/sr-primitives/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/sr-primitives/src/lib.rs b/core/sr-primitives/src/lib.rs index 9ec8fed2e37d7..590b6fedd7f04 100644 --- a/core/sr-primitives/src/lib.rs +++ b/core/sr-primitives/src/lib.rs @@ -545,6 +545,7 @@ macro_rules! impl_outer_config { /// sr_primitives::assert_eq_error_rate!(12, 10, 1); /// # } /// ``` +#[macro_export] #[cfg(feature = "std")] macro_rules! assert_eq_error_rate { ($x:expr, $y:expr, $error:expr $(,)?) => { @@ -557,6 +558,7 @@ macro_rules! assert_eq_error_rate { ); }; } + /// Simple blob to hold an extrinsic without committing to its format and ensure it is serialized /// correctly. #[derive(PartialEq, Eq, Clone, Default, Encode, Decode)] From c5616c2613e88d8ee793866549b6ef40c3d13403 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 17:35:39 +1300 Subject: [PATCH 43/63] add cfg(test) --- core/sr-arithmetic/src/per_things.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core/sr-arithmetic/src/per_things.rs b/core/sr-arithmetic/src/per_things.rs index 8252d64aeb96a..4517f6f68c001 100644 --- a/core/sr-arithmetic/src/per_things.rs +++ b/core/sr-arithmetic/src/per_things.rs @@ -8,6 +8,7 @@ use crate::traits::{SaturatedConversion, UniqueSaturatedInto, Saturating}; /// Copied from `sr-primitives` and documented there. #[cfg(feature = "std")] +#[cfg(test)] macro_rules! assert_eq_error_rate { ($x:expr, $y:expr, $error:expr $(,)?) => { assert!( From c0827926a9e0db9a7d8423315c04b69b628cd230 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 09:48:17 +0100 Subject: [PATCH 44/63] Update core/sr-arithmetic/src/traits.rs Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- core/sr-arithmetic/src/traits.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/core/sr-arithmetic/src/traits.rs b/core/sr-arithmetic/src/traits.rs index 2a4e972eb7af7..4196c31600196 100644 --- a/core/sr-arithmetic/src/traits.rs +++ b/core/sr-arithmetic/src/traits.rs @@ -18,7 +18,6 @@ use rstd::prelude::*; use rstd::{self, convert::{TryFrom, TryInto}}; -//use crate::codec::{Codec, Encode, Decode, HasCompact}; //use crate::generic::{Digest, DigestItem}; //use crate::weights::DispatchInfo; use codec::HasCompact; From 7878cec5f9a5ee1d706bc386dd9e94af8f97ab25 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 09:49:35 +0100 Subject: [PATCH 45/63] Update core/sr-arithmetic/src/traits.rs Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- core/sr-arithmetic/src/traits.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/core/sr-arithmetic/src/traits.rs b/core/sr-arithmetic/src/traits.rs index 4196c31600196..0634fa6e2e8ad 100644 --- a/core/sr-arithmetic/src/traits.rs +++ b/core/sr-arithmetic/src/traits.rs @@ -18,7 +18,6 @@ use rstd::prelude::*; use rstd::{self, convert::{TryFrom, TryInto}}; -//use crate::generic::{Digest, DigestItem}; //use crate::weights::DispatchInfo; use codec::HasCompact; pub use integer_sqrt::IntegerSquareRoot; From 5387c96b90fb8a0e22c4eb3441d0a64914abb7ec Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 14:00:28 +0100 Subject: [PATCH 46/63] Update core/sr-arithmetic/fuzzer/src/biguint.rs Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- core/sr-arithmetic/fuzzer/src/biguint.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 2ea9c63e4f7e1..ee291efac7aa5 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -156,7 +156,7 @@ fn main() { let w = u.clone().div_unit(v.get(0)); let num_w = num_u.clone() / &num_v; assert_biguints_eq(&w, &num_w); - } else { + } else if u.len() > v.len() { let w = u.clone().div(&v, rem).map(|(w, _)| w); let num_w = num_u.clone().checked_div(&num_v); @@ -205,4 +205,4 @@ fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) { let b_iter = b.as_slice().iter().rev(); assert!(a_iter.eq(b_iter), "arithmetic: {:?}\nnum-bigint: {:?}", a, b); -} \ No newline at end of file +} From 98cdb31b79ad145aa98bc8e62cd11e8b237aeaf2 Mon Sep 17 00:00:00 2001 From: Ashley Date: Wed, 16 Oct 2019 02:01:24 +1300 Subject: [PATCH 47/63] Allow rounding up in rational128 --- core/sr-arithmetic/fuzzer/src/rational128.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/src/rational128.rs b/core/sr-arithmetic/fuzzer/src/rational128.rs index 1457d62d861d1..5f6b10918744a 100644 --- a/core/sr-arithmetic/fuzzer/src/rational128.rs +++ b/core/sr-arithmetic/fuzzer/src/rational128.rs @@ -43,11 +43,12 @@ fn main() { let truth = mul_div(a, b, c); // if Err just use the truth value. We don't care about such cases. The point of this - // fuzzing is to make sure: if `multiply_by_rational` returns `Ok`, it must be 100% accurate - // returning `Err` is fine. + // fuzzing is to make sure that `multiply_by_rational` is 100% accurate as long as the + // value fits in a u128. let result = multiply_by_rational(a, b, c).unwrap_or(truth); - if truth != result { + // `multiply_by_rational` rounds up, so we need to allow both cases. + if !(truth == result || truth == result - 1) { println!("++ Expected {}", truth); println!("+++++++ Got {}", result); panic!(); From 3ac8b871ab1bf91478e1c9aa17fe466d72b85cf2 Mon Sep 17 00:00:00 2001 From: Ashley Date: Wed, 16 Oct 2019 02:30:56 +1300 Subject: [PATCH 48/63] Make changes to biguint.rs --- core/sr-arithmetic/fuzzer/src/biguint.rs | 112 +++++++++-------------- 1 file changed, 42 insertions(+), 70 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index ee291efac7aa5..9fb5f993ce973 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -29,35 +29,45 @@ use honggfuzz::fuzz; use sr_arithmetic::biguint::{BigUint, Single}; use std::convert::TryFrom; -use num_traits::ops::checked::CheckedDiv; type S = u128; fn main() { loop { fuzz!(|data: (Vec, Vec, bool)| { - let (mut digits_u, mut digits_v, rem) = data; + let (mut digits_u, mut digits_v, return_remainder) = data; - run_with_data_set(4, &digits_u, &digits_v, |u, v| { - let ue = S::try_from(u.clone()).unwrap(); - let ve = S::try_from(v.clone()).unwrap(); + let mut u = BigUint::from_limbs(&digits_u); + let mut v = BigUint::from_limbs(&digits_v); + + u.lstrip(); + v.lstrip(); + + let ue = S::try_from(u.clone()); + let ve = S::try_from(v.clone()); + + digits_u.reverse(); + digits_v.reverse(); + + let num_u = num_bigint::BigUint::new(digits_u.clone()); + let num_v = num_bigint::BigUint::new(digits_v.clone()); + + if check_digit_lengths(&u, &v, 4) { assert_eq!(u.cmp(&v), ue.cmp(&ve)); assert_eq!(u.eq(&v), ue.eq(&ve)); - }); + } - run_with_data_set(3, &digits_u, &digits_v, |u, v| { - let expected = S::try_from(u.clone()).unwrap() + S::try_from(v.clone()).unwrap(); + if check_digit_lengths(&u, &v, 3) { + let expected = ue.unwrap() + ve.unwrap(); let t = u.clone().add(&v); assert_eq!( S::try_from(t.clone()).unwrap(), expected, "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, ); - }); + } - run_with_data_set(4, &digits_u, &digits_v, |u, v| { - let expected = S::try_from(u.clone()) - .unwrap() - .checked_sub(S::try_from(v.clone()).unwrap()); + if check_digit_lengths(&u, &v, 4) { + let expected = ue.unwrap().checked_sub(ve.unwrap()); let t = u.clone().sub(&v); if expected.is_none() { assert!(t.is_err()) @@ -69,20 +79,19 @@ fn main() { "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, ); } - }); + } - run_with_data_set(2, &digits_u, &digits_v, |u, v| { - let expected = S::try_from(u.clone()).unwrap() * S::try_from(v.clone()).unwrap(); + if check_digit_lengths(&u, &v, 2) { + let expected = ue.unwrap() * ve.unwrap(); let t = u.clone().mul(&v); assert_eq!( S::try_from(t.clone()).unwrap(), expected, "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, ); - }); + } - run_with_data_set(4, &digits_u, &digits_v, |u, v| { - let ue = S::try_from(u.clone()).unwrap(); - let ve = S::try_from(v.clone()).unwrap(); + if check_digit_lengths(&u, &v, 4) { + let (ue, ve) = (ue.unwrap(), ve.unwrap()); if ve == 0 { return; } @@ -105,28 +114,13 @@ fn main() { } else if v.msb() != 0 && u.msb() != 0 && u.len() > v.len() { panic!("div returned none for an unexpected reason"); } - }); + } // Test against num_bigint - let u = BigUint::from_limbs(&digits_u); - let v = BigUint::from_limbs(&digits_v); - - digits_u.reverse(); - digits_v.reverse(); - - let num_u = num_bigint::BigUint::new(digits_u.clone()); - let num_v = num_bigint::BigUint::new(digits_v.clone()); - // Equality - assert_biguints_eq(&u, &num_u); - assert_biguints_eq(&v, &num_v); - - if digits_u == digits_v { - assert_eq!(u, v); - assert_eq!(num_u, num_v); - } + assert_eq!(u.cmp(&v), num_u.cmp(&num_v)); // Addition @@ -156,46 +150,24 @@ fn main() { let w = u.clone().div_unit(v.get(0)); let num_w = num_u.clone() / &num_v; assert_biguints_eq(&w, &num_w); - } else if u.len() > v.len() { - let w = u.clone().div(&v, rem).map(|(w, _)| w); - let num_w = num_u.clone().checked_div(&num_v); + } else if u.len() > v.len() && v.len() > 0 { + let num_remainder = num_u.clone() % num_v.clone(); - // assert that the division was checked equally: - // assert_eq!(w.is_some(), num_w.is_some()); + let (w, remainder) = u.clone().div(&v, return_remainder).unwrap(); + let num_w = num_u.clone() / &num_v; - if let Some(w) = w { - assert_biguints_eq(&w, &num_w.unwrap()); + assert_biguints_eq(&w, &num_w); + + if return_remainder { + assert_biguints_eq(&remainder, &num_remainder); } } }); } } -fn run_with_data_set( - max_limbs: usize, - digits_u: &[Single], digits_v: &[Single], - assertion: F, -) - where - F: Fn(BigUint, BigUint) -> (), -{ - // Ensure that `1 <= num_digits < max_limbs`. - let valid = value_between(digits_u.len(), 1, max_limbs) && - value_between(digits_v.len(), 1, max_limbs); - if !valid { - return; - } - - let u = BigUint::from_limbs(digits_u); - let v = BigUint::from_limbs(digits_v); - // this is easier than using lldb - // println!("u: {:?}, v: {:?}", u, v); - - assertion(u, v) -} - -fn value_between(value: usize, min: usize, max: usize) -> bool { - min <= value && value <= max +fn check_digit_lengths(u: &BigUint, v: &BigUint, max_limbs: usize) -> bool { + 1 <= u.len() && u.len() <= max_limbs && 1 <= v.len() && v.len() <= max_limbs } fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) { @@ -204,5 +176,5 @@ fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) { // the `num-bigint` `BigUint` is little endian whereas our `BigUint` is big endian. let b_iter = b.as_slice().iter().rev(); - assert!(a_iter.eq(b_iter), "arithmetic: {:?}\nnum-bigint: {:?}", a, b); + assert!(a_iter.eq(b_iter), "\narithmetic: {:?}\nnum-bigint: {:?}", a, b); } From 41cfa3a01e9a628a43293b37682dfa1c03fe8f15 Mon Sep 17 00:00:00 2001 From: Ashley Date: Tue, 15 Oct 2019 19:02:46 +0100 Subject: [PATCH 49/63] Update core/sr-arithmetic/src/traits.rs Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com> --- core/sr-arithmetic/src/traits.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/core/sr-arithmetic/src/traits.rs b/core/sr-arithmetic/src/traits.rs index 0634fa6e2e8ad..fac89376cb890 100644 --- a/core/sr-arithmetic/src/traits.rs +++ b/core/sr-arithmetic/src/traits.rs @@ -18,7 +18,6 @@ use rstd::prelude::*; use rstd::{self, convert::{TryFrom, TryInto}}; -//use crate::weights::DispatchInfo; use codec::HasCompact; pub use integer_sqrt::IntegerSquareRoot; pub use num_traits::{ From 99099c9109a1cd0caa5c298916425f987269d462 Mon Sep 17 00:00:00 2001 From: Ashley Date: Wed, 16 Oct 2019 07:06:13 +1300 Subject: [PATCH 50/63] Final touches --- core/sr-arithmetic/fuzzer/Cargo.toml | 2 +- core/sr-arithmetic/src/per_things.rs | 15 +++++++++++++++ node/runtime/src/lib.rs | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml index 149ab2764919a..fac0b3b92918c 100644 --- a/core/sr-arithmetic/fuzzer/Cargo.toml +++ b/core/sr-arithmetic/fuzzer/Cargo.toml @@ -9,7 +9,7 @@ honggfuzz = "0.5" sr-arithmetic = { path = ".." } primitive-types = "0.6" num-bigint = { git = "https://github.com/expenses/num-bigint", branch = "as-slice" } -num-traits = "*" +num-traits = "0.2.8" [[bin]] name = "biguint" diff --git a/core/sr-arithmetic/src/per_things.rs b/core/sr-arithmetic/src/per_things.rs index 4517f6f68c001..f6be88a1f93e3 100644 --- a/core/sr-arithmetic/src/per_things.rs +++ b/core/sr-arithmetic/src/per_things.rs @@ -1,3 +1,18 @@ +// Copyright 2019 Parity Technologies (UK) Ltd. +// This file is part of Substrate. + +// Substrate is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Substrate is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Substrate. If not, see . #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index d594014092b14..d8fc9a1a5784a 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -84,7 +84,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to equal spec_version. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 176, + spec_version: 175, impl_version: 176, apis: RUNTIME_API_VERSIONS, }; From e32f8875f917b03b5133cb9c36e0355c0c3989bc Mon Sep 17 00:00:00 2001 From: Ashley Date: Wed, 16 Oct 2019 07:19:15 +1300 Subject: [PATCH 51/63] Convert to num_bigint::BigUint to compare --- Cargo.lock | 13 +------------ core/sr-arithmetic/fuzzer/Cargo.toml | 2 +- core/sr-arithmetic/fuzzer/src/biguint.rs | 11 ++++++----- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dea9ea42d3826..cb841d22d9d3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2653,16 +2653,6 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-bigint" -version = "0.2.3" -source = "git+https://github.com/expenses/num-bigint?branch=as-slice#66cbc96158015d498340365012ec7d3b7bd3f052" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num-bigint" version = "0.2.3" @@ -3891,7 +3881,7 @@ name = "sr-arithmetic-fuzzer" version = "2.0.0" dependencies = [ "honggfuzz 0.5.45 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.3 (git+https://github.com/expenses/num-bigint?branch=as-slice)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "primitive-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "sr-arithmetic 2.0.0", @@ -6929,7 +6919,6 @@ dependencies = [ "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum nohash-hasher 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4e657a6ec97f9a3ba46f6f7034ea6db9fcd5b71d25ef1074b7bc03da49be0e8e" "checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" -"checksum num-bigint 0.2.3 (git+https://github.com/expenses/num-bigint?branch=as-slice)" = "" "checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" diff --git a/core/sr-arithmetic/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml index fac0b3b92918c..345c0aa4d90fa 100644 --- a/core/sr-arithmetic/fuzzer/Cargo.toml +++ b/core/sr-arithmetic/fuzzer/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" honggfuzz = "0.5" sr-arithmetic = { path = ".." } primitive-types = "0.6" -num-bigint = { git = "https://github.com/expenses/num-bigint", branch = "as-slice" } +num-bigint = "0.2.3" num-traits = "0.2.8" [[bin]] diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 9fb5f993ce973..6173e0ca44f75 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -171,10 +171,11 @@ fn check_digit_lengths(u: &BigUint, v: &BigUint, max_limbs: usize) -> bool { } fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) { - // `BigUint` doesn't check the input in `from_limbs` so we skip any leading 0s. - let a_iter = a.as_slice().iter().skip_while(|&&i| i == 0); - // the `num-bigint` `BigUint` is little endian whereas our `BigUint` is big endian. - let b_iter = b.as_slice().iter().rev(); + // `num_bigint::BigUint` doesn't expose it's internals, so we need to convert into that to + // compare. It is little endian while our `BigUint` is big endian so we need to reverse the + // limbs. + let mut limbs = a.as_slice().iter().rev().cloned().collect(); + let num_a = num_bigint::BigUint::new(limbs); - assert!(a_iter.eq(b_iter), "\narithmetic: {:?}\nnum-bigint: {:?}", a, b); + assert!(&num_a == b, "\narithmetic: {:?}\nnum-bigint: {:?}", a, b); } From 883272c215e9ae743a0da9e1456908c9befa14e1 Mon Sep 17 00:00:00 2001 From: Ashley Date: Wed, 16 Oct 2019 07:23:04 +1300 Subject: [PATCH 52/63] remove unused mut --- core/sr-arithmetic/fuzzer/src/biguint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 6173e0ca44f75..d72103a2d05b2 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -174,7 +174,7 @@ fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) { // `num_bigint::BigUint` doesn't expose it's internals, so we need to convert into that to // compare. It is little endian while our `BigUint` is big endian so we need to reverse the // limbs. - let mut limbs = a.as_slice().iter().rev().cloned().collect(); + let limbs = a.as_slice().iter().rev().cloned().collect(); let num_a = num_bigint::BigUint::new(limbs); assert!(&num_a == b, "\narithmetic: {:?}\nnum-bigint: {:?}", a, b); From 1209939c7fe6910a6f90fe325014807af0258881 Mon Sep 17 00:00:00 2001 From: Ashley Date: Wed, 16 Oct 2019 08:47:58 +1300 Subject: [PATCH 53/63] more small changes --- core/sr-arithmetic/fuzzer/Cargo.toml | 6 +- core/sr-arithmetic/fuzzer/src/biguint.rs | 8 +- core/sr-arithmetic/fuzzer/src/rational128.rs | 2 +- core/sr-arithmetic/src/biguint.rs | 4 - core/sr-arithmetic/src/traits.rs | 94 -------------------- core/sr-primitives/src/traits.rs | 72 ++++++++++++++- 6 files changed, 79 insertions(+), 107 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/Cargo.toml b/core/sr-arithmetic/fuzzer/Cargo.toml index 345c0aa4d90fa..8838e60436f4a 100644 --- a/core/sr-arithmetic/fuzzer/Cargo.toml +++ b/core/sr-arithmetic/fuzzer/Cargo.toml @@ -5,11 +5,11 @@ authors = ["Parity Technologies "] edition = "2018" [dependencies] -honggfuzz = "0.5" sr-arithmetic = { path = ".." } +honggfuzz = "0.5" primitive-types = "0.6" -num-bigint = "0.2.3" -num-traits = "0.2.8" +num-bigint = "0.2" +num-traits = "0.2" [[bin]] name = "biguint" diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index d72103a2d05b2..22e1bbcad9beb 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -171,10 +171,12 @@ fn check_digit_lengths(u: &BigUint, v: &BigUint, max_limbs: usize) -> bool { } fn assert_biguints_eq(a: &BigUint, b: &num_bigint::BigUint) { + let mut a = a.clone(); + a.lstrip(); + // `num_bigint::BigUint` doesn't expose it's internals, so we need to convert into that to - // compare. It is little endian while our `BigUint` is big endian so we need to reverse the - // limbs. - let limbs = a.as_slice().iter().rev().cloned().collect(); + // compare. + let limbs = (0 .. a.len()).map(|i| a.get(i)).collect(); let num_a = num_bigint::BigUint::new(limbs); assert!(&num_a == b, "\narithmetic: {:?}\nnum-bigint: {:?}", a, b); diff --git a/core/sr-arithmetic/fuzzer/src/rational128.rs b/core/sr-arithmetic/fuzzer/src/rational128.rs index 5f6b10918744a..c0acf12a150b0 100644 --- a/core/sr-arithmetic/fuzzer/src/rational128.rs +++ b/core/sr-arithmetic/fuzzer/src/rational128.rs @@ -47,7 +47,7 @@ fn main() { // value fits in a u128. let result = multiply_by_rational(a, b, c).unwrap_or(truth); - // `multiply_by_rational` rounds up, so we need to allow both cases. + // `multiply_by_rational` rounds the value, so we need to allow both cases. if !(truth == result || truth == result - 1) { println!("++ Expected {}", truth); println!("+++++++ Got {}", result); diff --git a/core/sr-arithmetic/src/biguint.rs b/core/sr-arithmetic/src/biguint.rs index 7bb38d32fec97..9c426d309209a 100644 --- a/core/sr-arithmetic/src/biguint.rs +++ b/core/sr-arithmetic/src/biguint.rs @@ -97,10 +97,6 @@ impl BigUint { } } - pub fn as_slice(&self) -> &[Single] { - &self.digits - } - /// Number of limbs. pub fn len(&self) -> usize { self.digits.len() } diff --git a/core/sr-arithmetic/src/traits.rs b/core/sr-arithmetic/src/traits.rs index fac89376cb890..d02425066ff9d 100644 --- a/core/sr-arithmetic/src/traits.rs +++ b/core/sr-arithmetic/src/traits.rs @@ -16,7 +16,6 @@ //! Primitives for the runtime modules. -use rstd::prelude::*; use rstd::{self, convert::{TryFrom, TryInto}}; use codec::HasCompact; pub use integer_sqrt::IntegerSquareRoot; @@ -142,96 +141,3 @@ pub trait SaturatedConversion { } } impl SaturatedConversion for T {} - -/// Convenience type to work around the highly unergonomic syntax needed -/// to invoke the functions of overloaded generic traits, in this case -/// `TryFrom` and `TryInto`. -pub trait CheckedConversion { - /// Convert from a value of `T` into an equivalent instance of `Option`. - /// - /// This just uses `TryFrom` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn checked_from(t: T) -> Option where Self: TryFrom { - >::try_from(t).ok() - } - /// Consume self to return `Some` equivalent value of `Option`. - /// - /// This just uses `TryInto` internally but with this - /// variant you can provide the destination type using turbofish syntax - /// in case Rust happens not to assume the correct type. - fn checked_into(self) -> Option where Self: TryInto { - >::try_into(self).ok() - } -} -impl CheckedConversion for T {} - -/// Multiply and divide by a number that isn't necessarily the same type. Basically just the same -/// as `Mul` and `Div` except it can be used for all basic numeric types. -pub trait Scale { - /// The output type of the product of `self` and `Other`. - type Output; - - /// @return the product of `self` and `other`. - fn mul(self, other: Other) -> Self::Output; - - /// @return the integer division of `self` and `other`. - fn div(self, other: Other) -> Self::Output; - - /// @return the modulo remainder of `self` and `other`. - fn rem(self, other: Other) -> Self::Output; -} -macro_rules! impl_scale { - ($self:ty, $other:ty) => { - impl Scale<$other> for $self { - type Output = Self; - fn mul(self, other: $other) -> Self::Output { self * (other as Self) } - fn div(self, other: $other) -> Self::Output { self / (other as Self) } - fn rem(self, other: $other) -> Self::Output { self % (other as Self) } - } - } -} -impl_scale!(u128, u128); -impl_scale!(u128, u64); -impl_scale!(u128, u32); -impl_scale!(u128, u16); -impl_scale!(u128, u8); -impl_scale!(u64, u64); -impl_scale!(u64, u32); -impl_scale!(u64, u16); -impl_scale!(u64, u8); -impl_scale!(u32, u32); -impl_scale!(u32, u16); -impl_scale!(u32, u8); -impl_scale!(u16, u16); -impl_scale!(u16, u8); -impl_scale!(u8, u8); - -/// Trait for things that can be clear (have no bits set). For numeric types, essentially the same -/// as `Zero`. -pub trait Clear { - /// True iff no bits are set. - fn is_clear(&self) -> bool; - - /// Return the value of Self that is clear. - fn clear() -> Self; -} - -impl Clear for T { - fn is_clear(&self) -> bool { *self == Self::clear() } - fn clear() -> Self { Default::default() } -} - -/// A meta trait for all bit ops. -pub trait SimpleBitOps: - Sized + Clear + - rstd::ops::BitOr + - rstd::ops::BitXor + - rstd::ops::BitAnd -{} -impl + - rstd::ops::BitXor + - rstd::ops::BitAnd -> SimpleBitOps for T {} diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index 0c1a30e315d6f..ce24fc8593737 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -17,7 +17,7 @@ //! Primitives for the runtime modules. use rstd::prelude::*; -use rstd::{self, result, marker::PhantomData}; +use rstd::{self, result, marker::PhantomData, convert::{TryFrom, TryInto}}; use runtime_io; #[cfg(feature = "std")] use std::fmt::{Debug, Display}; @@ -28,7 +28,11 @@ use crate::codec::{Codec, Encode, Decode}; use crate::transaction_validity::{ ValidTransaction, TransactionValidity, TransactionValidityError, UnknownTransaction, }; -pub use arithmetic::traits::*; +pub use arithmetic::traits::{ + SimpleArithmetic, UniqueSaturatedInto, UniqueSaturatedFrom, Saturating, SaturatedConversion, + Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, + CheckedShl, CheckedShr, IntegerSquareRoot +}; use crate::generic::{Digest, DigestItem}; use crate::weights::DispatchInfo; use app_crypto::AppKey; @@ -190,6 +194,70 @@ impl> Convert for ConvertInto { fn convert(a: A) -> B { a.into() } } +/// Convenience type to work around the highly unergonomic syntax needed +/// to invoke the functions of overloaded generic traits, in this case +/// `TryFrom` and `TryInto`. +pub trait CheckedConversion { + /// Convert from a value of `T` into an equivalent instance of `Option`. + /// + /// This just uses `TryFrom` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn checked_from(t: T) -> Option where Self: TryFrom { + >::try_from(t).ok() + } + /// Consume self to return `Some` equivalent value of `Option`. + /// + /// This just uses `TryInto` internally but with this + /// variant you can provide the destination type using turbofish syntax + /// in case Rust happens not to assume the correct type. + fn checked_into(self) -> Option where Self: TryInto { + >::try_into(self).ok() + } +} +impl CheckedConversion for T {} + +/// Multiply and divide by a number that isn't necessarily the same type. Basically just the same +/// as `Mul` and `Div` except it can be used for all basic numeric types. +pub trait Scale { + /// The output type of the product of `self` and `Other`. + type Output; + + /// @return the product of `self` and `other`. + fn mul(self, other: Other) -> Self::Output; + + /// @return the integer division of `self` and `other`. + fn div(self, other: Other) -> Self::Output; + + /// @return the modulo remainder of `self` and `other`. + fn rem(self, other: Other) -> Self::Output; +} +macro_rules! impl_scale { + ($self:ty, $other:ty) => { + impl Scale<$other> for $self { + type Output = Self; + fn mul(self, other: $other) -> Self::Output { self * (other as Self) } + fn div(self, other: $other) -> Self::Output { self / (other as Self) } + fn rem(self, other: $other) -> Self::Output { self % (other as Self) } + } + } +} +impl_scale!(u128, u128); +impl_scale!(u128, u64); +impl_scale!(u128, u32); +impl_scale!(u128, u16); +impl_scale!(u128, u8); +impl_scale!(u64, u64); +impl_scale!(u64, u32); +impl_scale!(u64, u16); +impl_scale!(u64, u8); +impl_scale!(u32, u32); +impl_scale!(u32, u16); +impl_scale!(u32, u8); +impl_scale!(u16, u16); +impl_scale!(u16, u8); +impl_scale!(u8, u8); + /// Trait for things that can be clear (have no bits set). For numeric types, essentially the same /// as `Zero`. pub trait Clear { From 7202e2dd41b64f72aca21ef6278a72cc667e4fff Mon Sep 17 00:00:00 2001 From: Ashley Date: Wed, 16 Oct 2019 08:50:45 +1300 Subject: [PATCH 54/63] shuffle sr-primitives trait imports --- core/sr-primitives/src/traits.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sr-primitives/src/traits.rs b/core/sr-primitives/src/traits.rs index ce24fc8593737..71de5eb558100 100644 --- a/core/sr-primitives/src/traits.rs +++ b/core/sr-primitives/src/traits.rs @@ -28,13 +28,13 @@ use crate::codec::{Codec, Encode, Decode}; use crate::transaction_validity::{ ValidTransaction, TransactionValidity, TransactionValidityError, UnknownTransaction, }; +use crate::generic::{Digest, DigestItem}; +use crate::weights::DispatchInfo; pub use arithmetic::traits::{ SimpleArithmetic, UniqueSaturatedInto, UniqueSaturatedFrom, Saturating, SaturatedConversion, Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedShl, CheckedShr, IntegerSquareRoot }; -use crate::generic::{Digest, DigestItem}; -use crate::weights::DispatchInfo; use app_crypto::AppKey; use impl_trait_for_tuples::impl_for_tuples; From 1cadf86c5706e5a8deefb93c81591ecebe595be6 Mon Sep 17 00:00:00 2001 From: Ashley Date: Wed, 16 Oct 2019 09:35:07 +1300 Subject: [PATCH 55/63] more code review --- core/sr-primitives/src/curve.rs | 2 +- core/sr-primitives/src/generic/header.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/core/sr-primitives/src/curve.rs b/core/sr-primitives/src/curve.rs index e6c75a18a635e..dc6316bd470c7 100644 --- a/core/sr-primitives/src/curve.rs +++ b/core/sr-primitives/src/curve.rs @@ -16,7 +16,7 @@ //! Provides some utilities to define a piecewise linear function. -use arithmetic::{Perbill, traits::{SimpleArithmetic, SaturatedConversion}}; +use crate::{Perbill, traits::{SimpleArithmetic, SaturatedConversion}}; use core::ops::Sub; /// Piecewise Linear function in [0, 1] -> [0, 1]. diff --git a/core/sr-primitives/src/generic/header.rs b/core/sr-primitives/src/generic/header.rs index 5a0726641bf10..e9a8405fe21b0 100644 --- a/core/sr-primitives/src/generic/header.rs +++ b/core/sr-primitives/src/generic/header.rs @@ -21,9 +21,8 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "std")] use log::debug; use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef, Error}; -use arithmetic::traits::SimpleArithmetic; use crate::traits::{ - self, Member, SimpleBitOps, MaybeDisplay, Hash as HashT, MaybeSerializeDebug, + self, Member, SimpleArithmetic, SimpleBitOps, MaybeDisplay, Hash as HashT, MaybeSerializeDebug, MaybeSerializeDebugButNotDeserialize }; use crate::generic::Digest; From 2dd9c31d43dc5d92979052649aa615ae4cccad60 Mon Sep 17 00:00:00 2001 From: Ashley Date: Thu, 17 Oct 2019 18:32:07 +1300 Subject: [PATCH 56/63] move assert_eq_error_rate to lib.rs --- core/sr-arithmetic/src/lib.rs | 14 ++++++++++++++ core/sr-arithmetic/src/per_things.rs | 15 --------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/core/sr-arithmetic/src/lib.rs b/core/sr-arithmetic/src/lib.rs index e95a13eb3f915..847ca9e797cb0 100644 --- a/core/sr-arithmetic/src/lib.rs +++ b/core/sr-arithmetic/src/lib.rs @@ -22,6 +22,20 @@ #![cfg_attr(feature = "bench", feature(test))] #[cfg(feature = "bench")] extern crate test; +/// Copied from `sr-primitives` and documented there. +#[cfg(test)] +macro_rules! assert_eq_error_rate { + ($x:expr, $y:expr, $error:expr $(,)?) => { + assert!( + ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), + "{:?} != {:?} (with error rate {:?})", + $x, + $y, + $error, + ); + }; +} + pub mod biguint; pub mod helpers_128bit; pub mod traits; diff --git a/core/sr-arithmetic/src/per_things.rs b/core/sr-arithmetic/src/per_things.rs index f6be88a1f93e3..8883ad99fcb14 100644 --- a/core/sr-arithmetic/src/per_things.rs +++ b/core/sr-arithmetic/src/per_things.rs @@ -21,21 +21,6 @@ use rstd::{ops, prelude::*, convert::TryInto}; use codec::{Encode, Decode}; use crate::traits::{SaturatedConversion, UniqueSaturatedInto, Saturating}; -/// Copied from `sr-primitives` and documented there. -#[cfg(feature = "std")] -#[cfg(test)] -macro_rules! assert_eq_error_rate { - ($x:expr, $y:expr, $error:expr $(,)?) => { - assert!( - ($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)), - "{:?} != {:?} (with error rate {:?})", - $x, - $y, - $error, - ); - }; -} - macro_rules! implement_per_thing { ($name:ident, $test_mod:ident, [$($test_units:tt),+], $max:tt, $type:ty, $upper_type:ty, $title:expr $(,)?) => { /// A fixed point representation of a number between in the range [0, 1]. From 9a025915f76fb10948b1322ce8d85c055330d320 Mon Sep 17 00:00:00 2001 From: Ashley Date: Thu, 17 Oct 2019 19:55:07 +0100 Subject: [PATCH 57/63] Update core/sr-arithmetic/fuzzer/src/biguint.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Bastian Köcher --- core/sr-arithmetic/fuzzer/src/biguint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 22e1bbcad9beb..bda7156571d17 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -24,7 +24,7 @@ //! //! # More infomation //! More information about `honggfuzz` can be found -//! [here](https://docs.rs/honggfuzz/0.5.45/honggfuzz/). +//! [here](https://docs.rs/honggfuzz/). use honggfuzz::fuzz; use sr_arithmetic::biguint::{BigUint, Single}; From d58d6d3013cc95da1d3b18ed01b1b38594545973 Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 18 Oct 2019 08:04:57 +1300 Subject: [PATCH 58/63] Get rid of S --- core/sr-arithmetic/fuzzer/src/biguint.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/src/biguint.rs b/core/sr-arithmetic/fuzzer/src/biguint.rs index 22e1bbcad9beb..d6d00947d09ff 100644 --- a/core/sr-arithmetic/fuzzer/src/biguint.rs +++ b/core/sr-arithmetic/fuzzer/src/biguint.rs @@ -30,8 +30,6 @@ use honggfuzz::fuzz; use sr_arithmetic::biguint::{BigUint, Single}; use std::convert::TryFrom; -type S = u128; - fn main() { loop { fuzz!(|data: (Vec, Vec, bool)| { @@ -43,8 +41,8 @@ fn main() { u.lstrip(); v.lstrip(); - let ue = S::try_from(u.clone()); - let ve = S::try_from(v.clone()); + let ue = u128::try_from(u.clone()); + let ve = u128::try_from(v.clone()); digits_u.reverse(); digits_v.reverse(); @@ -61,7 +59,7 @@ fn main() { let expected = ue.unwrap() + ve.unwrap(); let t = u.clone().add(&v); assert_eq!( - S::try_from(t.clone()).unwrap(), expected, + u128::try_from(t.clone()).unwrap(), expected, "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, ); } @@ -75,7 +73,7 @@ fn main() { let t = t.unwrap(); let expected = expected.unwrap(); assert_eq!( - S::try_from(t.clone()).unwrap(), expected, + u128::try_from(t.clone()).unwrap(), expected, "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, ); } @@ -85,7 +83,7 @@ fn main() { let expected = ue.unwrap() * ve.unwrap(); let t = u.clone().mul(&v); assert_eq!( - S::try_from(t.clone()).unwrap(), expected, + u128::try_from(t.clone()).unwrap(), expected, "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, ); } @@ -98,17 +96,17 @@ fn main() { let (q, r) = (ue / ve, ue % ve); if let Some((qq, rr)) = u.clone().div(&v, true) { assert_eq!( - S::try_from(qq.clone()).unwrap(), q, + u128::try_from(qq.clone()).unwrap(), q, "{:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, ); assert_eq!( - S::try_from(rr.clone()).unwrap(), r, + u128::try_from(rr.clone()).unwrap(), r, "{:?} % {:?} ===> {:?} != {:?}", u, v, rr, r, ); } else if v.len() == 1 { let qq = u.clone().div_unit(ve as Single); assert_eq!( - S::try_from(qq.clone()).unwrap(), q, + u128::try_from(qq.clone()).unwrap(), q, "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, ); } else if v.msb() != 0 && u.msb() != 0 && u.len() > v.len() { From ab5ec37990250e0f313d6be99259e0dc16bc928e Mon Sep 17 00:00:00 2001 From: Ashley Date: Fri, 18 Oct 2019 08:11:05 +1300 Subject: [PATCH 59/63] Simplify rational128 honggfuzz link --- core/sr-arithmetic/fuzzer/src/rational128.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sr-arithmetic/fuzzer/src/rational128.rs b/core/sr-arithmetic/fuzzer/src/rational128.rs index c0acf12a150b0..d4a86d773ebfd 100644 --- a/core/sr-arithmetic/fuzzer/src/rational128.rs +++ b/core/sr-arithmetic/fuzzer/src/rational128.rs @@ -24,7 +24,7 @@ //! //! # More infomation //! More information about `honggfuzz` can be found -//! [here](https://docs.rs/honggfuzz/0.5.45/honggfuzz/). +//! [here](https://docs.rs/honggfuzz/). use honggfuzz::fuzz; use sr_arithmetic::{helpers_128bit::multiply_by_rational, traits::Zero}; From dcf169cdf2553bfeea20ed9c5c39d765a787d9cf Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 19 Oct 2019 08:42:02 +1300 Subject: [PATCH 60/63] Insignificantly change rational128 fuzzing code --- core/sr-arithmetic/fuzzer/src/rational128.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/core/sr-arithmetic/fuzzer/src/rational128.rs b/core/sr-arithmetic/fuzzer/src/rational128.rs index d4a86d773ebfd..b2a00d754527f 100644 --- a/core/sr-arithmetic/fuzzer/src/rational128.rs +++ b/core/sr-arithmetic/fuzzer/src/rational128.rs @@ -41,17 +41,16 @@ fn main() { println!("++ Equation: {} * {} / {}", a, b, c); - let truth = mul_div(a, b, c); - // if Err just use the truth value. We don't care about such cases. The point of this - // fuzzing is to make sure that `multiply_by_rational` is 100% accurate as long as the - // value fits in a u128. - let result = multiply_by_rational(a, b, c).unwrap_or(truth); + // The point of this fuzzing is to make sure that `multiply_by_rational` is 100% + // accurate as long as the value fits in a u128. + if let Ok(result) = multiply_by_rational(a, b, c) { + let truth = mul_div(a, b, c); - // `multiply_by_rational` rounds the value, so we need to allow both cases. - if !(truth == result || truth == result - 1) { - println!("++ Expected {}", truth); - println!("+++++++ Got {}", result); - panic!(); + if result != truth && result != truth + 1 { + println!("++ Expected {}", truth); + println!("+++++++ Got {}", result); + panic!(); + } } }) } From 900c30547d88e0ebfa63aae1731a21f41fa7d63a Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 19 Oct 2019 08:55:08 +1300 Subject: [PATCH 61/63] Slightly tidy up some of the arithmetic logic --- core/sr-arithmetic/src/biguint.rs | 19 +++++++------------ core/sr-arithmetic/src/fixed64.rs | 12 ++---------- core/sr-arithmetic/src/per_things.rs | 20 ++------------------ 3 files changed, 11 insertions(+), 40 deletions(-) diff --git a/core/sr-arithmetic/src/biguint.rs b/core/sr-arithmetic/src/biguint.rs index 9c426d309209a..931eafd899ea3 100644 --- a/core/sr-arithmetic/src/biguint.rs +++ b/core/sr-arithmetic/src/biguint.rs @@ -111,12 +111,9 @@ impl BigUint { /// A naive getter for limb at `index`. Note that the order is lsb -> msb. pub fn checked_get(&self, index: usize) -> Option { - if let Some(i) = self.len().checked_sub(1) { - if let Some(j) = i.checked_sub(index) { - return self.digits.get(j).cloned(); - } - } - None + let i = self.len().checked_sub(1)?; + let j = i.checked_sub(index)?; + self.digits.get(j).cloned() } /// A naive setter for limb at `index`. Note that the order is lsb -> msb. @@ -147,16 +144,14 @@ impl BigUint { self.digits[0] } - /// Strips zeros from the left side of `self`, if any. + /// Strips zeros from the left side (the most significant limbs) of `self`, if any. pub fn lstrip(&mut self) { // by definition, a big-int number should never have leading zero limbs. This function // has the ability to cause this. There is nothing to do if the number already has 1 // limb only. call it a day and return. if self.len().is_zero() { return; } - let mut index = 0; - for elem in self.digits.iter() { - if *elem != 0 { break } else { index += 1 } - } + let index = self.digits.iter().position(|&elem| elem != 0).unwrap_or(0); + if index > 0 { self.digits = self.digits[index..].to_vec() } @@ -441,7 +436,7 @@ impl rstd::fmt::Debug for BigUint { f, "BigUint {{ {:?} ({:?})}}", self.digits, - u128::try_from(self.clone()).unwrap_or_else(|_| 0), + u128::try_from(self.clone()).unwrap_or(0), ) } } diff --git a/core/sr-arithmetic/src/fixed64.rs b/core/sr-arithmetic/src/fixed64.rs index a5fadeb4679e9..f4096d18133d3 100644 --- a/core/sr-arithmetic/src/fixed64.rs +++ b/core/sr-arithmetic/src/fixed64.rs @@ -135,21 +135,13 @@ impl ops::Sub for Fixed64 { impl CheckedSub for Fixed64 { fn checked_sub(&self, rhs: &Self) -> Option { - if let Some(v) = self.0.checked_sub(rhs.0) { - Some(Self(v)) - } else { - None - } + self.0.checked_sub(rhs.0).map(Self) } } impl CheckedAdd for Fixed64 { fn checked_add(&self, rhs: &Self) -> Option { - if let Some(v) = self.0.checked_add(rhs.0) { - Some(Self(v)) - } else { - None - } + self.0.checked_add(rhs.0).map(Self) } } diff --git a/core/sr-arithmetic/src/per_things.rs b/core/sr-arithmetic/src/per_things.rs index 8883ad99fcb14..afd8100a843e7 100644 --- a/core/sr-arithmetic/src/per_things.rs +++ b/core/sr-arithmetic/src/per_things.rs @@ -18,7 +18,7 @@ use serde::{Serialize, Deserialize}; use rstd::{ops, prelude::*, convert::TryInto}; -use codec::{Encode, Decode}; +use codec::{Encode, Decode, CompactAs}; use crate::traits::{SaturatedConversion, UniqueSaturatedInto, Saturating}; macro_rules! implement_per_thing { @@ -27,7 +27,7 @@ macro_rules! implement_per_thing { /// #[doc = $title] #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Ord, PartialOrd))] - #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq)] + #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, CompactAs)] pub struct $name($type); impl $name { @@ -186,22 +186,6 @@ macro_rules! implement_per_thing { } } - impl codec::CompactAs for $name { - type As = $type; - fn encode_as(&self) -> &$type { - &self.0 - } - fn decode_from(x: $type) -> Self { - Self(x) - } - } - - impl From> for $name { - fn from(x: codec::Compact<$name>) -> Self { - x.0 - } - } - #[cfg(test)] mod $test_mod { use codec::{Encode, Decode}; From 79e4348f06c4f56aca8272b9f5e4c1569fafd554 Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 19 Oct 2019 09:06:00 +1300 Subject: [PATCH 62/63] Get rid of sr_arithmetic again(?) and fix sr-primitives/weights --- core/sr-primitives/src/sr_arithmetic.rs | 2203 ----------------------- core/sr-primitives/src/weights.rs | 7 +- 2 files changed, 2 insertions(+), 2208 deletions(-) delete mode 100644 core/sr-primitives/src/sr_arithmetic.rs diff --git a/core/sr-primitives/src/sr_arithmetic.rs b/core/sr-primitives/src/sr_arithmetic.rs deleted file mode 100644 index 5f5b5dc1e523b..0000000000000 --- a/core/sr-primitives/src/sr_arithmetic.rs +++ /dev/null @@ -1,2203 +0,0 @@ -// Copyright 2019 Parity Technologies (UK) Ltd. -// This file is part of Substrate. - -// Substrate is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Substrate is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Substrate. If not, see . - -//! Minimal fixed point arithmetic primitives and types for runtime. - -#[cfg(feature = "std")] -use crate::serde::{Serialize, Deserialize}; - -use rstd::{ - ops, cmp::Ordering, prelude::*, - convert::{TryFrom, TryInto}, -}; -use codec::{Encode, Decode}; -use crate::traits::{ - SaturatedConversion, CheckedSub, CheckedAdd, Bounded, UniqueSaturatedInto, Saturating, Zero, -}; - -macro_rules! implement_per_thing { - ($name:ident, $test_mod:ident, [$($test_units:tt),+], $max:tt, $type:ty, $upper_type:ty, $title:expr $(,)?) => { - /// A fixed point representation of a number between in the range [0, 1]. - /// - #[doc = $title] - #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Ord, PartialOrd))] - #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq)] - pub struct $name($type); - - impl $name { - /// Nothing. - pub fn zero() -> Self { Self(0) } - - /// `true` if this is nothing. - pub fn is_zero(&self) -> bool { self.0 == 0 } - - /// Everything. - pub fn one() -> Self { Self($max) } - - /// Consume self and deconstruct into a raw numeric type. - pub fn deconstruct(self) -> $type { self.0 } - - /// Return the scale at which this per-thing is working. - pub const fn accuracy() -> $type { $max } - - /// From an explicitly defined number of parts per maximum of the type. - /// - /// This can be called at compile time. - pub const fn from_parts(parts: $type) -> Self { - Self([parts, $max][(parts > $max) as usize]) - } - - /// Converts from a percent. Equal to `x / 100`. - /// - /// This can be created at compile time. - pub const fn from_percent(x: $type) -> Self { - Self([x, 100][(x > 100) as usize] * ($max / 100)) - } - - /// Return the product of multiplication of this value by itself. - pub fn square(self) -> Self { - // both can be safely casted and multiplied. - let p: $upper_type = self.0 as $upper_type * self.0 as $upper_type; - let q: $upper_type = $max as $upper_type * $max as $upper_type; - Self::from_rational_approximation(p, q) - } - - /// Converts a fraction into `Permill`. - #[cfg(feature = "std")] - pub fn from_fraction(x: f64) -> Self { Self((x * ($max as f64)) as $type) } - - /// Approximate the fraction `p/q` into a per-thing fraction. This will never overflow. - /// - /// The computation of this approximation is performed in the generic type `N`. Given - /// `M` as the data type that can hold the maximum value of this per-thing (e.g. u32 for - /// perbill), this can only work if `N == M` or `N: From + TryInto`. - pub fn from_rational_approximation(p: N, q: N) -> Self - where N: Clone + Ord + From<$type> + TryInto<$type> + ops::Div - { - // q cannot be zero. - let q = q.max((1 as $type).into()); - // p should not be bigger than q. - let p = p.min(q.clone()); - - let factor = (q.clone() / $max.into()).max((1 as $type).into()); - - // q cannot overflow: (q / (q/$max)) < 2 * $max. p < q hence p also cannot overflow. - // this implies that $type must be able to fit 2 * $max. - let q_reduce: $type = (q / factor.clone()) - .try_into() - .map_err(|_| "Failed to convert") - .expect( - "q / (q/$max) < (2 * $max). Macro prevents any type being created that \ - does not satisfy this; qed" - ); - let p_reduce: $type = (p / factor.clone()) - .try_into() - .map_err(|_| "Failed to convert") - .expect( - "q / (q/$max) < (2 * $max). Macro prevents any type being created that \ - does not satisfy this; qed" - ); - - // `p_reduced` and `q_reduced` are withing $type. Mul by another $max will always - // fit in $upper_type. This is guaranteed by the macro tests. - let part = - p_reduce as $upper_type - * ($max as $upper_type) - / q_reduce as $upper_type; - - $name(part as $type) - } - } - - impl Saturating for $name { - fn saturating_add(self, rhs: Self) -> Self { - // defensive-only: since `$max * 2 < $type::max_value()`, this can never overflow. - Self::from_parts(self.0.saturating_add(rhs.0)) - } - fn saturating_sub(self, rhs: Self) -> Self { - Self::from_parts(self.0.saturating_sub(rhs.0)) - } - fn saturating_mul(self, rhs: Self) -> Self { - let a = self.0 as $upper_type; - let b = rhs.0 as $upper_type; - let m = $max as $upper_type; - let parts = a * b / m; - // This will always fit into $type. - Self::from_parts(parts as $type) - } - } - - impl ops::Div for $name { - type Output = Self; - - fn div(self, rhs: Self) -> Self::Output { - let p = self.0; - let q = rhs.0; - Self::from_rational_approximation(p, q) - } - } - - /// Overflow-prune multiplication. - /// - /// tailored to be used with a balance type. - impl ops::Mul for $name - where - N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem - + ops::Div + ops::Mul + ops::Add, - { - type Output = N; - fn mul(self, b: N) -> Self::Output { - let maximum: N = $max.into(); - let upper_max: $upper_type = $max.into(); - let part: N = self.0.into(); - - let rem_multiplied_divided = { - let rem = b.clone().rem(maximum.clone()); - - // `rem_sized` is inferior to $max, thus it fits into $type. This is assured by - // a test. - let rem_sized = rem.saturated_into::<$type>(); - - // `self` and `rem_sized` are inferior to $max, thus the product is less than - // $max^2 and fits into $upper_type. This is assured by a test. - let rem_multiplied_upper = rem_sized as $upper_type * self.0 as $upper_type; - - // `rem_multiplied_upper` is less than $max^2 therefore divided by $max it fits - // in $type. remember that $type always fits $max. - let mut rem_multiplied_divided_sized = - (rem_multiplied_upper / upper_max) as $type; - // fix a tiny rounding error - if rem_multiplied_upper % upper_max > upper_max / 2 { - rem_multiplied_divided_sized += 1; - } - - // `rem_multiplied_divided_sized` is inferior to b, thus it can be converted - // back to N type - rem_multiplied_divided_sized.into() - }; - - (b / maximum) * part + rem_multiplied_divided - } - } - - impl codec::CompactAs for $name { - type As = $type; - fn encode_as(&self) -> &$type { - &self.0 - } - fn decode_from(x: $type) -> Self { - Self(x) - } - } - - impl From> for $name { - fn from(x: codec::Compact<$name>) -> Self { - x.0 - } - } - - #[cfg(test)] - mod $test_mod { - use codec::{Encode, Decode}; - use super::{$name, Saturating}; - use crate::{assert_eq_error_rate, traits::Zero}; - - - #[test] - fn macro_expanded_correctly() { - // needed for the `from_percent` to work. - assert!($max >= 100); - assert!($max % 100 == 0); - - // needed for `from_rational_approximation` - assert!(2 * $max < <$type>::max_value()); - assert!(($max as $upper_type) < <$upper_type>::max_value()); - - // for something like percent they can be the same. - assert!((<$type>::max_value() as $upper_type) <= <$upper_type>::max_value()); - assert!(($max as $upper_type).checked_mul($max.into()).is_some()); - } - - #[derive(Encode, Decode, PartialEq, Eq, Debug)] - struct WithCompact { - data: T, - } - - #[test] - fn has_compact() { - let data = WithCompact { data: $name(1) }; - let encoded = data.encode(); - assert_eq!(data, WithCompact::<$name>::decode(&mut &encoded[..]).unwrap()); - } - - #[test] - fn compact_encoding() { - let tests = [ - // assume all per_things have the size u8 at least. - (0 as $type, 1usize), - (1 as $type, 1usize), - (63, 1), - (64, 2), - (65, 2), - (<$type>::max_value(), <$type>::max_value().encode().len() + 1) - ]; - for &(n, l) in &tests { - let compact: crate::codec::Compact<$name> = $name(n).into(); - let encoded = compact.encode(); - assert_eq!(encoded.len(), l); - let decoded = >::decode(&mut & encoded[..]) - .unwrap(); - let per_thingy: $name = decoded.into(); - assert_eq!(per_thingy, $name(n)); - } - } - - #[test] - fn per_thing_api_works() { - // some really basic stuff - assert_eq!($name::zero(), $name::from_parts(Zero::zero())); - assert_eq!($name::one(), $name::from_parts($max)); - assert_eq!($name::accuracy(), $max); - assert_eq!($name::from_percent(0), $name::from_parts(Zero::zero())); - assert_eq!($name::from_percent(10), $name::from_parts($max / 10)); - assert_eq!($name::from_percent(100), $name::from_parts($max)); - } - - macro_rules! per_thing_mul_test { - ($num_type:tt) => { - // multiplication from all sort of from_percent - assert_eq!( - $name::from_percent(100) * $num_type::max_value(), - $num_type::max_value() - ); - assert_eq_error_rate!( - $name::from_percent(99) * $num_type::max_value(), - ((Into::::into($num_type::max_value()) * 99u32) / 100u32).as_u128() as $num_type, - 1, - ); - assert_eq!( - $name::from_percent(50) * $num_type::max_value(), - $num_type::max_value() / 2, - ); - assert_eq_error_rate!( - $name::from_percent(1) * $num_type::max_value(), - $num_type::max_value() / 100, - 1, - ); - assert_eq!($name::from_percent(0) * $num_type::max_value(), 0); - - // // multiplication with bounds - assert_eq!($name::one() * $num_type::max_value(), $num_type::max_value()); - assert_eq!($name::zero() * $num_type::max_value(), 0); - } - } - - #[test] - fn per_thing_mul_works() { - use primitive_types::U256; - - // accuracy test - assert_eq!($name::from_rational_approximation(1 as $type, 3) * 30 as $type, 10); - - $(per_thing_mul_test!($test_units);)* - } - - #[test] - fn per_thing_mul_rounds_to_nearest_number() { - assert_eq!($name::from_percent(33) * 10u64, 3); - assert_eq!($name::from_percent(34) * 10u64, 3); - assert_eq!($name::from_percent(35) * 10u64, 3); - assert_eq!($name::from_percent(36) * 10u64, 4); - assert_eq!($name::from_percent(36) * 10u64, 4); - } - - #[test] - fn per_thing_multiplication_with_large_number() { - use primitive_types::U256; - let max_minus_one = $max - 1; - assert_eq_error_rate!( - $name::from_parts(max_minus_one) * std::u128::MAX, - ((Into::::into(std::u128::MAX) * max_minus_one) / $max).as_u128(), - 1, - ); - } - - macro_rules! per_thing_from_rationale_approx_test { - ($num_type:tt) => { - // within accuracy boundary - assert_eq!( - $name::from_rational_approximation(1 as $num_type, 0), - $name::one(), - ); - assert_eq!( - $name::from_rational_approximation(1 as $num_type, 1), - $name::one(), - ); - assert_eq_error_rate!( - $name::from_rational_approximation(1 as $num_type, 3).0, - $name::from_parts($max / 3).0, - 2 - ); - assert_eq!( - $name::from_rational_approximation(1 as $num_type, 10), - $name::from_percent(10), - ); - assert_eq!( - $name::from_rational_approximation(1 as $num_type, 4), - $name::from_percent(25), - ); - assert_eq!( - $name::from_rational_approximation(1 as $num_type, 4), - $name::from_rational_approximation(2 as $num_type, 8), - ); - // no accurate anymore but won't overflow. - assert_eq!( - $name::from_rational_approximation( - $num_type::max_value() - 1, - $num_type::max_value() - ), - $name::one(), - ); - assert_eq_error_rate!( - $name::from_rational_approximation( - $num_type::max_value() / 3, - $num_type::max_value() - ).0, - $name::from_parts($max / 3).0, - 2 - ); - assert_eq!( - $name::from_rational_approximation(1, $num_type::max_value()), - $name::zero(), - ); - }; - } - - #[test] - fn per_thing_from_rationale_approx_works() { - // This is just to make sure something like Percent which _might_ get built from a - // u8 does not overflow in the context of this test. - let max_value = $max as $upper_type; - // almost at the edge - assert_eq!( - $name::from_rational_approximation($max - 1, $max + 1), - $name::from_parts($max - 2), - ); - assert_eq!( - $name::from_rational_approximation(1, $max-1), - $name::from_parts(1), - ); - assert_eq!( - $name::from_rational_approximation(1, $max), - $name::from_parts(1), - ); - assert_eq!( - $name::from_rational_approximation(2, 2 * $max - 1), - $name::from_parts(1), - ); - assert_eq!( - $name::from_rational_approximation(1, $max+1), - $name::zero(), - ); - assert_eq!( - $name::from_rational_approximation(3 * max_value / 2, 3 * max_value), - $name::from_percent(50), - ); - $(per_thing_from_rationale_approx_test!($test_units);)* - } - - #[test] - fn per_things_mul_operates_in_output_type() { - // assert_eq!($name::from_percent(50) * 100u32, 50u32); - assert_eq!($name::from_percent(50) * 100u64, 50u64); - assert_eq!($name::from_percent(50) * 100u128, 50u128); - } - - #[test] - fn per_thing_saturating_op_works() { - assert_eq!( - $name::from_percent(50).saturating_add($name::from_percent(40)), - $name::from_percent(90) - ); - assert_eq!( - $name::from_percent(50).saturating_add($name::from_percent(50)), - $name::from_percent(100) - ); - assert_eq!( - $name::from_percent(60).saturating_add($name::from_percent(50)), - $name::from_percent(100) - ); - - assert_eq!( - $name::from_percent(60).saturating_sub($name::from_percent(50)), - $name::from_percent(10) - ); - assert_eq!( - $name::from_percent(60).saturating_sub($name::from_percent(60)), - $name::from_percent(0) - ); - assert_eq!( - $name::from_percent(60).saturating_sub($name::from_percent(70)), - $name::from_percent(0) - ); - - assert_eq!( - $name::from_percent(50).saturating_mul($name::from_percent(50)), - $name::from_percent(25) - ); - assert_eq!( - $name::from_percent(20).saturating_mul($name::from_percent(20)), - $name::from_percent(4) - ); - assert_eq!( - $name::from_percent(10).saturating_mul($name::from_percent(10)), - $name::from_percent(1) - ); - } - - #[test] - fn per_thing_square_works() { - assert_eq!($name::from_percent(100).square(), $name::from_percent(100)); - assert_eq!($name::from_percent(50).square(), $name::from_percent(25)); - assert_eq!($name::from_percent(10).square(), $name::from_percent(1)); - assert_eq!( - $name::from_percent(2).square(), - $name::from_parts((4 * ($max as $upper_type) / 100 / 100) as $type) - ); - } - - #[test] - fn per_things_div_works() { - // normal - assert_eq!($name::from_percent(10) / $name::from_percent(20), - $name::from_percent(50) - ); - assert_eq!($name::from_percent(10) / $name::from_percent(10), - $name::from_percent(100) - ); - assert_eq!($name::from_percent(10) / $name::from_percent(0), - $name::from_percent(100) - ); - - // will not overflow - assert_eq!($name::from_percent(10) / $name::from_percent(5), - $name::from_percent(100) - ); - assert_eq!($name::from_percent(100) / $name::from_percent(50), - $name::from_percent(100) - ); - } - } - }; -} - -implement_per_thing!( - Percent, - test_per_cent, - [u32, u64, u128], - 100u8, - u8, - u16, - "_Percent_", -); -implement_per_thing!( - Permill, - test_permill, - [u32, u64, u128], - 1_000_000u32, - u32, - u64, - "_Parts per Million_", -); -implement_per_thing!( - Perbill, - test_perbill, - [u32, u64, u128], - 1_000_000_000u32, - u32, - u64, - "_Parts per Billion_", -); -implement_per_thing!( - Perquintill, - test_perquintill, - [u64, u128], - 1_000_000_000_000_000_000u64, - u64, - u128, - "_Parts per Quintillion_", -); - -/// An unsigned fixed point number. Can hold any value in the range [-9_223_372_036, 9_223_372_036] -/// with fixed point accuracy of one billion. -#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Fixed64(i64); - -/// The accuracy of the `Fixed64` type. -const DIV: i64 = 1_000_000_000; - -impl Fixed64 { - /// creates self from a natural number. - /// - /// Note that this might be lossy. - pub fn from_natural(int: i64) -> Self { - Self(int.saturating_mul(DIV)) - } - - /// Return the accuracy of the type. Given that this function returns the value `X`, it means - /// that an instance composed of `X` parts (`Fixed64::from_parts(X)`) is equal to `1`. - pub fn accuracy() -> i64 { - DIV - } - - /// Raw constructor. Equal to `parts / 1_000_000_000`. - pub fn from_parts(parts: i64) -> Self { - Self(parts) - } - - /// creates self from a rational number. Equal to `n/d`. - /// - /// Note that this might be lossy. - pub fn from_rational(n: i64, d: u64) -> Self { - Self( - ((n as i128).saturating_mul(DIV as i128) / (d as i128).max(1)) - .try_into() - .unwrap_or(Bounded::max_value()) - ) - } - - /// Performs a saturated multiply and accumulate by unsigned number. - /// - /// Returns a saturated `int + (self * int)`. - pub fn saturated_multiply_accumulate(&self, int: N) -> N - where - N: TryFrom + From + UniqueSaturatedInto + Bounded + Clone + Saturating + - ops::Rem + ops::Div + ops::Mul + - ops::Add, - { - let div = DIV as u64; - let positive = self.0 > 0; - // safe to convert as absolute value. - let parts = self.0.checked_abs().map(|v| v as u64).unwrap_or(i64::max_value() as u64 + 1); - - - // will always fit. - let natural_parts = parts / div; - // might saturate. - let natural_parts: N = natural_parts.saturated_into(); - // fractional parts can always fit into u32. - let perbill_parts = (parts % div) as u32; - - let n = int.clone().saturating_mul(natural_parts); - let p = Perbill::from_parts(perbill_parts) * int.clone(); - - // everything that needs to be either added or subtracted from the original weight. - let excess = n.saturating_add(p); - - if positive { - int.saturating_add(excess) - } else { - int.saturating_sub(excess) - } - } -} - -impl Saturating for Fixed64 { - fn saturating_add(self, rhs: Self) -> Self { - Self(self.0.saturating_add(rhs.0)) - } - fn saturating_mul(self, rhs: Self) -> Self { - Self(self.0.saturating_mul(rhs.0) / DIV) - } - fn saturating_sub(self, rhs: Self) -> Self { - Self(self.0.saturating_sub(rhs.0)) - } -} - -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait -/// for safe addition. -impl ops::Add for Fixed64 { - type Output = Self; - - fn add(self, rhs: Self) -> Self::Output { - Self(self.0 + rhs.0) - } -} - -/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait -/// for safe subtraction. -impl ops::Sub for Fixed64 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self::Output { - Self(self.0 - rhs.0) - } -} - -impl CheckedSub for Fixed64 { - fn checked_sub(&self, rhs: &Self) -> Option { - if let Some(v) = self.0.checked_sub(rhs.0) { - Some(Self(v)) - } else { - None - } - } -} - -impl CheckedAdd for Fixed64 { - fn checked_add(&self, rhs: &Self) -> Option { - if let Some(v) = self.0.checked_add(rhs.0) { - Some(Self(v)) - } else { - None - } - } -} - -#[cfg(feature = "std")] -impl rstd::fmt::Debug for Fixed64 { - fn fmt(&self, f: &mut rstd::fmt::Formatter<'_>) -> rstd::fmt::Result { - write!(f, "Fixed64({},{})", self.0 / DIV, (self.0 % DIV) / 1000) - } -} - -/// Infinite precision unsigned integer for substrate runtime. -pub mod biguint { - use super::Zero; - use rstd::{cmp::Ordering, ops, prelude::*, cell::RefCell, convert::TryFrom}; - - // A sensible value for this would be half of the dword size of the host machine. Since the - // runtime is compiled to 32bit webassembly, using 32 and 64 for single and double respectively - // should yield the most performance. TODO #3745 we could benchmark this and verify. - /// Representation of a single limb. - pub type Single = u32; - /// Representation of two limbs. - pub type Double = u64; - /// Difference in the number of bits of [`Single`] and [`Double`]. - const SHIFT: usize = 32; - /// short form of _Base_. Analogous to the value 10 in base-10 decimal numbers. - const B: Double = Single::max_value() as Double + 1; - - /// Splits a [`Double`] limb number into a tuple of two [`Single`] limb numbers. - pub fn split(a: Double) -> (Single, Single) { - let al = a as Single; - let ah = (a >> SHIFT) as Single; - (ah, al) - } - - /// Assumed as a given primitive. - /// - /// Multiplication of two singles, which at most yields 1 double. - pub fn mul_single(a: Single, b: Single) -> Double { - let a: Double = a.into(); - let b: Double = b.into(); - let r = a * b; - r - } - - /// Assumed as a given primitive. - /// - /// Addition of two singles, which at most takes a single limb of result and a carry, - /// returned as a tuple respectively. - pub fn add_single(a: Single, b: Single) -> (Single, Single) { - let a: Double = a.into(); - let b: Double = b.into(); - let q = a + b; - let (carry, r) = split(q); - (r, carry) - } - - /// Assumed as a given primitive. - /// - /// Division of double by a single limb. Always returns a double limb of quotient and a single - /// limb of remainder. - fn div_single(a: Double, b: Single) -> (Double, Single) { - let b: Double = b.into(); - let q = a / b; - let r = a % b; - // both conversions are trivially safe. - (q, r as Single) - } - - /// Simple wrapper around an infinitely large integer, represented as limbs of [`Single`]. - #[derive(Clone, Default)] - pub struct BigUint { - /// digits (limbs) of this number (sorted as msb -> lsd). - pub(crate) digits: Vec, - } - - impl BigUint { - /// Create a new instance with `size` limbs. This prevents any number with zero limbs to be - /// created. - /// - /// The behavior of the type is undefined with zero limbs. - pub fn with_capacity(size: usize) -> Self { - Self { digits: vec![0; size.max(1)] } - } - - /// Raw constructor from custom limbs. If `limbs` is empty, `Zero::zero()` implementation is - /// used. - pub fn from_limbs(limbs: &[Single]) -> Self { - if limbs.len() > 0 { - Self { digits: limbs.to_vec() } - } else { - Zero::zero() - } - } - - /// Number of limbs. - pub fn len(&self) -> usize { self.digits.len() } - - /// A naive getter for limb at `index`. Note that the order is lsb -> msb. - /// - /// #### Panics - /// - /// This panics if index is out of range. - pub fn get(&self, index: usize) -> Single { - self.digits[self.len() - 1 - index] - } - - /// A naive getter for limb at `index`. Note that the order is lsb -> msb. - pub fn checked_get(&self, index: usize) -> Option { - if let Some(i) = self.len().checked_sub(1) { - if let Some(j) = i.checked_sub(index) { - return self.digits.get(j).cloned(); - } - } - return None; - } - - /// A naive setter for limb at `index`. Note that the order is lsb -> msb. - /// - /// #### Panics - /// - /// This panics if index is out of range. - pub fn set(&mut self, index: usize, value: Single) { - let len = self.digits.len(); - self.digits[len - 1 - index] = value; - } - - /// returns the least significant limb of the number. - /// - /// #### Panics - /// - /// While the constructor of the type prevents this, this can panic if `self` has no digits. - pub fn lsb(&self) -> Single { - self.digits[self.len() - 1] - } - - /// returns the most significant limb of the number. - /// - /// #### Panics - /// - /// While the constructor of the type prevents this, this can panic if `self` has no digits. - pub fn msb(&self) -> Single { - self.digits[0] - } - - /// Strips zeros from the left side of `self`, if any. - pub fn lstrip(&mut self) { - // by definition, a big-int number should never have leading zero limbs. This function - // has the ability to cause this. There is nothing to do if the number already has 1 - // limb only. call it a day and return. - if self.len().is_zero() { return; } - let mut index = 0; - for elem in self.digits.iter() { - if *elem != 0 { break } else { index += 1 } - } - if index > 0 { - self.digits = self.digits[index..].to_vec() - } - } - - /// Zero-pad `self` from left to reach `size` limbs. Will not make any difference if `self` - /// is already bigger than `size` limbs. - pub fn lpad(&mut self, size: usize) { - let n = self.len(); - if n >= size { return; } - let pad = size - n; - let mut new_digits = (0..pad).map(|_| 0).collect::>(); - new_digits.extend(self.digits.iter()); - self.digits = new_digits; - } - - /// Adds `self` with `other`. self and other do not have to have any particular size. Given - /// that the `n = max{size(self), size(other)}`, it will produce a number with `n + 1` - /// limbs. - /// - /// This function does not strip the output and returns the original allocated `n + 1` - /// limbs. The caller may strip the output if desired. - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn add(self, other: &Self) -> Self { - let n = self.len().max(other.len()); - let mut k: Double = 0; - let mut w = Self::with_capacity(n + 1); - - for j in 0..n { - let u = Double::from(self.checked_get(j).unwrap_or(0)); - let v = Double::from(other.checked_get(j).unwrap_or(0)); - let s = u + v + k; - w.set(j, (s % B) as Single); - k = s / B; - } - // k is always 0 or 1. - w.set(n, k as Single); - w - } - - /// Subtracts `other` from `self`. self and other do not have to have any particular size. - /// Given that the `n = max{size(self), size(other)}`, it will produce a number of size `n`. - /// - /// If `other` is bigger than `self`, `Err(B - borrow)` is returned. - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn sub(self, other: &Self) -> Result { - let n = self.len().max(other.len()); - let mut k = 0; - let mut w = Self::with_capacity(n); - for j in 0..n { - let s = { - let u = Double::from(self.checked_get(j).unwrap_or(0)); - let v = Double::from(other.checked_get(j).unwrap_or(0)); - let mut needs_borrow = false; - let mut t = 0; - - if let Some(v) = u.checked_sub(v) { - if let Some(v2) = v.checked_sub(k) { - t = v2 % B; - k = 0; - } else { - needs_borrow = true; - } - } else { - needs_borrow = true; - } - if needs_borrow { - t = u + B - v - k; - k = 1; - } - t - }; - // PROOF: t either comes from `v2 % B`, or from `u + B - v - k`. The former is - // trivial. The latter will not overflow this branch will only happen if the sum of - // `u - v - k` part has been negative, hence `u + B - v - k < b`. - w.set(j, s as Single); - } - - if k.is_zero() { - Ok(w) - } else { - Err(w) - } - } - - /// Multiplies n-limb number `self` with m-limb number `other`. - /// - /// The resulting number will always have `n + m` limbs. - /// - /// This function does not strip the output and returns the original allocated `n + m` - /// limbs. The caller may strip the output if desired. - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn mul(self, other: &Self) -> Self { - let n = self.len(); - let m = other.len(); - let mut w = Self::with_capacity(m + n); - - for j in 0..n { - if self.get(j) == 0 { - // Note: `with_capacity` allocates with 0. Explicitly set j + m to zero if - // otherwise. - continue; - } - - let mut k = 0; - for i in 0..m { - // PROOF: (B−1) × (B−1) + (B−1) + (B−1) = B^2 −1 < B^2. addition is safe. - let t = - mul_single(self.get(j), other.get(i)) - + Double::from(w.get(i + j)) - + Double::from(k); - w.set(i + j, (t % B) as Single); - // PROOF: (B^2 - 1) / B < B. conversion is safe. - k = (t / B) as Single; - } - w.set(j + m, k); - } - w - } - - /// Divides `self` by a single limb `other`. This can be used in cases where the original - /// division cannot work due to the divisor (`other`) being just one limb. - /// - /// Invariant: `other` cannot be zero. - pub fn div_unit(self, mut other: Single) -> Self { - other = other.max(1); - let n = self.len(); - let mut out = Self::with_capacity(n); - let mut r: Single = 0; - // PROOF: (B-1) * B + (B-1) still fits in double - let with_r = |x: Double, r: Single| { r as Double * B + x }; - for d in (0..=n-1).rev() { - let (q, rr) = div_single(with_r(self.get(d).into(), r), other) ; - out.set(d, q as Single); - r = rr; - } - out - } - - /// Divides an `n + m` limb self by a `n` limb `other`. The result is a `m + 1` limb - /// quotient and a `n` limb remainder, if enabled by passing `true` in `rem` argument, both - /// in the form of an option's `Ok`. - /// - /// - requires `other` to be stripped and have no leading zeros. - /// - requires `self` to be stripped and have no leading zeros. - /// - requires `other` to have at least two limbs. - /// - requires `self` to have a greater length compared to `other`. - /// - /// All arguments are examined without being stripped for the above conditions. If any of - /// the above fails, `None` is returned.` - /// - /// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4. - pub fn div(self, other: &Self, rem: bool) -> Option<(Self, Self)> { - if other.len() <= 1 - || other.msb() == 0 - || self.msb() == 0 - || self.len() <= other.len() - { - return None - } - let n = other.len(); - let m = self.len() - n; - - let mut q = Self::with_capacity(m + 1); - let mut r = Self::with_capacity(n); - - // PROOF: 0 <= normalizer_bits < SHIFT 0 <= normalizer < B. all conversions are - // safe. - let normalizer_bits = other.msb().leading_zeros() as Single; - let normalizer = (2 as Single).pow(normalizer_bits as u32) as Single; - - // step D1. - let mut self_norm = self.mul(&Self::from(normalizer)); - let mut other_norm = other.clone().mul(&Self::from(normalizer)); - - // defensive only; the mul implementation should always create this. - self_norm.lpad(n + m + 1); - other_norm.lstrip(); - - // step D2. - for j in (0..=m).rev() { - // step D3.0 Find an estimate of q[j], named qhat. - let (qhat, rhat) = { - // PROOF: this always fits into `Double`. In the context of Single = u8, and - // Double = u16, think of 255 * 256 + 255 which is just u16::max_value(). - let dividend = - Double::from(self_norm.get(j + n)) - * B - + Double::from(self_norm.get(j + n - 1)); - let divisor = other_norm.get(n - 1); - div_single(dividend, divisor.into()) - }; - - // D3.1 test qhat - // replace qhat and rhat with RefCells. This helps share state with the closure - let qhat = RefCell::new(qhat); - let rhat = RefCell::new(rhat as Double); - - let test = || { - // decrease qhat if it is bigger than the base (B) - let qhat_local = *qhat.borrow(); - let rhat_local = *rhat.borrow(); - let predicate_1 = qhat_local >= B; - let predicate_2 = { - let lhs = qhat_local * other_norm.get(n - 2) as Double; - let rhs = B * rhat_local + self_norm.get(j + n - 2) as Double; - lhs > rhs - }; - if predicate_1 || predicate_2 { - *qhat.borrow_mut() -= 1; - *rhat.borrow_mut() += other_norm.get(n - 1) as Double; - true - } else { - false - } - }; - - test(); - while (*rhat.borrow() as Double) < B { - if !test() { break; } - } - - let qhat = qhat.into_inner(); - // we don't need rhat anymore. just let it go out of scope when it does. - - // step D4 - let lhs = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; - let rhs = other_norm.clone().mul(&Self::from(qhat)); - - let maybe_sub = lhs.sub(&rhs); - let mut negative = false; - let sub = match maybe_sub { - Ok(t) => t, - Err(t) => { negative = true; t } - }; - (j..=j+n).for_each(|d| { self_norm.set(d, sub.get(d - j)); }); - - // step D5 - // PROOF: the `test()` specifically decreases qhat until it is below `B`. conversion - // is safe. - q.set(j, qhat as Single); - - // step D6: add back if negative happened. - if negative { - q.set(j, q.get(j) - 1); - let u = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() }; - let r = other_norm.clone().add(&u); - (j..=j+n).rev().for_each(|d| { self_norm.set(d, r.get(d - j)); }) - } - } - - // if requested, calculate remainder. - if rem { - // undo the normalization. - if normalizer_bits > 0 { - let s = SHIFT as u32; - let nb = normalizer_bits; - for d in 0..n-1 { - let v = self_norm.get(d) >> nb - | self_norm.get(d + 1).overflowing_shl(s - nb).0; - r.set(d, v); - } - r.set(n - 1, self_norm.get(n - 1) >> normalizer_bits); - } else { - r = self_norm; - } - } - - Some((q, r)) - } - } - - #[cfg(feature = "std")] - impl rstd::fmt::Debug for BigUint { - fn fmt(&self, f: &mut rstd::fmt::Formatter<'_>) -> rstd::fmt::Result { - write!( - f, - "BigUint {{ {:?} ({:?})}}", - self.digits, - u128::try_from(self.clone()).unwrap_or_else(|_| 0), - ) - } - } - - impl PartialEq for BigUint { - fn eq(&self, other: &Self) -> bool { - // sadly, we have to reallocate here as strip mutably uses self. - let mut lhs = self.clone(); - let mut rhs = other.clone(); - lhs.lstrip(); - rhs.lstrip(); - lhs.digits.eq(&rhs.digits) - } - } - - impl Eq for BigUint {} - - impl Ord for BigUint { - fn cmp(&self, other: &Self) -> Ordering { - let lhs_first = self.digits.iter().position(|&e| e != 0); - let rhs_first = other.digits.iter().position(|&e| e != 0); - - match (lhs_first, rhs_first) { - // edge cases that should not happen. This basically means that one or both were - // zero. - (None, None) => Ordering::Equal, - (Some(_), None) => Ordering::Greater, - (None, Some(_)) => Ordering::Less, - (Some(lhs_idx), Some(rhs_idx)) => { - let lhs = &self.digits[lhs_idx..]; - let rhs = &other.digits[rhs_idx..]; - let len_cmp = lhs.len().cmp(&rhs.len()); - match len_cmp { - Ordering::Equal => lhs.cmp(rhs), - _ => len_cmp, - } - } - } - } - } - - impl PartialOrd for BigUint { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } - } - - impl ops::Add for BigUint { - type Output = Self; - fn add(self, rhs: Self) -> Self::Output { - self.add(&rhs) - } - } - - impl ops::Sub for BigUint { - type Output = Self; - fn sub(self, rhs: Self) -> Self::Output { - self.sub(&rhs).unwrap_or_else(|e| e) - } - } - - impl ops::Mul for BigUint { - type Output = Self; - fn mul(self, rhs: Self) -> Self::Output { - self.mul(&rhs) - } - } - - impl Zero for BigUint { - fn zero() -> Self { - Self { digits: vec![Zero::zero()] } - } - - fn is_zero(&self) -> bool { - self.digits.iter().all(|d| d.is_zero()) - } - } - - macro_rules! impl_try_from_number_for { - ($([$type:ty, $len:expr]),+) => { - $( - impl TryFrom for $type { - type Error = &'static str; - fn try_from(mut value: BigUint) -> Result<$type, Self::Error> { - value.lstrip(); - let error_message = concat!("cannot fit a number into ", stringify!($type)); - if value.len() * SHIFT > $len { - Err(error_message) - } else { - let mut acc: $type = Zero::zero(); - for (i, d) in value.digits.iter().rev().cloned().enumerate() { - let d: $type = d.into(); - acc += d << (SHIFT * i); - } - Ok(acc) - } - } - } - )* - }; - } - // can only be implemented for sizes bigger than two limb. - impl_try_from_number_for!([u128, 128], [u64, 64]); - - macro_rules! impl_from_for_smaller_than_word { - ($($type:ty),+) => { - $(impl From<$type> for BigUint { - fn from(a: $type) -> Self { - Self { digits: vec! [a.into()] } - } - })* - } - } - impl_from_for_smaller_than_word!(u8, u16, Single); - - impl From for BigUint { - fn from(a: Double) -> Self { - let (ah, al) = split(a); - Self { digits: vec![ah, al] } - } - } - - #[cfg(test)] - pub mod tests_biguint { - use super::*; - use rand::Rng; - #[cfg(feature = "bench")] - use test::Bencher; - - // TODO move into a proper fuzzer #3745 - const FUZZ_COUNT: usize = 100_000; - - pub fn random_big_uint(size: usize) -> BigUint { - let mut rng = rand::thread_rng(); - let digits = (0..size).map(|_| rng.gen_range(0, Single::max_value())).collect(); - BigUint { digits } - } - - fn run_with_data_set( - count: usize, - limbs_ub_1: usize, - limbs_ub_2: usize, - exact: bool, - assertion: F, - ) where - F: Fn(BigUint, BigUint) -> () - { - let mut rng = rand::thread_rng(); - for _ in 0..count { - let digits_len_1 = if exact { limbs_ub_1 } else { rng.gen_range(1, limbs_ub_1) }; - let digits_len_2 = if exact { limbs_ub_2 } else { rng.gen_range(1, limbs_ub_2) }; - - let u = random_big_uint(digits_len_1); - let v = random_big_uint(digits_len_2); - assertion(u, v); - } - } - - fn with_limbs(n: usize) -> BigUint { - BigUint { digits: vec![1; n] } - } - - #[test] - fn split_works() { - let a = SHIFT / 2; - let b = SHIFT * 3 / 2; - let num: Double = 1 << a | 1 << b; - // example when `Single = u8` - // assert_eq!(num, 0b_0001_0000_0001_0000) - assert_eq!(split(num), (1 << a, 1 << a)); - } - - #[test] - fn strip_works() { - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![1, 0] }); - - let mut a = BigUint::from_limbs(&[0, 0, 1]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![1] }); - - let mut a = BigUint::from_limbs(&[0, 0]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![0] }); - - let mut a = BigUint::from_limbs(&[0, 0, 0]); - a.lstrip(); - assert_eq!(a, BigUint { digits: vec![0] }); - } - - #[test] - fn lpad_works() { - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lpad(2); - assert_eq!(a.digits, vec![0, 1, 0]); - - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lpad(3); - assert_eq!(a.digits, vec![0, 1, 0]); - - let mut a = BigUint::from_limbs(&[0, 1, 0]); - a.lpad(4); - assert_eq!(a.digits, vec![0, 0, 1, 0]); - } - - #[test] - fn equality_works() { - assert_eq!( - BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, - true, - ); - assert_eq!( - BigUint { digits: vec![3, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, - false, - ); - assert_eq!( - BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, - true, - ); - } - - #[test] - fn ordering_works() { - assert!(BigUint { digits: vec![0] } < BigUint { digits: vec![1] }); - assert!(BigUint { digits: vec![0] } == BigUint { digits: vec![0] }); - assert!(BigUint { digits: vec![] } == BigUint { digits: vec![0] }); - assert!(BigUint { digits: vec![] } == BigUint { digits: vec![] }); - assert!(BigUint { digits: vec![] } < BigUint { digits: vec![1] }); - - assert!(BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); - assert!(BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }); - - assert!(BigUint { digits: vec![1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); - assert!(BigUint { digits: vec![0, 1, 2, 4] } > BigUint { digits: vec![1, 2, 3] }); - assert!(BigUint { digits: vec![1, 2, 1, 0] } > BigUint { digits: vec![1, 2, 3] }); - - assert!(BigUint { digits: vec![0, 1, 2, 1] } < BigUint { digits: vec![1, 2, 3] }); - } - - #[test] - fn basic_random_ord_eq_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { - let ue = S::try_from(u.clone()).unwrap(); - let ve = S::try_from(v.clone()).unwrap(); - assert_eq!(u.cmp(&v), ue.cmp(&ve)); - assert_eq!(u.eq(&v), ue.eq(&ve)); - }) - } - - #[test] - fn can_try_build_numbers_from_types() { - use rstd::convert::TryFrom; - assert_eq!(u64::try_from(with_limbs(1)).unwrap(), 1); - assert_eq!(u64::try_from(with_limbs(2)).unwrap(), u32::max_value() as u64 + 2); - assert_eq!( - u64::try_from(with_limbs(3)).unwrap_err(), - "cannot fit a number into u64", - ); - assert_eq!( - u128::try_from(with_limbs(3)).unwrap(), - u32::max_value() as u128 + u64::max_value() as u128 + 3 - ); - } - - #[test] - fn zero_works() { - assert_eq!(BigUint::zero(), BigUint { digits: vec![0] }); - assert_eq!(BigUint { digits: vec![0, 1, 0] }.is_zero(), false); - assert_eq!(BigUint { digits: vec![0, 0, 0] }.is_zero(), true); - - let a = BigUint::zero(); - let b = BigUint::zero(); - let c = a * b; - assert_eq!(c.digits, vec![0, 0]); - } - - #[test] - fn basic_random_add_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 3, 3, false, |u, v| { - let expected = S::try_from(u.clone()).unwrap() + S::try_from(v.clone()).unwrap(); - let t = u.clone().add(&v); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} + {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - }) - } - - #[test] - fn sub_negative_works() { - assert_eq!( - BigUint::from(10 as Single).sub(&BigUint::from(5 as Single)).unwrap(), - BigUint::from(5 as Single) - ); - assert_eq!( - BigUint::from(10 as Single).sub(&BigUint::from(10 as Single)).unwrap(), - BigUint::from(0 as Single) - ); - assert_eq!( - BigUint::from(10 as Single).sub(&BigUint::from(13 as Single)).unwrap_err(), - BigUint::from((B - 3) as Single), - ); - } - - #[test] - fn basic_random_sub_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { - let expected = S::try_from(u.clone()).unwrap() - .checked_sub(S::try_from(v.clone()).unwrap()); - let t = u.clone().sub(&v); - if expected.is_none() { - assert!(t.is_err()) - } else { - let t = t.unwrap(); - let expected = expected.unwrap(); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} - {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - } - }) - } - - #[test] - fn basic_random_mul_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 2, 2, false, |u, v| { - let expected = S::try_from(u.clone()).unwrap() * S::try_from(v.clone()).unwrap(); - let t = u.clone().mul(&v); - assert_eq!( - S::try_from(t.clone()).unwrap(), expected, - "{:?} * {:?} ===> {:?} != {:?}", u, v, t, expected, - ); - }) - } - - #[test] - fn mul_always_appends_one_digit() { - let a = BigUint::from(10 as Single); - let b = BigUint::from(4 as Single); - assert_eq!(a.len(), 1); - assert_eq!(b.len(), 1); - - let n = a.mul(&b); - - assert_eq!(n.len(), 2); - assert_eq!(n.digits, vec![0, 40]); - } - - #[test] - fn div_conditions_work() { - let a = BigUint { digits: vec![2] }; - let b = BigUint { digits: vec![1, 2] }; - let c = BigUint { digits: vec![1, 1, 2] }; - let d = BigUint { digits: vec![0, 2] }; - let e = BigUint { digits: vec![0, 1, 1, 2] }; - - assert!(a.clone().div(&b, true).is_none()); - assert!(c.clone().div(&a, true).is_none()); - assert!(c.clone().div(&d, true).is_none()); - assert!(e.clone().div(&a, true).is_none()); - - assert!(c.clone().div(&b, true).is_some()); - } - - #[test] - fn div_unit_works() { - let a = BigUint { digits: vec![100] }; - let b = BigUint { digits: vec![1, 100] }; - - assert_eq!(a.clone().div_unit(1), a); - assert_eq!(a.clone().div_unit(0), a); - assert_eq!(a.clone().div_unit(2), BigUint::from(50 as Single)); - assert_eq!(a.clone().div_unit(7), BigUint::from(14 as Single)); - - assert_eq!(b.clone().div_unit(1), b); - assert_eq!(b.clone().div_unit(0), b); - assert_eq!(b.clone().div_unit(2), BigUint::from(((B + 100) / 2) as Single)); - assert_eq!(b.clone().div_unit(7), BigUint::from(((B + 100) / 7) as Single)); - - } - - #[test] - fn basic_random_div_works() { - type S = u128; - run_with_data_set(FUZZ_COUNT, 4, 4, false, |u, v| { - let ue = S::try_from(u.clone()).unwrap(); - let ve = S::try_from(v.clone()).unwrap(); - let (q, r) = (ue / ve, ue % ve); - if let Some((qq, rr)) = u.clone().div(&v, true) { - assert_eq!( - S::try_from(qq.clone()).unwrap(), q, - "{:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, - ); - assert_eq!( - S::try_from(rr.clone()).unwrap(), r, - "{:?} % {:?} ===> {:?} != {:?}", u, v, rr, r, - ); - } else if v.len() == 1 { - let qq = u.clone().div_unit(ve as Single); - assert_eq!( - S::try_from(qq.clone()).unwrap(), q, - "[single] {:?} / {:?} ===> {:?} != {:?}", u, v, qq, q, - ); - } else { - if v.msb() == 0 || v.msb() == 0 || u.len() <= v.len() {} // nada - else { panic!("div returned none for an unexpected reason"); } - } - }) - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_addition_2_digit(bencher: &mut Bencher) { - let a = random_big_uint(2); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().add(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_addition_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(4); - bencher.iter(|| { - let _ = a.clone().add(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_subtraction_2_digit(bencher: &mut Bencher) { - let a = random_big_uint(2); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().sub(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_subtraction_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(4); - bencher.iter(|| { - let _ = a.clone().sub(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_multiplication_2_digit(bencher: &mut Bencher) { - let a = random_big_uint(2); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().mul(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_multiplication_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(4); - bencher.iter(|| { - let _ = a.clone().mul(&b); - }); - } - - #[cfg(feature = "bench")] - #[bench] - fn bench_division_4_digit(bencher: &mut Bencher) { - let a = random_big_uint(4); - let b = random_big_uint(2); - bencher.iter(|| { - let _ = a.clone().div(&b, true); - }); - } - } -} - -/// Some helper functions to work with 128bit numbers. Note that the functionality provided here is -/// only sensible to use with 128bit numbers because for smaller sizes, you can always rely on -/// assumptions of a bigger type (u128) being available, or simply create a per-thing and use the -/// multiplication implementation provided there. -pub mod helpers_128bit { - use crate::biguint; - use crate::traits::Zero; - use rstd::{cmp::{min, max}, convert::TryInto}; - - /// Helper gcd function used in Rational128 implementation. - pub fn gcd(a: u128, b: u128) -> u128 { - match ((a, b), (a & 1, b & 1)) { - ((x, y), _) if x == y => y, - ((0, x), _) | ((x, 0), _) => x, - ((x, y), (0, 1)) | ((y, x), (1, 0)) => gcd(x >> 1, y), - ((x, y), (0, 0)) => gcd(x >> 1, y >> 1) << 1, - ((x, y), (1, 1)) => { - let (x, y) = (min(x, y), max(x, y)); - gcd((y - x) >> 1, x) - }, - _ => unreachable!(), - } - } - - /// split a u128 into two u64 limbs - pub fn split(a: u128) -> (u64, u64) { - let al = a as u64; - let ah = (a >> 64) as u64; - (ah, al) - } - - /// Convert a u128 to a u32 based biguint. - pub fn to_big_uint(x: u128) -> biguint::BigUint { - let (xh, xl) = split(x); - let (xhh, xhl) = biguint::split(xh); - let (xlh, xll) = biguint::split(xl); - let mut n = biguint::BigUint::from_limbs(&[xhh, xhl, xlh, xll]); - n.lstrip(); - n - } - - /// Safely and accurately compute `a * b / c`. The approach is: - /// - Simply try `a * b / c`. - /// - Else, convert them both into big numbers and re-try. `Err` is returned if the result - /// cannot be safely casted back to u128. - /// - /// Invariant: c must be greater than or equal to 1. - pub fn multiply_by_rational(a: u128, b: u128, c: u128) -> Result { - if a.is_zero() || b.is_zero() { return Ok(Zero::zero()); } - let c = c.max(1); - - // a and b are interchangeable by definition in this function. It always helps to assume the - // bigger of which is being multiplied by a `0 < b/c < 1`. Hence, a should be the bigger and - // b the smaller one. - let t = a; - let a = a.max(b); - let b = t.min(b); - - if let Some(x) = a.checked_mul(b) { - // This is the safest way to go. Try it. - Ok(x / c) - } else { - let a_num = to_big_uint(a); - let b_num = to_big_uint(b); - let c_num = to_big_uint(c); - - let mut ab = a_num * b_num; - ab.lstrip(); - let mut q = if c_num.len() == 1 { - // PROOF: if `c_num.len() == 1` then `c` fits in one limb. - ab.div_unit(c as biguint::Single) - } else { - // PROOF: both `ab` and `c` cannot have leading zero limbs; if length of `c` is 1, - // the previous branch would handle. Also, if ab for sure has a bigger size than - // c, because `a.checked_mul(b)` has failed, hence ab must be at least one limb - // bigger than c. In this case, returning zero is defensive-only and div should - // always return Some. - let (mut q, r) = ab.div(&c_num, true).unwrap_or((Zero::zero(), Zero::zero())); - let r: u128 = r.try_into() - .expect("reminder of div by c is always less than c; qed"); - if r > (c / 2) { q = q.add(&to_big_uint(1)); } - q - }; - q.lstrip(); - q.try_into().map_err(|_| "result cannot fit in u128") - } - } -} - -/// A wrapper for any rational number with a 128 bit numerator and denominator. -#[derive(Clone, Copy, Default, Eq)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct Rational128(u128, u128); - -impl Rational128 { - /// Nothing. - pub fn zero() -> Self { - Self(0, 1) - } - - /// If it is zero or not - pub fn is_zero(&self) -> bool { - self.0.is_zero() - } - - /// Build from a raw `n/d`. - pub fn from(n: u128, d: u128) -> Self { - Self(n, d.max(1)) - } - - /// Build from a raw `n/d`. This could lead to / 0 if not properly handled. - pub fn from_unchecked(n: u128, d: u128) -> Self { - Self(n, d) - } - - /// Return the numerator. - pub fn n(&self) -> u128 { - self.0 - } - - /// Return the denominator. - pub fn d(&self) -> u128 { - self.1 - } - - /// Convert `self` to a similar rational number where denominator is the given `den`. - // - /// This only returns if the result is accurate. `Err` is returned if the result cannot be - /// accurately calculated. - pub fn to_den(self, den: u128) -> Result { - if den == self.1 { - Ok(self) - } else { - helpers_128bit::multiply_by_rational(self.0, den, self.1).map(|n| Self(n, den)) - } - } - - /// Get the least common divisor of `self` and `other`. - /// - /// This only returns if the result is accurate. `Err` is returned if the result cannot be - /// accurately calculated. - pub fn lcm(&self, other: &Self) -> Result { - // this should be tested better: two large numbers that are almost the same. - if self.1 == other.1 { return Ok(self.1) } - let g = helpers_128bit::gcd(self.1, other.1); - helpers_128bit::multiply_by_rational(self.1 , other.1, g) - } - - /// A saturating add that assumes `self` and `other` have the same denominator. - pub fn lazy_saturating_add(self, other: Self) -> Self { - if other.is_zero() { - self - } else { - Self(self.0.saturating_add(other.0) ,self.1) - } - } - - /// A saturating subtraction that assumes `self` and `other` have the same denominator. - pub fn lazy_saturating_sub(self, other: Self) -> Self { - if other.is_zero() { - self - } else { - Self(self.0.saturating_sub(other.0) ,self.1) - } - } - - /// Addition. Simply tries to unify the denominators and add the numerators. - /// - /// Overflow might happen during any of the steps. Error is returned in such cases. - pub fn checked_add(self, other: Self) -> Result { - let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; - let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - let n = self_scaled.0.checked_add(other_scaled.0) - .ok_or("overflow while adding numerators")?; - Ok(Self(n, self_scaled.1)) - } - - /// Subtraction. Simply tries to unify the denominators and subtract the numerators. - /// - /// Overflow might happen during any of the steps. None is returned in such cases. - pub fn checked_sub(self, other: Self) -> Result { - let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?; - let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?; - - let n = self_scaled.0.checked_sub(other_scaled.0) - .ok_or("overflow while subtracting numerators")?; - Ok(Self(n, self_scaled.1)) - } -} - -impl PartialOrd for Rational128 { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for Rational128 { - fn cmp(&self, other: &Self) -> Ordering { - // handle some edge cases. - if self.1 == other.1 { - self.0.cmp(&other.0) - } else if self.1.is_zero() { - Ordering::Greater - } else if other.1.is_zero() { - Ordering::Less - } else { - // Don't even compute gcd. - let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); - let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); - self_n.cmp(&other_n) - } - } -} - -impl PartialEq for Rational128 { - fn eq(&self, other: &Self) -> bool { - // handle some edge cases. - if self.1 == other.1 { - self.0.eq(&other.0) - } else { - let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1); - let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1); - self_n.eq(&other_n) - } - } -} - -#[cfg(test)] -mod test_rational128 { - use super::*; - use super::helpers_128bit::*; - use rand::Rng; - - const MAX128: u128 = u128::max_value(); - const MAX64: u128 = u64::max_value() as u128; - const MAX64_2: u128 = 2 * u64::max_value() as u128; - - fn r(p: u128, q: u128) -> Rational128 { - Rational128(p, q) - } - - fn mul_div(a: u128, b: u128, c: u128) -> u128 { - use primitive_types::U256; - if a.is_zero() { return Zero::zero(); } - let c = c.max(1); - - // e for extended - let ae: U256 = a.into(); - let be: U256 = b.into(); - let ce: U256 = c.into(); - - let r = ae * be / ce; - if r > u128::max_value().into() { - a - } else { - r.as_u128() - } - } - - #[test] - fn truth_value_function_works() { - assert_eq!( - mul_div(2u128.pow(100), 8, 4), - 2u128.pow(101) - ); - assert_eq!( - mul_div(2u128.pow(100), 4, 8), - 2u128.pow(99) - ); - - // and it returns a if result cannot fit - assert_eq!(mul_div(MAX128 - 10, 2, 1), MAX128 - 10); - } - - #[test] - fn to_denom_works() { - // simple up and down - assert_eq!(r(1, 5).to_den(10), Ok(r(2, 10))); - assert_eq!(r(4, 10).to_den(5), Ok(r(2, 5))); - - // up and down with large numbers - assert_eq!(r(MAX128 - 10, MAX128).to_den(10), Ok(r(10, 10))); - assert_eq!(r(MAX128 / 2, MAX128).to_den(10), Ok(r(5, 10))); - - // large to perbill. This is very well needed for phragmen. - assert_eq!( - r(MAX128 / 2, MAX128).to_den(1000_000_000), - Ok(r(500_000_000, 1000_000_000)) - ); - - // large to large - assert_eq!(r(MAX128 / 2, MAX128).to_den(MAX128/2), Ok(r(MAX128/4, MAX128/2))); - } - - #[test] - fn gdc_works() { - assert_eq!(gcd(10, 5), 5); - assert_eq!(gcd(7, 22), 1); - } - - #[test] - fn lcm_works() { - // simple stuff - assert_eq!(r(3, 10).lcm(&r(4, 15)).unwrap(), 30); - assert_eq!(r(5, 30).lcm(&r(1, 7)).unwrap(), 210); - assert_eq!(r(5, 30).lcm(&r(1, 10)).unwrap(), 30); - - // large numbers - assert_eq!( - r(1_000_000_000, MAX128).lcm(&r(7_000_000_000, MAX128-1)), - Err("result cannot fit in u128"), - ); - assert_eq!( - r(1_000_000_000, MAX64).lcm(&r(7_000_000_000, MAX64-1)), - Ok(340282366920938463408034375210639556610), - ); - assert!(340282366920938463408034375210639556610 < MAX128); - assert!(340282366920938463408034375210639556610 == MAX64 * (MAX64 - 1)); - } - - #[test] - fn add_works() { - // works - assert_eq!(r(3, 10).checked_add(r(1, 10)).unwrap(), r(2, 5)); - assert_eq!(r(3, 10).checked_add(r(3, 7)).unwrap(), r(51, 70)); - - // errors - assert_eq!( - r(1, MAX128).checked_add(r(1, MAX128-1)), - Err("failed to scale to denominator"), - ); - assert_eq!( - r(7, MAX128).checked_add(r(MAX128, MAX128)), - Err("overflow while adding numerators"), - ); - assert_eq!( - r(MAX128, MAX128).checked_add(r(MAX128, MAX128)), - Err("overflow while adding numerators"), - ); - } - - #[test] - fn sub_works() { - // works - assert_eq!(r(3, 10).checked_sub(r(1, 10)).unwrap(), r(1, 5)); - assert_eq!(r(6, 10).checked_sub(r(3, 7)).unwrap(), r(12, 70)); - - // errors - assert_eq!( - r(2, MAX128).checked_sub(r(1, MAX128-1)), - Err("failed to scale to denominator"), - ); - assert_eq!( - r(7, MAX128).checked_sub(r(MAX128, MAX128)), - Err("overflow while subtracting numerators"), - ); - assert_eq!( - r(1, 10).checked_sub(r(2,10)), - Err("overflow while subtracting numerators"), - ); - } - - #[test] - fn ordering_and_eq_works() { - assert!(r(1, 2) > r(1, 3)); - assert!(r(1, 2) > r(2, 6)); - - assert!(r(1, 2) < r(6, 6)); - assert!(r(2, 1) > r(2, 6)); - - assert!(r(5, 10) == r(1, 2)); - assert!(r(1, 2) == r(1, 2)); - - assert!(r(1, 1490000000000200000) > r(1, 1490000000000200001)); - } - - #[test] - fn multiply_by_rational_works() { - assert_eq!(multiply_by_rational(7, 2, 3).unwrap(), 7 * 2 / 3); - assert_eq!(multiply_by_rational(7, 20, 30).unwrap(), 7 * 2 / 3); - assert_eq!(multiply_by_rational(20, 7, 30).unwrap(), 7 * 2 / 3); - - assert_eq!( - // MAX128 % 3 == 0 - multiply_by_rational(MAX128, 2, 3).unwrap(), - MAX128 / 3 * 2, - ); - assert_eq!( - // MAX128 % 7 == 3 - multiply_by_rational(MAX128, 5, 7).unwrap(), - (MAX128 / 7 * 5) + (3 * 5 / 7), - ); - assert_eq!( - // MAX128 % 7 == 3 - multiply_by_rational(MAX128, 11 , 13).unwrap(), - (MAX128 / 13 * 11) + (8 * 11 / 13), - ); - assert_eq!( - // MAX128 % 1000 == 455 - multiply_by_rational(MAX128, 555, 1000).unwrap(), - (MAX128 / 1000 * 555) + (455 * 555 / 1000), - ); - - assert_eq!( - multiply_by_rational(2 * MAX64 - 1, MAX64, MAX64).unwrap(), - 2 * MAX64 - 1, - ); - assert_eq!( - multiply_by_rational(2 * MAX64 - 1, MAX64 - 1, MAX64).unwrap(), - 2 * MAX64 - 3, - ); - - assert_eq!( - multiply_by_rational(MAX64 + 100, MAX64_2, MAX64_2 / 2).unwrap(), - (MAX64 + 100) * 2, - ); - assert_eq!( - multiply_by_rational(MAX64 + 100, MAX64_2 / 100, MAX64_2 / 200).unwrap(), - (MAX64 + 100) * 2, - ); - - assert_eq!( - multiply_by_rational(2u128.pow(66) - 1, 2u128.pow(65) - 1, 2u128.pow(65)).unwrap(), - 73786976294838206461, - ); - assert_eq!( - multiply_by_rational(1_000_000_000, MAX128 / 8, MAX128 / 2).unwrap(), - 250000000, - ); - } - - #[test] - fn multiply_by_rational_a_b_are_interchangeable() { - assert_eq!( - multiply_by_rational(10, MAX128, MAX128 / 2), - Ok(20), - ); - assert_eq!( - multiply_by_rational(MAX128, 10, MAX128 / 2), - Ok(20), - ); - } - - fn do_fuzz_multiply_by_rational( - iters: usize, - bits: u32, - maximum_error: u128, - do_print: bool, - bounded: bool, - mul_fn: F, - ) where F: Fn(u128, u128, u128) -> u128 { - let mut rng = rand::thread_rng(); - let mut average_diff = 0.0; - let upper_bound = 2u128.pow(bits); - - for _ in 0..iters { - let a = rng.gen_range(0u128, upper_bound); - let c = rng.gen_range(0u128, upper_bound); - let b = rng.gen_range( - 0u128, - if bounded { c } else { upper_bound } - ); - - let a: u128 = a.into(); - let b: u128 = b.into(); - let c: u128 = c.into(); - - let truth = mul_div(a, b, c); - let result = mul_fn(a, b, c); - let diff = truth.max(result) - truth.min(result); - let loss_ratio = diff as f64 / truth as f64; - average_diff += loss_ratio; - - if do_print && diff > maximum_error { - println!("++ Computed with more loss than expected: {} * {} / {}", a, b, c); - println!("++ Expected {}", truth); - println!("+++++++ Got {}", result); - } - } - - // print report - println!( - "## Fuzzed with {} numbers. Average error was {}", - iters, - average_diff / (iters as f64), - ); - } - - // TODO $# move into a proper fuzzer #3745 - const FUZZ_COUNT: usize = 100_000; - - #[test] - fn fuzz_multiply_by_rational_32() { - // if Err just return the truth value. We don't care about such cases. The point of this - // fuzzing is to make sure: if `multiply_by_rational` returns `Ok`, it must be 100% accurate - // returning `Err` is fine. - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 32, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 32, 0, false, false, f); - } - - #[test] - fn fuzz_multiply_by_rational_64() { - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 64, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 64, 0, false, false, f); - } - - #[test] - fn fuzz_multiply_by_rational_96() { - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 96, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 96, 0, false, false, f); - } - - #[test] - fn fuzz_multiply_by_rational_128() { - let f = |a, b, c| multiply_by_rational(a, b, c).unwrap_or(mul_div(a, b, c)); - println!("\nInvariant: b < c"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 127, 0, false, true, f); - println!("every possibility"); - do_fuzz_multiply_by_rational(FUZZ_COUNT, 127, 0, false, false, f); - } -} - -#[cfg(test)] -mod tests_fixed64 { - use super::*; - - fn max() -> Fixed64 { - Fixed64::from_parts(i64::max_value()) - } - - #[test] - fn fixed64_semantics() { - assert_eq!(Fixed64::from_rational(5, 2).0, 5 * 1_000_000_000 / 2); - assert_eq!(Fixed64::from_rational(5, 2), Fixed64::from_rational(10, 4)); - assert_eq!(Fixed64::from_rational(5, 0), Fixed64::from_rational(5, 1)); - - // biggest value that can be created. - assert_ne!(max(), Fixed64::from_natural(9_223_372_036)); - assert_eq!(max(), Fixed64::from_natural(9_223_372_037)); - } - - #[test] - fn fixed_64_growth_decrease_curve() { - let test_set = vec![0u32, 1, 10, 1000, 1_000_000_000]; - - // negative (1/2) - let mut fm = Fixed64::from_rational(-1, 2); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i) as i32, i as i32 - i as i32 / 2); - }); - - // unit (1) multiplier - fm = Fixed64::from_parts(0); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i), i); - }); - - // i.5 multiplier - fm = Fixed64::from_rational(1, 2); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i), i * 3 / 2); - }); - - // dual multiplier - fm = Fixed64::from_rational(1, 1); - test_set.clone().into_iter().for_each(|i| { - assert_eq!(fm.saturated_multiply_accumulate(i), i * 2); - }); - } - - macro_rules! saturating_mul_acc_test { - ($num_type:tt) => { - assert_eq!( - Fixed64::from_rational(100, 1).saturated_multiply_accumulate(10 as $num_type), - 1010, - ); - assert_eq!( - Fixed64::from_rational(100, 2).saturated_multiply_accumulate(10 as $num_type), - 510, - ); - assert_eq!( - Fixed64::from_rational(100, 3).saturated_multiply_accumulate(0 as $num_type), - 0, - ); - assert_eq!( - Fixed64::from_rational(5, 1).saturated_multiply_accumulate($num_type::max_value()), - $num_type::max_value() - ); - assert_eq!( - max().saturated_multiply_accumulate($num_type::max_value()), - $num_type::max_value() - ); - } - } - - #[test] - fn fixed64_multiply_accumulate_works() { - saturating_mul_acc_test!(u32); - saturating_mul_acc_test!(u64); - saturating_mul_acc_test!(u128); - } -} diff --git a/core/sr-primitives/src/weights.rs b/core/sr-primitives/src/weights.rs index aa0170b7f96c9..b1cce0f77f4ff 100644 --- a/core/sr-primitives/src/weights.rs +++ b/core/sr-primitives/src/weights.rs @@ -23,11 +23,8 @@ //! Note that the decl_module macro _cannot_ enforce this and will simply fail if an invalid struct //! (something that does not implement `Weighable`) is passed in. -use arithmetic::{Fixed64, traits::{Saturating, Bounded}}; -use crate::{ - codec::{Encode, Decode}, - transaction_validity::TransactionPriority -}; +pub use crate::transaction_validity::TransactionPriority; +use arithmetic::traits::Bounded; /// Numeric range of a transaction weight. pub type Weight = u32; From 0a843c84428f4822e505d23abaf8020aa492722e Mon Sep 17 00:00:00 2001 From: Ashley Date: Sat, 19 Oct 2019 09:21:17 +1300 Subject: [PATCH 63/63] Apply updates to sr_arithmetic.rs to crate --- core/sr-arithmetic/src/biguint.rs | 2 -- core/sr-arithmetic/src/fixed64.rs | 37 ++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/core/sr-arithmetic/src/biguint.rs b/core/sr-arithmetic/src/biguint.rs index 931eafd899ea3..d90ad4862ba10 100644 --- a/core/sr-arithmetic/src/biguint.rs +++ b/core/sr-arithmetic/src/biguint.rs @@ -321,8 +321,6 @@ impl BigUint { let mut q = Self::with_capacity(m + 1); let mut r = Self::with_capacity(n); - debug_assert!(other.msb() != 0); - // PROOF: 0 <= normalizer_bits < SHIFT 0 <= normalizer < B. all conversions are // safe. let normalizer_bits = other.msb().leading_zeros() as Single; diff --git a/core/sr-arithmetic/src/fixed64.rs b/core/sr-arithmetic/src/fixed64.rs index f4096d18133d3..7dfc8414d26b7 100644 --- a/core/sr-arithmetic/src/fixed64.rs +++ b/core/sr-arithmetic/src/fixed64.rs @@ -28,7 +28,6 @@ use crate::{ /// An unsigned fixed point number. Can hold any value in the range [-9_223_372_036, 9_223_372_036] /// with fixed point accuracy of one billion. -#[cfg_attr(feature = "std", derive(Debug))] #[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Fixed64(i64); @@ -145,6 +144,13 @@ impl CheckedAdd for Fixed64 { } } +#[cfg(feature = "std")] +impl rstd::fmt::Debug for Fixed64 { + fn fmt(&self, f: &mut rstd::fmt::Formatter<'_>) -> rstd::fmt::Result { + write!(f, "Fixed64({},{})", self.0 / DIV, (self.0 % DIV) / 1000) + } +} + #[cfg(test)] mod tests { use super::*; @@ -164,6 +170,35 @@ mod tests { assert_eq!(max(), Fixed64::from_natural(9_223_372_037)); } + #[test] + fn fixed_64_growth_decrease_curve() { + let test_set = vec![0u32, 1, 10, 1000, 1_000_000_000]; + + // negative (1/2) + let mut fm = Fixed64::from_rational(-1, 2); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i) as i32, i as i32 - i as i32 / 2); + }); + + // unit (1) multiplier + fm = Fixed64::from_parts(0); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i), i); + }); + + // i.5 multiplier + fm = Fixed64::from_rational(1, 2); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i), i * 3 / 2); + }); + + // dual multiplier + fm = Fixed64::from_rational(1, 1); + test_set.clone().into_iter().for_each(|i| { + assert_eq!(fm.saturated_multiply_accumulate(i), i * 2); + }); + } + macro_rules! saturating_mul_acc_test { ($num_type:tt) => { assert_eq!(