From c110f3eac979ba97c4c1bf2be9629596084171fa Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 24 Oct 2017 16:09:44 +0800 Subject: [PATCH 01/76] ethereum-types refactor --- Cargo.toml | 28 + build.rs | 17 + examples/modular.rs | 55 ++ src/lib.rs | 29 + src/uint.rs | 1298 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1427 insertions(+) create mode 100644 Cargo.toml create mode 100644 build.rs create mode 100644 examples/modular.rs create mode 100644 src/lib.rs create mode 100644 src/uint.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..6fde4f889 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,28 @@ +[package] +description = "Large fixed-size integers arithmetics" +homepage = "http://parity.io" +repository = "https://github.com/ethcore/bigint" +license = "MIT/Apache-2.0" +name = "uint" +version = "0.1.0" +authors = ["Parity Technologies "] +build = "build.rs" + +[build-dependencies] +rustc_version = "0.2" + +[dependencies] +rustc-hex = { version = "1.0", optional = true } +heapsize = { version = "0.4", optional = true } +byteorder = { version = "1", default-features = false } + +[dev-dependencies] +quickcheck = "0.4" + +[features] +heapsizeof = ["heapsize", "std"] +std = ["rustc-hex"] + +[[example]] +name = "modular" +required-features = ["std"] diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..432acc3f4 --- /dev/null +++ b/build.rs @@ -0,0 +1,17 @@ +// Copyright 2015-2017 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate rustc_version; + +use rustc_version::{version_meta, Channel}; + +fn main() { + if let Channel::Nightly = version_meta().unwrap().channel { + println!("cargo:rustc-cfg=asm_available"); + } +} diff --git a/examples/modular.rs b/examples/modular.rs new file mode 100644 index 000000000..06a808a1e --- /dev/null +++ b/examples/modular.rs @@ -0,0 +1,55 @@ +// Copyright 2015-2017 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate uint; + +use uint::U256; + +fn main() { + // Example modular arithmetic using bigint U256 primitives + + // imagine the field 0..p + // where the p is defined below + // (it's a prime!) + let p = U256::from_dec_str( + "38873241744847760218045702002058062581688990428170398542849190507947196700873" + ).expect("p to be a good number in the example"); + + // then, on this field, + // (p-1) + (p+1) = 0 + + // (p - 1) mod p + let p_minus_1 = (p - 1u64.into()) % p; + // (p + 1) mod p + let p_plus_1 = (p + 1u64.into()) % p; + // ((p - 1) mod p + (p + 1) mod p) mod p + let sum = (p_minus_1 + p_plus_1) % p; + assert_eq!(sum, 0.into()); + + // on this field, + // (p-1) + (p-1) = p-2 + let p_minus_1 = (p - 1u64.into()) % p; + let sum = (p_minus_1 + p_minus_1) % p; + assert_eq!(sum, p - 2.into()); + + // on this field, + // (p-1) * 3 = p-3 + let p_minus_1 = (p - 1u64.into()) % p; + + // multiplication is a series of additions + let multiplicator = 3; + let mul = { + let mut result = p_minus_1; + for _ in 0..multiplicator-1 { + result = (p_minus_1 + result) % p; + } + result + }; + + assert_eq!(mul, p - 3.into()); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 000000000..4a3dc8afa --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,29 @@ +// Copyright 2015-2017 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Efficient large, fixed-size big integers and hashes. + +#![cfg_attr(asm_available, feature(asm))] + +#[doc(hidden)] +pub extern crate byteorder; + +#[cfg(feature="heapsizeof")] +#[doc(hidden)] +pub extern crate heapsize; + +#[cfg(feature="std")] +#[doc(hidden)] +pub extern crate core; + +#[cfg(feature = "std")] +#[doc(hidden)] +pub extern crate rustc_hex; + +mod uint; +pub use uint::*; diff --git a/src/uint.rs b/src/uint.rs new file mode 100644 index 000000000..39e7aca7e --- /dev/null +++ b/src/uint.rs @@ -0,0 +1,1298 @@ +// Copyright 2015-2017 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Code derived from original work by Andrew Poelstra + +// Rust Bitcoin Library +// Written in 2014 by +// Andrew Poelstra +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// + +//! Big unsigned integer types. +//! +//! Implementation of a various large-but-fixed sized unsigned integer types. +//! The functions here are designed to be fast. There are optional `x86_64` +//! implementations for even more speed, hidden behind the `x64_arithmetic` +//! feature flag. + +/// Conversion from decimal string error +#[derive(Debug, PartialEq)] +pub enum FromDecStrErr { + /// Char not from range 0-9 + InvalidCharacter, + /// Value does not fit into type + InvalidLength, +} + +#[macro_export] +#[doc(hidden)] +macro_rules! impl_map_from { + ($thing:ident, $from:ty, $to:ty) => { + impl From<$from> for $thing { + fn from(value: $from) -> $thing { + From::from(value as $to) + } + } + } +} + +#[cfg(not(all(asm_available, target_arch="x86_64")))] +#[macro_export] +#[doc(hidden)] +macro_rules! uint_overflowing_add { + ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + uint_overflowing_add_reg!($name, $n_words, $self_expr, $other) + }) +} + +#[macro_export] +#[doc(hidden)] +macro_rules! uint_overflowing_add_reg { + ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + uint_overflowing_binop!( + $name, + $n_words, + $self_expr, + $other, + u64::overflowing_add + ) + }) +} + +#[cfg(all(asm_available, target_arch="x86_64"))] +#[macro_export] +#[doc(hidden)] +macro_rules! uint_overflowing_add { + (U256, $n_words:tt, $self_expr: expr, $other: expr) => ({ + let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; + let self_t: &[u64; $n_words] = &$self_expr.0; + let other_t: &[u64; $n_words] = &$other.0; + + let overflow: u8; + unsafe { + asm!(" + add $9, $0 + adc $10, $1 + adc $11, $2 + adc $12, $3 + setc %al + " + : "=r"(result[0]), "=r"(result[1]), "=r"(result[2]), "=r"(result[3]), "={al}"(overflow) + : "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), + "mr"(other_t[0]), "mr"(other_t[1]), "mr"(other_t[2]), "mr"(other_t[3]) + : + : + ); + } + (U256(result), overflow != 0) + }); + (U512, $n_words:tt, $self_expr: expr, $other: expr) => ({ + let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; + let self_t: &[u64; $n_words] = &$self_expr.0; + let other_t: &[u64; $n_words] = &$other.0; + + let overflow: u8; + + unsafe { + asm!(" + add $15, $0 + adc $16, $1 + adc $17, $2 + adc $18, $3 + lodsq + adc $11, %rax + stosq + lodsq + adc $12, %rax + stosq + lodsq + adc $13, %rax + stosq + lodsq + adc $14, %rax + stosq + setc %al + + ": "=r"(result[0]), "=r"(result[1]), "=r"(result[2]), "=r"(result[3]), + + "={al}"(overflow) /* $0 - $4 */ + + : "{rdi}"(&result[4] as *const u64) /* $5 */ + "{rsi}"(&other_t[4] as *const u64) /* $6 */ + "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), + "m"(self_t[4]), "m"(self_t[5]), "m"(self_t[6]), "m"(self_t[7]), + /* $7 - $14 */ + + "mr"(other_t[0]), "mr"(other_t[1]), "mr"(other_t[2]), "mr"(other_t[3]), + "m"(other_t[4]), "m"(other_t[5]), "m"(other_t[6]), "m"(other_t[7]) /* $15 - $22 */ + : "rdi", "rsi" + : + ); + } + (U512(result), overflow != 0) + }); + + ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ( + uint_overflowing_add_reg!($name, $n_words, $self_expr, $other) + ) +} + +#[cfg(not(all(asm_available, target_arch="x86_64")))] +#[macro_export] +#[doc(hidden)] +macro_rules! uint_overflowing_sub { + ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + uint_overflowing_sub_reg!($name, $n_words, $self_expr, $other) + }) +} + +#[macro_export] +#[doc(hidden)] +macro_rules! uint_overflowing_binop { + ($name:ident, $n_words:tt, $self_expr: expr, $other: expr, $fn:expr) => ({ + let $name(ref me) = $self_expr; + let $name(ref you) = $other; + + let mut ret = unsafe { ::core::mem::uninitialized() }; + let ret_ptr = &mut ret as *mut [u64; $n_words] as *mut u64; + let mut carry = 0u64; + + unroll! { + for i in 0..$n_words { + use ::core::ptr; + + if carry != 0 { + let (res1, overflow1) = ($fn)(me[i], you[i]); + let (res2, overflow2) = ($fn)(res1, carry); + + unsafe { + ptr::write( + ret_ptr.offset(i as _), + res2 + ); + } + carry = (overflow1 as u8 + overflow2 as u8) as u64; + } else { + let (res, overflow) = ($fn)(me[i], you[i]); + + unsafe { + ptr::write( + ret_ptr.offset(i as _), + res + ); + } + + carry = overflow as u64; + } + } + } + + ($name(ret), carry > 0) + }) +} + +#[macro_export] +#[doc(hidden)] +macro_rules! uint_overflowing_sub_reg { + ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + uint_overflowing_binop!( + $name, + $n_words, + $self_expr, + $other, + u64::overflowing_sub + ) + }) +} + +#[cfg(all(asm_available, target_arch="x86_64"))] +#[macro_export] +#[doc(hidden)] +macro_rules! uint_overflowing_sub { + (U256, $n_words:tt, $self_expr: expr, $other: expr) => ({ + let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; + let self_t: &[u64; $n_words] = &$self_expr.0; + let other_t: &[u64; $n_words] = &$other.0; + + let overflow: u8; + unsafe { + asm!(" + sub $9, $0 + sbb $10, $1 + sbb $11, $2 + sbb $12, $3 + setb %al + " + : "=r"(result[0]), "=r"(result[1]), "=r"(result[2]), "=r"(result[3]), "={al}"(overflow) + : "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), "mr"(other_t[0]), "mr"(other_t[1]), "mr"(other_t[2]), "mr"(other_t[3]) + : + : + ); + } + (U256(result), overflow != 0) + }); + (U512, $n_words:tt, $self_expr: expr, $other: expr) => ({ + let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; + let self_t: &[u64; $n_words] = &$self_expr.0; + let other_t: &[u64; $n_words] = &$other.0; + + let overflow: u8; + + unsafe { + asm!(" + sub $15, $0 + sbb $16, $1 + sbb $17, $2 + sbb $18, $3 + lodsq + sbb $19, %rax + stosq + lodsq + sbb $20, %rax + stosq + lodsq + sbb $21, %rax + stosq + lodsq + sbb $22, %rax + stosq + setb %al + " + : "=r"(result[0]), "=r"(result[1]), "=r"(result[2]), "=r"(result[3]), + + "={al}"(overflow) /* $0 - $4 */ + + : "{rdi}"(&result[4] as *const u64) /* $5 */ + "{rsi}"(&self_t[4] as *const u64) /* $6 */ + "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), + "m"(self_t[4]), "m"(self_t[5]), "m"(self_t[6]), "m"(self_t[7]), + /* $7 - $14 */ + + "m"(other_t[0]), "m"(other_t[1]), "m"(other_t[2]), "m"(other_t[3]), + "m"(other_t[4]), "m"(other_t[5]), "m"(other_t[6]), "m"(other_t[7]) /* $15 - $22 */ + : "rdi", "rsi" + : + ); + } + (U512(result), overflow != 0) + }); + ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + uint_overflowing_sub_reg!($name, $n_words, $self_expr, $other) + }) +} + +#[cfg(all(asm_available, target_arch="x86_64"))] +#[macro_export] +macro_rules! uint_overflowing_mul { + (U256, $n_words: expr, $self_expr: expr, $other: expr) => ({ + let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; + let self_t: &[u64; $n_words] = &$self_expr.0; + let other_t: &[u64; $n_words] = &$other.0; + + let overflow: u64; + unsafe { + asm!(" + mov $5, %rax + mulq $9 + mov %rax, $0 + mov %rdx, $1 + + mov $5, %rax + mulq $10 + add %rax, $1 + adc $$0, %rdx + mov %rdx, $2 + + mov $5, %rax + mulq $11 + add %rax, $2 + adc $$0, %rdx + mov %rdx, $3 + + mov $5, %rax + mulq $12 + add %rax, $3 + adc $$0, %rdx + mov %rdx, %rcx + + mov $6, %rax + mulq $9 + add %rax, $1 + adc %rdx, $2 + adc $$0, $3 + adc $$0, %rcx + + mov $6, %rax + mulq $10 + add %rax, $2 + adc %rdx, $3 + adc $$0, %rcx + adc $$0, $3 + adc $$0, %rcx + + mov $6, %rax + mulq $11 + add %rax, $3 + adc $$0, %rdx + or %rdx, %rcx + + mov $7, %rax + mulq $9 + add %rax, $2 + adc %rdx, $3 + adc $$0, %rcx + + mov $7, %rax + mulq $10 + add %rax, $3 + adc $$0, %rdx + or %rdx, %rcx + + mov $8, %rax + mulq $9 + add %rax, $3 + or %rdx, %rcx + + cmpq $$0, %rcx + jne 2f + + mov $8, %rcx + jrcxz 12f + + mov $12, %rcx + mov $11, %rax + or %rax, %rcx + mov $10, %rax + or %rax, %rcx + jmp 2f + + 12: + mov $12, %rcx + jrcxz 11f + + mov $7, %rcx + mov $6, %rax + or %rax, %rcx + + cmpq $$0, %rcx + jne 2f + + 11: + mov $11, %rcx + jrcxz 2f + mov $7, %rcx + + 2: + " + : /* $0 */ "={r8}"(result[0]), /* $1 */ "={r9}"(result[1]), /* $2 */ "={r10}"(result[2]), + /* $3 */ "={r11}"(result[3]), /* $4 */ "={rcx}"(overflow) + + : /* $5 */ "m"(self_t[0]), /* $6 */ "m"(self_t[1]), /* $7 */ "m"(self_t[2]), + /* $8 */ "m"(self_t[3]), /* $9 */ "m"(other_t[0]), /* $10 */ "m"(other_t[1]), + /* $11 */ "m"(other_t[2]), /* $12 */ "m"(other_t[3]) + : "rax", "rdx" + : + + ); + } + (U256(result), overflow > 0) + }); + ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ( + uint_overflowing_mul_reg!($name, $n_words, $self_expr, $other) + ) +} + +#[cfg(not(all(asm_available, target_arch="x86_64")))] +#[macro_export] +#[doc(hidden)] +macro_rules! uint_overflowing_mul { + ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + uint_overflowing_mul_reg!($name, $n_words, $self_expr, $other) + }) +} + +#[macro_export] +#[doc(hidden)] +macro_rules! uint_full_mul_reg { + ($name:ident, $n_words:tt, $self_expr:expr, $other:expr) => ({{ + #![allow(unused_assignments)] + + let $name(ref me) = $self_expr; + let $name(ref you) = $other; + let mut ret = [0u64; 2*$n_words]; + + unroll! { + for i in 0..$n_words { + let mut carry = 0u64; + let (b_u, b_l) = $crate::split(you[i]); + + unroll! { + for j in 0..$n_words { + if me[j] != 0 || carry != 0 { + let a = $crate::split(me[j]); + + // multiply parts + let (c_l, overflow_l) = $crate::mul_u32(a, b_l, ret[i + j]); + let (c_u, overflow_u) = $crate::mul_u32(a, b_u, c_l >> 32); + ret[i + j] = (c_l & 0xFFFFFFFF) + (c_u << 32); + + // No overflow here + let res = (c_u >> 32) + (overflow_u << 32); + // possible overflows + let (res, o1) = res.overflowing_add(overflow_l + carry); + let (res, o2) = res.overflowing_add(ret[i + j + 1]); + ret[i + j + 1] = res; + + // Only single overflow possible there + carry = (o1 | o2) as u64; + } + } + } + } + } + + ret + }}) +} + +#[macro_export] +#[doc(hidden)] +macro_rules! uint_overflowing_mul_reg { + ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + let ret: [u64; $n_words * 2] = uint_full_mul_reg!($name, $n_words, $self_expr, $other); + + // The safety of this is enforced by the compiler + let ret: [[u64; $n_words]; 2] = unsafe { ::core::mem::transmute(ret) }; + + // The compiler WILL NOT inline this if you remove this annotation. + #[inline(always)] + fn any_nonzero(arr: &[u64; $n_words]) -> bool { + unroll! { + for i in 0..$n_words { + if arr[i] != 0 { + return true; + } + } + } + + false + } + + ($name(ret[0]), any_nonzero(&ret[1])) + }) +} + +#[macro_export] +#[doc(hidden)] +macro_rules! overflowing { + ($op: expr, $overflow: expr) => ( + { + let (overflow_x, overflow_overflow) = $op; + $overflow |= overflow_overflow; + overflow_x + } + ); + ($op: expr) => ( + { + let (overflow_x, _overflow_overflow) = $op; + overflow_x + } + ); +} + +#[macro_export] +#[doc(hidden)] +macro_rules! panic_on_overflow { + ($name: expr) => { + if $name { + panic!("arithmetic operation overflow") + } + } +} + +#[inline(always)] +#[doc(hidden)] +pub fn mul_u32(a: (u64, u64), b: u64, carry: u64) -> (u64, u64) { + let upper = b * a.0; + let lower = b * a.1; + + let (res1, overflow1) = lower.overflowing_add(upper << 32); + let (res2, overflow2) = res1.overflowing_add(carry); + + let carry = (upper >> 32) + overflow1 as u64 + overflow2 as u64; + (res2, carry) +} + +#[inline(always)] +#[doc(hidden)] +pub fn split(a: u64) -> (u64, u64) { + (a >> 32, a & 0xFFFFFFFF) +} + +#[macro_export] +macro_rules! construct_uint { + ($name:ident, $n_words:tt) => ( + /// Little-endian large integer type + #[repr(C)] + #[derive(Copy, Clone, Eq, PartialEq, Hash)] + pub struct $name(pub [u64; $n_words]); + + impl $name { + /// Convert from a decimal string. + pub fn from_dec_str(value: &str) -> Result { + if !value.bytes().all(|b| b >= 48 && b <= 57) { + return Err($crate::FromDecStrErr::InvalidCharacter) + } + + let mut res = Self::default(); + for b in value.bytes().map(|b| b - 48) { + let (r, overflow) = res.overflowing_mul_u32(10); + if overflow { + return Err($crate::FromDecStrErr::InvalidLength); + } + let (r, overflow) = r.overflowing_add(b.into()); + if overflow { + return Err($crate::FromDecStrErr::InvalidLength); + } + res = r; + } + Ok(res) + } + + /// Conversion to u32 + #[inline] + pub fn low_u32(&self) -> u32 { + let &$name(ref arr) = self; + arr[0] as u32 + } + + /// Conversion to u64 + #[inline] + pub fn low_u64(&self) -> u64 { + let &$name(ref arr) = self; + arr[0] + } + + /// Conversion to u32 with overflow checking + /// + /// # Panics + /// + /// Panics if the number is larger than 2^32. + #[inline] + pub fn as_u32(&self) -> u32 { + let &$name(ref arr) = self; + if (arr[0] & (0xffffffffu64 << 32)) != 0 { + panic!("Integer overflow when casting U256") + } + self.as_u64() as u32 + } + + /// Conversion to u64 with overflow checking + /// + /// # Panics + /// + /// Panics if the number is larger than 2^64. + #[inline] + pub fn as_u64(&self) -> u64 { + let &$name(ref arr) = self; + for i in 1..$n_words { + if arr[i] != 0 { + panic!("Integer overflow when casting U256") + } + } + arr[0] + } + + /// Whether this is zero. + #[inline] + pub fn is_zero(&self) -> bool { + let &$name(ref arr) = self; + for i in 0..$n_words { if arr[i] != 0 { return false; } } + return true; + } + + /// Return the least number of bits needed to represent the number + #[inline] + pub fn bits(&self) -> usize { + let &$name(ref arr) = self; + for i in 1..$n_words { + if arr[$n_words - i] > 0 { return (0x40 * ($n_words - i + 1)) - arr[$n_words - i].leading_zeros() as usize; } + } + 0x40 - arr[0].leading_zeros() as usize + } + + /// Return if specific bit is set. + /// + /// # Panics + /// + /// Panics if `index` exceeds the bit width of the number. + #[inline] + pub fn bit(&self, index: usize) -> bool { + let &$name(ref arr) = self; + arr[index / 64] & (1 << (index % 64)) != 0 + } + + /// Returns the number of leading zeros in the binary representation of self. + pub fn leading_zeros(&self) -> u32 { + let mut r = 0; + for i in 0..$n_words { + let w = self.0[$n_words - i - 1]; + if w == 0 { + r += 64; + } else { + r += w.leading_zeros(); + break; + } + } + r + } + + /// Returns the number of leading zeros in the binary representation of self. + pub fn trailing_zeros(&self) -> u32 { + let mut r = 0; + for i in 0..$n_words { + let w = self.0[i]; + if w == 0 { + r += 64; + } else { + r += w.trailing_zeros(); + break; + } + } + r + } + + /// Return specific byte. + /// + /// # Panics + /// + /// Panics if `index` exceeds the byte width of the number. + #[inline] + pub fn byte(&self, index: usize) -> u8 { + let &$name(ref arr) = self; + (arr[index / 8] >> (((index % 8)) * 8)) as u8 + } + + /// Write to the slice in big-endian format. + #[inline] + pub fn to_big_endian(&self, bytes: &mut [u8]) { + use $crate::byteorder::{ByteOrder, BigEndian}; + debug_assert!($n_words * 8 == bytes.len()); + for i in 0..$n_words { + BigEndian::write_u64(&mut bytes[8 * i..], self.0[$n_words - i - 1]); + } + } + + /// Write to the slice in little-endian format. + #[inline] + pub fn to_little_endian(&self, bytes: &mut [u8]) { + use $crate::byteorder::{ByteOrder, LittleEndian}; + debug_assert!($n_words * 8 == bytes.len()); + for i in 0..$n_words { + LittleEndian::write_u64(&mut bytes[8 * i..], self.0[i]); + } + } + + + /// Create `10**n` as this type. + /// + /// # Panics + /// + /// Panics if the result overflows the type. + #[inline] + pub fn exp10(n: usize) -> Self { + match n { + 0 => Self::from(1u64), + _ => Self::exp10(n - 1).mul_u32(10) + } + } + + /// Zero (additive identity) of this type. + #[inline] + pub fn zero() -> Self { + From::from(0u64) + } + + /// One (multiplicative identity) of this type. + #[inline] + pub fn one() -> Self { + From::from(1u64) + } + + /// The maximum value which can be inhabited by this type. + #[inline] + pub fn max_value() -> Self { + let mut result = [0; $n_words]; + for i in 0..$n_words { + result[i] = u64::max_value(); + } + $name(result) + } + + /// Fast exponentation by squaring + /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring + /// + /// # Panics + /// + /// Panics if the result overflows the type. + pub fn pow(self, expon: Self) -> Self { + if expon.is_zero() { + return Self::one() + } + let is_even = |x : &Self| x.low_u64() & 1 == 0; + + let u_one = Self::one(); + let mut y = u_one; + let mut n = expon; + let mut x = self; + while n > u_one { + if is_even(&n) { + x = x * x; + n = n >> 1; + } else { + y = x * y; + x = x * x; + // to reduce odd number by 1 we should just clear the last bit + n.0[$n_words-1] = n.0[$n_words-1] & ((!0u64)>>1); + n = n >> 1; + } + } + x * y + } + + /// Fast exponentation by squaring + /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring + pub fn overflowing_pow(self, expon: Self) -> (Self, bool) { + if expon.is_zero() { return (Self::one(), false) } + + let is_even = |x : &Self| x.low_u64() & 1 == 0; + + let u_one = Self::one(); + let mut y = u_one; + let mut n = expon; + let mut x = self; + let mut overflow = false; + + while n > u_one { + if is_even(&n) { + x = overflowing!(x.overflowing_mul(x), overflow); + n = n >> 1; + } else { + y = overflowing!(x.overflowing_mul(y), overflow); + x = overflowing!(x.overflowing_mul(x), overflow); + n = (n - u_one) >> 1; + } + } + let res = overflowing!(x.overflowing_mul(y), overflow); + (res, overflow) + } + + /// Optimized instructions + #[inline(always)] + pub fn overflowing_add(self, other: $name) -> ($name, bool) { + uint_overflowing_add!($name, $n_words, self, other) + } + + /// Addition which saturates at the maximum value. + pub fn saturating_add(self, other: $name) -> $name { + match self.overflowing_add(other) { + (_, true) => $name::max_value(), + (val, false) => val, + } + } + + /// Subtraction which underflows and returns a flag if it does. + #[inline(always)] + pub fn overflowing_sub(self, other: $name) -> ($name, bool) { + uint_overflowing_sub!($name, $n_words, self, other) + } + + /// Subtraction which saturates at zero. + pub fn saturating_sub(self, other: $name) -> $name { + match self.overflowing_sub(other) { + (_, true) => $name::zero(), + (val, false) => val, + } + } + + /// Multiply with overflow, returning a flag if it does. + #[inline(always)] + pub fn overflowing_mul(self, other: $name) -> ($name, bool) { + uint_overflowing_mul!($name, $n_words, self, other) + } + + /// Multiplication which saturates at the maximum value.. + pub fn saturating_mul(self, other: $name) -> $name { + match self.overflowing_mul(other) { + (_, true) => $name::max_value(), + (val, false) => val, + } + } + + /// Division with overflow + pub fn overflowing_div(self, other: $name) -> ($name, bool) { + (self / other, false) + } + + /// Modulus with overflow. + pub fn overflowing_rem(self, other: $name) -> ($name, bool) { + (self % other, false) + } + + /// Negation with overflow. + pub fn overflowing_neg(self) -> ($name, bool) { + (!self, true) + } + + /// Multiplication by u32 + pub fn mul_u32(self, other: u32) -> Self { + let (ret, overflow) = self.overflowing_mul_u32(other); + panic_on_overflow!(overflow); + ret + } + + /// Overflowing multiplication by u32 + #[allow(dead_code)] // not used when multiplied with inline assembly + fn overflowing_mul_u32(self, other: u32) -> (Self, bool) { + let $name(ref arr) = self; + let mut ret = [0u64; $n_words]; + let mut carry = 0; + let o = other as u64; + + for i in 0..$n_words { + let (res, carry2) = $crate::mul_u32($crate::split(arr[i]), o, carry); + ret[i] = res; + carry = carry2; + } + + ($name(ret), carry > 0) + } + + /// Converts from big endian representation bytes in memory + /// Can also be used as (&slice).into(), as it is default `From` + /// slice implementation for U256 + pub fn from_big_endian(slice: &[u8]) -> Self { + assert!($n_words * 8 >= slice.len()); + + let mut ret = [0; $n_words]; + unsafe { + let ret_u8: &mut [u8; $n_words * 8] = ::core::mem::transmute(&mut ret); + let mut ret_ptr = ret_u8.as_mut_ptr(); + let mut slice_ptr = slice.as_ptr().offset(slice.len() as isize - 1); + for _ in 0..slice.len() { + *ret_ptr = *slice_ptr; + ret_ptr = ret_ptr.offset(1); + slice_ptr = slice_ptr.offset(-1); + } + } + + $name(ret) + } + + /// Converts from little endian representation bytes in memory + pub fn from_little_endian(slice: &[u8]) -> Self { + assert!($n_words * 8 >= slice.len()); + + let mut ret = [0; $n_words]; + unsafe { + let ret_u8: &mut [u8; $n_words * 8] = ::core::mem::transmute(&mut ret); + ret_u8[0..slice.len()].copy_from_slice(&slice); + } + + $name(ret) + } + + impl_std_for_uint_internals!($name, $n_words); + } + + impl Default for $name { + fn default() -> Self { + $name::zero() + } + } + + impl From for $name { + fn from(value: u64) -> $name { + let mut ret = [0; $n_words]; + ret[0] = value; + $name(ret) + } + } + + + impl_map_from!($name, u8, u64); + impl_map_from!($name, u16, u64); + impl_map_from!($name, u32, u64); + impl_map_from!($name, usize, u64); + + impl From for $name { + fn from(value: i64) -> $name { + match value >= 0 { + true => From::from(value as u64), + false => { panic!("Unsigned integer can't be created from negative value"); } + } + } + } + + impl_map_from!($name, i8, i64); + impl_map_from!($name, i16, i64); + impl_map_from!($name, i32, i64); + impl_map_from!($name, isize, i64); + + // Converts from big endian representation of U256 + impl<'a> From<&'a [u8]> for $name { + fn from(bytes: &[u8]) -> $name { + Self::from_big_endian(bytes) + } + } + + + impl ::core::ops::Add<$name> for $name { + type Output = $name; + + fn add(self, other: $name) -> $name { + let (result, overflow) = self.overflowing_add(other); + panic_on_overflow!(overflow); + result + } + } + + impl ::core::ops::Sub<$name> for $name { + type Output = $name; + + #[inline] + fn sub(self, other: $name) -> $name { + let (result, overflow) = self.overflowing_sub(other); + panic_on_overflow!(overflow); + result + } + } + + impl ::core::ops::Mul<$name> for $name { + type Output = $name; + + fn mul(self, other: $name) -> $name { + let (result, overflow) = self.overflowing_mul(other); + panic_on_overflow!(overflow); + result + } + } + + impl ::core::ops::Div<$name> for $name { + type Output = $name; + + fn div(self, other: $name) -> $name { + let mut sub_copy = self; + let mut shift_copy = other; + let mut ret = [0u64; $n_words]; + + let my_bits = self.bits(); + let your_bits = other.bits(); + + // Check for division by 0 + assert!(your_bits != 0); + + // Early return in case we are dividing by a larger number than us + if my_bits < your_bits { + return $name(ret); + } + + // Bitwise long division + let mut shift = my_bits - your_bits; + shift_copy = shift_copy << shift; + loop { + if sub_copy >= shift_copy { + ret[shift / 64] |= 1 << (shift % 64); + sub_copy = overflowing!(sub_copy.overflowing_sub(shift_copy)); + } + shift_copy = shift_copy >> 1; + if shift == 0 { break; } + shift -= 1; + } + + $name(ret) + } + } + + impl ::core::ops::Rem<$name> for $name { + type Output = $name; + + fn rem(self, other: $name) -> $name { + let times = self / other; + self - (times * other) + } + } + + impl ::core::ops::BitAnd<$name> for $name { + type Output = $name; + + #[inline] + fn bitand(self, other: $name) -> $name { + let $name(ref arr1) = self; + let $name(ref arr2) = other; + let mut ret = [0u64; $n_words]; + for i in 0..$n_words { + ret[i] = arr1[i] & arr2[i]; + } + $name(ret) + } + } + + impl ::core::ops::BitXor<$name> for $name { + type Output = $name; + + #[inline] + fn bitxor(self, other: $name) -> $name { + let $name(ref arr1) = self; + let $name(ref arr2) = other; + let mut ret = [0u64; $n_words]; + for i in 0..$n_words { + ret[i] = arr1[i] ^ arr2[i]; + } + $name(ret) + } + } + + impl ::core::ops::BitOr<$name> for $name { + type Output = $name; + + #[inline] + fn bitor(self, other: $name) -> $name { + let $name(ref arr1) = self; + let $name(ref arr2) = other; + let mut ret = [0u64; $n_words]; + for i in 0..$n_words { + ret[i] = arr1[i] | arr2[i]; + } + $name(ret) + } + } + + impl ::core::ops::Not for $name { + type Output = $name; + + #[inline] + fn not(self) -> $name { + let $name(ref arr) = self; + let mut ret = [0u64; $n_words]; + for i in 0..$n_words { + ret[i] = !arr[i]; + } + $name(ret) + } + } + + impl ::core::ops::Shl for $name { + type Output = $name; + + fn shl(self, shift: usize) -> $name { + let $name(ref original) = self; + let mut ret = [0u64; $n_words]; + let word_shift = shift / 64; + let bit_shift = shift % 64; + + // shift + for i in word_shift..$n_words { + ret[i] = original[i - word_shift] << bit_shift; + } + // carry + if bit_shift > 0 { + for i in word_shift+1..$n_words { + ret[i] += original[i - 1 - word_shift] >> (64 - bit_shift); + } + } + $name(ret) + } + } + + impl ::core::ops::Shr for $name { + type Output = $name; + + fn shr(self, shift: usize) -> $name { + let $name(ref original) = self; + let mut ret = [0u64; $n_words]; + let word_shift = shift / 64; + let bit_shift = shift % 64; + + // shift + for i in word_shift..$n_words { + ret[i - word_shift] = original[i] >> bit_shift; + } + + // Carry + if bit_shift > 0 { + for i in word_shift+1..$n_words { + ret[i - word_shift - 1] += original[i] << (64 - bit_shift); + } + } + + $name(ret) + } + } + + impl Ord for $name { + fn cmp(&self, other: &$name) -> ::core::cmp::Ordering { + let &$name(ref me) = self; + let &$name(ref you) = other; + let mut i = $n_words; + while i > 0 { + i -= 1; + if me[i] < you[i] { return ::core::cmp::Ordering::Less; } + if me[i] > you[i] { return ::core::cmp::Ordering::Greater; } + } + ::core::cmp::Ordering::Equal + } + } + + impl PartialOrd for $name { + fn partial_cmp(&self, other: &$name) -> Option<::core::cmp::Ordering> { + Some(self.cmp(other)) + } + } + + impl_std_for_uint!($name, $n_words); + impl_heapsize_for_uint!($name); + ); +} + +#[cfg(feature="std")] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_std_for_uint_internals { + ($name: ident, $n_words: tt) => { + /// Convert to hex string. + #[inline] + pub fn to_hex(&self) -> String { + use core::cmp; + use $crate::rustc_hex::ToHex;; + + if self.is_zero() { return "0".to_owned(); } // special case. + let mut bytes = [0u8; 8 * $n_words]; + self.to_big_endian(&mut bytes); + let bp7 = self.bits() + 7; + let len = cmp::max(bp7 / 8, 1); + let bytes_hex = bytes[bytes.len() - len..].to_hex(); + (&bytes_hex[1 - bp7 % 8 / 4..]).to_owned() + } + } +} + +#[cfg(feature="std")] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_std_for_uint { + ($name: ident, $n_words: tt) => { + impl ::core::fmt::Debug for $name { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Display::fmt(self, f) + } + } + + impl ::core::fmt::Display for $name { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if self.is_zero() { + return write!(f, "0"); + } + + let mut s = String::new(); + let mut current = *self; + let ten = $name::from(10); + + while !current.is_zero() { + s = format!("{}{}", (current % ten).low_u32(), s); + current = current / ten; + } + + write!(f, "{}", s) + } + } + + impl ::core::str::FromStr for $name { + type Err = $crate::rustc_hex::FromHexError; + + fn from_str(value: &str) -> Result<$name, Self::Err> { + use $crate::rustc_hex::FromHex; + + let bytes: Vec = match value.len() % 2 == 0 { + true => try!(value.from_hex()), + false => try!(("0".to_owned() + value).from_hex()) + }; + + let bytes_ref: &[u8] = &bytes; + Ok(From::from(bytes_ref)) + } + } + + impl ::core::fmt::LowerHex for $name { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + let &$name(ref data) = self; + try!(write!(f, "0x")); + let mut latch = false; + for ch in data.iter().rev() { + for x in 0..16 { + let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64); + if !latch { latch = nibble != 0 } + if latch { + try!(write!(f, "{:x}", nibble)); + } + } + } + Ok(()) + } + } + + impl From<&'static str> for $name { + fn from(s: &'static str) -> Self { + s.parse().unwrap() + } + } + } +} + +#[cfg(not(feature="std"))] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_std_for_uint_internals { + ($name: ident, $n_words: tt) => {} +} + +#[cfg(not(feature="std"))] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_std_for_uint { + ($name: ident, $n_words: tt) => {} +} + +#[cfg(feature="heapsizeof")] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_heapsize_for_uint { + ($name: ident) => { + impl $crate::heapsize::HeapSizeOf for $name { + fn heap_size_of_children(&self) -> usize { + 0 + } + } + } +} + +#[cfg(not(feature="heapsizeof"))] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_heapsize_for_uint { + ($name: ident) => {} +} From c4e00f8ca10a11707f40c94c800bf5ae15b8ff06 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 24 Oct 2017 16:09:44 +0800 Subject: [PATCH 02/76] ethereum-types refactor --- Cargo.toml | 10 + src/lib.rs | 14 + src/uint_tests.rs | 1180 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1204 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/lib.rs create mode 100644 src/uint_tests.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..539d2ab32 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "tests" +version = "0.1.0" +authors = ["debris "] + +[dependencies] +uint = { path = "../uint" } +ethereum-types = { path ="../ethereum-types", features = ["std", "heapsizeof"] } +crunchy = "0.1.5" +quickcheck = "0.4" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 000000000..10da28f24 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,14 @@ +extern crate core; +#[macro_use] +extern crate uint; +extern crate ethereum_types; +#[macro_use] +extern crate crunchy; +#[macro_use] +extern crate quickcheck; +//#[macro_use] +//extern crate uint; + +//extern crate rustc_hex; + +mod uint_tests; diff --git a/src/uint_tests.rs b/src/uint_tests.rs new file mode 100644 index 000000000..eebf2a89f --- /dev/null +++ b/src/uint_tests.rs @@ -0,0 +1,1180 @@ +use std::u64::MAX; +use std::str::FromStr; +use uint::FromDecStrErr; +use ethereum_types::{U128, U256, U512}; + +#[test] +pub fn uint256_from() { + let e = U256([10, 0, 0, 0]); + + // test unsigned initialization + let ua = U256::from(10u8); + let ub = U256::from(10u16); + let uc = U256::from(10u32); + let ud = U256::from(10u64); + assert_eq!(e, ua); + assert_eq!(e, ub); + assert_eq!(e, uc); + assert_eq!(e, ud); + + // test initialization from bytes + let va = U256::from(&[10u8][..]); + assert_eq!(e, va); + + // more tests for initialization from bytes + assert_eq!(U256([0x1010, 0, 0, 0]), U256::from(&[0x10u8, 0x10][..])); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from(&[0x12u8, 0xf0][..])); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from(&[0, 0x12u8, 0xf0][..])); + assert_eq!(U256([0x12f0, 0 , 0, 0]), U256::from(&[0, 0, 0, 0, 0, 0, 0, 0x12u8, 0xf0][..])); + assert_eq!(U256([0x12f0, 1 , 0, 0]), U256::from(&[1, 0, 0, 0, 0, 0, 0, 0x12u8, 0xf0][..])); + assert_eq!( + U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), + U256::from(& + [ + 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, + 0x09, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x77, + 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0x12u8, 0xf0 + ][..] + ) + ); + assert_eq!( + U256([0x00192437100019fa, 0x243710, 0, 0]), + U256::from(&[0x24u8, 0x37, 0x10,0, 0x19, 0x24, 0x37, 0x10, 0, 0x19, 0xfa][..]) + ); + + // test initializtion from string + let sa = U256::from_str("0a").unwrap(); + assert_eq!(e, sa); + assert_eq!(U256([0x1010, 0, 0, 0]), U256::from_str("1010").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0 , 0, 0]), U256::from_str("0000000012f0").unwrap()); + assert_eq!(U256([0x12f0, 1 , 0, 0]), U256::from_str("0100000000000012f0").unwrap()); + assert_eq!( + U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), + U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap() + ); +} + +#[test] +pub fn uint256_to() { + let hex = "8090a0b0c0d0e0f00910203040506077583a2cf8264910e1436bda32571012f0"; + let uint = U256::from_str(hex).unwrap(); + let mut bytes = [0u8; 32]; + uint.to_big_endian(&mut bytes); + let uint2 = U256::from(&bytes[..]); + assert_eq!(uint, uint2); +} + +#[test] +pub fn uint256_bits_test() { + assert_eq!(U256::from(0u64).bits(), 0); + assert_eq!(U256::from(255u64).bits(), 8); + assert_eq!(U256::from(256u64).bits(), 9); + assert_eq!(U256::from(300u64).bits(), 9); + assert_eq!(U256::from(60000u64).bits(), 16); + assert_eq!(U256::from(70000u64).bits(), 17); + + //// Try to read the following lines out loud quickly + let mut shl = U256::from(70000u64); + shl = shl << 100; + assert_eq!(shl.bits(), 117); + shl = shl << 100; + assert_eq!(shl.bits(), 217); + shl = shl << 100; + assert_eq!(shl.bits(), 0); + + //// Bit set check + //// 01010 + assert!(!U256::from(10u8).bit(0)); + assert!(U256::from(10u8).bit(1)); + assert!(!U256::from(10u8).bit(2)); + assert!(U256::from(10u8).bit(3)); + assert!(!U256::from(10u8).bit(4)); + + //// byte check + assert_eq!(U256::from(10u8).byte(0), 10); + assert_eq!(U256::from(0xffu64).byte(0), 0xff); + assert_eq!(U256::from(0xffu64).byte(1), 0); + assert_eq!(U256::from(0x01ffu64).byte(0), 0xff); + assert_eq!(U256::from(0x01ffu64).byte(1), 0x1); + assert_eq!(U256([0u64, 0xfc, 0, 0]).byte(8), 0xfc); + assert_eq!(U256([0u64, 0, 0, u64::max_value()]).byte(31), 0xff); + assert_eq!(U256([0u64, 0, 0, (u64::max_value() >> 8) + 1]).byte(31), 0x01); +} + +#[test] +#[cfg_attr(feature="dev", allow(eq_op))] +pub fn uint256_comp_test() { + let small = U256([10u64, 0, 0, 0]); + let big = U256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]); + let bigger = U256([0x9C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]); + let biggest = U256([0x5C8C3EE70C644118u64, 0x0209E7378231E632, 0, 1]); + + assert!(small < big); + assert!(big < bigger); + assert!(bigger < biggest); + assert!(bigger <= biggest); + assert!(biggest <= biggest); + assert!(bigger >= big); + assert!(bigger >= small); + assert!(small <= small); +} + +#[test] +pub fn uint256_arithmetic_test() { + let init = U256::from(0xDEADBEEFDEADBEEFu64); + let copy = init; + + let add = init + copy; + assert_eq!(add, U256([0xBD5B7DDFBD5B7DDEu64, 1, 0, 0])); + // Bitshifts + let shl = add << 88; + assert_eq!(shl, U256([0u64, 0xDFBD5B7DDE000000, 0x1BD5B7D, 0])); + let shr = shl >> 40; + assert_eq!(shr, U256([0x7DDE000000000000u64, 0x0001BD5B7DDFBD5B, 0, 0])); + // Increment + let incr = shr + U256::from(1u64); + assert_eq!(incr, U256([0x7DDE000000000001u64, 0x0001BD5B7DDFBD5B, 0, 0])); + // Subtraction + let sub = overflowing!(incr.overflowing_sub(init)); + assert_eq!(sub, U256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0])); + // Multiplication + let mult = sub.mul_u32(300); + assert_eq!(mult, U256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0])); + // Division + assert_eq!(U256::from(105u8) / U256::from(5u8), U256::from(21u8)); + let div = mult / U256::from(300u16); + assert_eq!(div, U256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0])); + + let a = U256::from_str("ff000000000000000000000000000000000000000000000000000000000000d1").unwrap(); + let b = U256::from_str("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2e").unwrap(); + println!("{:x}", a); + println!("{:x}", b); + assert_eq!(!a, b); + assert_eq!(a, !b); +} + +#[test] +pub fn uint256_simple_mul() { + let a = U256::from_str("10000000000000000").unwrap(); + let b = U256::from_str("10000000000000000").unwrap(); + + let c = U256::from_str("100000000000000000000000000000000").unwrap(); + println!("Multiplying"); + let result = a.overflowing_mul(b); + println!("Got result"); + assert_eq!(result, (c, false)) +} + +#[test] +pub fn uint256_extreme_bitshift_test() { + //// Shifting a u64 by 64 bits gives an undefined value, so make sure that + //// we're doing the Right Thing here + let init = U256::from(0xDEADBEEFDEADBEEFu64); + + assert_eq!(init << 64, U256([0, 0xDEADBEEFDEADBEEF, 0, 0])); + let add = (init << 64) + init; + assert_eq!(add, U256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); + assert_eq!(add >> 0, U256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); + assert_eq!(add << 0, U256([0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0, 0])); + assert_eq!(add >> 64, U256([0xDEADBEEFDEADBEEF, 0, 0, 0])); + assert_eq!(add << 64, U256([0, 0xDEADBEEFDEADBEEF, 0xDEADBEEFDEADBEEF, 0])); +} + +#[test] +pub fn uint256_exp10() { + assert_eq!(U256::exp10(0), U256::from(1u64)); + println!("\none: {:?}", U256::from(1u64)); + println!("ten: {:?}", U256::from(10u64)); + assert_eq!(U256::from(2u64) * U256::from(10u64), U256::from(20u64)); + assert_eq!(U256::exp10(1), U256::from(10u64)); + assert_eq!(U256::exp10(2), U256::from(100u64)); + assert_eq!(U256::exp10(5), U256::from(100000u64)); +} + +#[test] +pub fn uint256_mul32() { + assert_eq!(U256::from(0u64).mul_u32(2), U256::from(0u64)); + assert_eq!(U256::from(1u64).mul_u32(2), U256::from(2u64)); + assert_eq!(U256::from(10u64).mul_u32(2), U256::from(20u64)); + assert_eq!(U256::from(10u64).mul_u32(5), U256::from(50u64)); + assert_eq!(U256::from(1000u64).mul_u32(50), U256::from(50000u64)); +} + +#[test] +fn uint256_pow() { + assert_eq!(U256::from(10).pow(U256::from(0)), U256::from(1)); + assert_eq!(U256::from(10).pow(U256::from(1)), U256::from(10)); + assert_eq!(U256::from(10).pow(U256::from(2)), U256::from(100)); + assert_eq!(U256::from(10).pow(U256::from(3)), U256::from(1000)); + assert_eq!(U256::from(10).pow(U256::from(20)), U256::exp10(20)); +} + +#[test] +#[should_panic] +fn uint256_pow_overflow_panic() { + U256::from(2).pow(U256::from(0x100)); +} + +#[test] +fn should_format_hex_correctly() { + assert_eq!(&U256::from(0).to_hex(), &"0"); + assert_eq!(&U256::from(0x1).to_hex(), &"1"); + assert_eq!(&U256::from(0xf).to_hex(), &"f"); + assert_eq!(&U256::from(0x10).to_hex(), &"10"); + assert_eq!(&U256::from(0xff).to_hex(), &"ff"); + assert_eq!(&U256::from(0x100).to_hex(), &"100"); + assert_eq!(&U256::from(0xfff).to_hex(), &"fff"); + assert_eq!(&U256::from(0x1000).to_hex(), &"1000"); +} + +#[test] +fn uint256_overflowing_pow() { + // assert_eq!( + // U256::from(2).overflowing_pow(U256::from(0xff)), + // (U256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap(), false) + // ); + assert_eq!( + U256::from(2).overflowing_pow(U256::from(0x100)), + (U256::zero(), true) + ); +} + +#[test] +pub fn uint256_mul1() { + assert_eq!(U256::from(1u64) * U256::from(10u64), U256::from(10u64)); +} + +#[test] +pub fn uint256_mul2() { + let a = U512::from_str("10000000000000000fffffffffffffffe").unwrap(); + let b = U512::from_str("ffffffffffffffffffffffffffffffff").unwrap(); + + assert_eq!(a * b, U512::from_str("10000000000000000fffffffffffffffcffffffffffffffff0000000000000002").unwrap()); +} + +#[test] +pub fn uint256_overflowing_mul() { + assert_eq!( + U256::from_str("100000000000000000000000000000000").unwrap().overflowing_mul( + U256::from_str("100000000000000000000000000000000").unwrap() + ), + (U256::zero(), true) + ); +} + +#[test] +pub fn uint128_add() { + assert_eq!( + U128::from_str("fffffffffffffffff").unwrap() + U128::from_str("fffffffffffffffff").unwrap(), + U128::from_str("1ffffffffffffffffe").unwrap() + ); +} + +#[test] +pub fn uint128_add_overflow() { + assert_eq!( + U128::from_str("ffffffffffffffffffffffffffffffff").unwrap() + .overflowing_add( + U128::from_str("ffffffffffffffffffffffffffffffff").unwrap() + ), + (U128::from_str("fffffffffffffffffffffffffffffffe").unwrap(), true) + ); +} + +#[test] +#[should_panic] +#[cfg(debug_assertions)] +pub fn uint128_add_overflow_panic() { + U128::from_str("ffffffffffffffffffffffffffffffff").unwrap() + + + U128::from_str("ffffffffffffffffffffffffffffffff").unwrap(); +} + +#[test] +pub fn uint128_mul() { + assert_eq!( + U128::from_str("fffffffff").unwrap() * U128::from_str("fffffffff").unwrap(), + U128::from_str("ffffffffe000000001").unwrap()); +} + +#[test] +pub fn uint512_mul() { + assert_eq!( + U512::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() + * + U512::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(), + U512::from_str("3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001").unwrap() + ); +} + +#[test] +pub fn uint256_mul_overflow() { + assert_eq!( + U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() + .overflowing_mul( + U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() + ), + (U256::from_str("1").unwrap(), true) + ); +} + +#[test] +#[should_panic] +pub fn uint256_mul_overflow_panic() { + U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() + * + U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(); +} + +#[test] +pub fn uint256_sub_overflow() { + assert_eq!( + U256::from_str("0").unwrap() + .overflowing_sub( + U256::from_str("1").unwrap() + ), + (U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(), true) + ); +} + +#[test] +#[should_panic] +pub fn uint256_sub_overflow_panic() { + U256::from_str("0").unwrap() + - + U256::from_str("1").unwrap(); +} + +#[test] +pub fn uint256_shl() { + assert_eq!( + U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() + << 4, + U256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0").unwrap() + ); +} + +#[test] +pub fn uint256_shl_words() { + assert_eq!( + U256::from_str("0000000000000001ffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() + << 64, + U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000").unwrap() + ); + assert_eq!( + U256::from_str("0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() + << 64, + U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000").unwrap() + ); +} + +#[test] +pub fn uint256_mul() { + assert_eq!( + U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() + * + U256::from_str("2").unwrap(), + U256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe").unwrap() + ); +} + +#[test] +fn uint256_div() { + assert_eq!(U256::from(10u64) / U256::from(1u64), U256::from(10u64)); + assert_eq!(U256::from(10u64) / U256::from(2u64), U256::from(5u64)); + assert_eq!(U256::from(10u64) / U256::from(3u64), U256::from(3u64)); +} + +#[test] +fn uint256_rem() { + assert_eq!(U256::from(10u64) % U256::from(1u64), U256::from(0u64)); + assert_eq!(U256::from(10u64) % U256::from(3u64), U256::from(1u64)); +} + +#[test] +fn uint256_from_dec_str() { + assert_eq!(U256::from_dec_str("10").unwrap(), U256::from(10u64)); + assert_eq!(U256::from_dec_str("1024").unwrap(), U256::from(1024u64)); + assert_eq!(U256::from_dec_str("115792089237316195423570985008687907853269984665640564039457584007913129639936"), Err(FromDecStrErr::InvalidLength)); + assert_eq!(U256::from_dec_str("0x11"), Err(FromDecStrErr::InvalidCharacter)); +} + +#[test] +fn display_uint() { + let s = "12345678987654321023456789"; + assert_eq!(format!("{}", U256::from_dec_str(s).unwrap()), s); +} + +#[test] +fn display_uint_zero() { + assert_eq!(format!("{}", U256::from(0)), "0"); +} + +#[test] +fn u512_multi_adds() { + let (result, _) = U512([0, 0, 0, 0, 0, 0, 0, 0]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, 0])); + assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 0, 0])); + + let (result, _) = U512([1, 0, 0, 0, 0, 0, 0, 1]).overflowing_add(U512([1, 0, 0, 0, 0, 0, 0, 1])); + assert_eq!(result, U512([2, 0, 0, 0, 0, 0, 0, 2])); + + let (result, _) = U512([0, 0, 0, 0, 0, 0, 0, 1]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, 1])); + assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 0, 2])); + + let (result, _) = U512([0, 0, 0, 0, 0, 0, 2, 1]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 3, 1])); + assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 5, 2])); + + let (result, _) = U512([1, 2, 3, 4, 5, 6, 7, 8]).overflowing_add(U512([9, 10, 11, 12, 13, 14, 15, 16])); + assert_eq!(result, U512([10, 12, 14, 16, 18, 20, 22, 24])); + + let (_, overflow) = U512([0, 0, 0, 0, 0, 0, 2, 1]).overflowing_add(U512([0, 0, 0, 0, 0, 0, 3, 1])); + assert!(!overflow); + + let (_, overflow) = U512([MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX]) + .overflowing_add(U512([MAX, MAX, MAX, MAX, MAX, MAX, MAX, MAX])); + assert!(overflow); + + let (_, overflow) = U512([0, 0, 0, 0, 0, 0, 0, MAX]) + .overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, MAX])); + assert!(overflow); + + let (_, overflow) = U512([0, 0, 0, 0, 0, 0, 0, MAX]) + .overflowing_add(U512([0, 0, 0, 0, 0, 0, 0, 0])); + assert!(!overflow); +} + +#[test] +fn u256_multi_adds() { + let (result, _) = U256([0, 0, 0, 0]).overflowing_add(U256([0, 0, 0, 0])); + assert_eq!(result, U256([0, 0, 0, 0])); + + let (result, _) = U256([0, 0, 0, 1]).overflowing_add(U256([0, 0, 0, 1])); + assert_eq!(result, U256([0, 0, 0, 2])); + + let (result, overflow) = U256([0, 0, 2, 1]).overflowing_add(U256([0, 0, 3, 1])); + assert_eq!(result, U256([0, 0, 5, 2])); + assert!(!overflow); + + let (_, overflow) = U256([MAX, MAX, MAX, MAX]) + .overflowing_add(U256([MAX, MAX, MAX, MAX])); + assert!(overflow); + + let (_, overflow) = U256([0, 0, 0, MAX]).overflowing_add(U256([0, 0, 0, MAX])); + assert!(overflow); +} + + +#[test] +fn u256_multi_subs() { + let (result, _) = U256([0, 0, 0, 0]).overflowing_sub(U256([0, 0, 0, 0])); + assert_eq!(result, U256([0, 0, 0, 0])); + + let (result, _) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 0, 1])); + assert_eq!(result, U256([0, 0, 0, 0])); + + let (_, overflow) = U256([0, 0, 2, 1]).overflowing_sub(U256([0, 0, 3, 1])); + assert!(overflow); + + let (result, overflow) = + U256([MAX, MAX, MAX, MAX]) + .overflowing_sub(U256([MAX/2, MAX/2, MAX/2, MAX/2])); + + assert!(!overflow); + assert_eq!(U256([MAX/2+1, MAX/2+1, MAX/2+1, MAX/2+1]), result); + + let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([0, 0, 1, 0])); + assert!(!overflow); + assert_eq!(U256([0, 0, MAX, 0]), result); + + let (result, overflow) = U256([0, 0, 0, 1]).overflowing_sub(U256([1, 0, 0, 0])); + assert!(!overflow); + assert_eq!(U256([MAX, MAX, MAX, 0]), result); +} + +#[test] +fn u512_multi_subs() { + let (result, _) = U512([0, 0, 0, 0, 0, 0, 0, 0]).overflowing_sub(U512([0, 0, 0, 0, 0, 0, 0, 0])); + assert_eq!(result, U512([0, 0, 0, 0, 0, 0, 0, 0])); + + let (result, _) = U512([10, 9, 8, 7, 6, 5, 4, 3]).overflowing_sub(U512([9, 8, 7, 6, 5, 4, 3, 2])); + assert_eq!(result, U512([1, 1, 1, 1, 1, 1, 1, 1])); + + let (_, overflow) = U512([10, 9, 8, 7, 6, 5, 4, 3]).overflowing_sub(U512([9, 8, 7, 6, 5, 4, 3, 2])); + assert!(!overflow); + + let (_, overflow) = U512([9, 8, 7, 6, 5, 4, 3, 2]).overflowing_sub(U512([10, 9, 8, 7, 6, 5, 4, 3])); + assert!(overflow); +} + +#[test] +fn u256_multi_carry_all() { + let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U256([1, MAX-1, 0, 0]), result); + + let (result, _) = U256([0, MAX, 0, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U256([0, 1, MAX-1, 0]), result); + + let (result, _) = U256([MAX, MAX, 0, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U256([1, MAX, MAX-1, 0]), result); + + let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U256([1, MAX, MAX-1, 0]), result); + + let (result, _) = U256([MAX, MAX, 0, 0]) + .overflowing_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U256([1, 0, MAX-1, MAX]), result); + + let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U256([1, MAX, MAX, MAX-1]), result); + + let (result, _) = U256([MAX, MAX, MAX, 0]).overflowing_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U256([1, MAX, MAX, MAX-1]), result); + + let (result, _) = U256([MAX, 0, 0, 0]).overflowing_mul( + U256([MAX, MAX, MAX, MAX])); + assert_eq!(U256([1, MAX, MAX, MAX]), result); + + let (result, _) = U256([MAX, MAX, MAX, MAX]) + .overflowing_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U256([1, MAX, MAX, MAX]), result); + + let (result, _) = U256([MAX, MAX, MAX, 0]) + .overflowing_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U256([1, 0, MAX, MAX-1]), result); + + let (result, _) = U256([MAX, MAX, 0, 0]) + .overflowing_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U256([1, 0, MAX, MAX-1]), result); + + let (result, _) = U256([MAX, MAX, MAX, MAX]) + .overflowing_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U256([1, 0, MAX, MAX]), result); + + let (result, _) = U256([MAX, MAX, 0, 0]) + .overflowing_mul(U256([MAX, MAX, MAX, MAX])); + assert_eq!(U256([1, 0, MAX, MAX]), result); + + let (result, _) = U256([MAX, MAX, MAX, 0]) + .overflowing_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U256([1, 0, 0, MAX-1]), result); + + let (result, _) = U256([MAX, MAX, MAX, 0]) + .overflowing_mul(U256([MAX, MAX, MAX, MAX])); + assert_eq!(U256([1, 0, 0, MAX]), result); + + let (result, _) = U256([MAX, MAX, MAX, MAX]) + .overflowing_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U256([1, 0, 0, MAX]), result); + + let (result, _) = U256([0, 0, 0, MAX]).overflowing_mul(U256([0, 0, 0, MAX])); + assert_eq!(U256([0, 0, 0, 0]), result); + + let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); + assert_eq!(U256([0, 0, 0, MAX]), result); + + let (result, _) = U256([MAX, MAX, MAX, MAX]) + .overflowing_mul(U256([MAX, MAX, MAX, MAX])); + assert_eq!(U256([1, 0, 0, 0]), result); +} + +#[test] +fn u256_multi_muls() { + let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); + assert_eq!(U256([0, 0, 0, 0]), result); + + let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([1, 0, 0, 0])); + assert_eq!(U256([1, 0, 0, 0]), result); + + let (result, _) = U256([5, 0, 0, 0]).overflowing_mul(U256([5, 0, 0, 0])); + assert_eq!(U256([25, 0, 0, 0]), result); + + let (result, _) = U256([0, 5, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); + assert_eq!(U256([0, 0, 25, 0]), result); + + let (result, _) = U256([0, 0, 0, 1]).overflowing_mul(U256([1, 0, 0, 0])); + assert_eq!(U256([0, 0, 0, 1]), result); + + let (result, _) = U256([0, 0, 0, 5]).overflowing_mul(U256([2, 0, 0, 0])); + assert_eq!(U256([0, 0, 0, 10]), result); + + let (result, _) = U256([0, 0, 1, 0]).overflowing_mul(U256([0, 5, 0, 0])); + assert_eq!(U256([0, 0, 0, 5]), result); + + let (result, _) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); + assert_eq!(U256([0, 0, 0, 0]), result); + + let (result, _) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); + assert_eq!(U256([0, 10, 0, 0]), result); + + let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); + assert_eq!(U256([0, 0, 0, MAX]), result); +} + +#[test] +fn u256_multi_muls_overflow() { + let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); + assert!(!overflow); + + let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); + assert!(!overflow); + + let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX])); + assert!(overflow); + + let (_, overflow) = U256([0, 1, 0, 0]).overflowing_mul(U256([0, 1, 0, 0])); + assert!(!overflow); + + let (_, overflow) = U256([0, 1, 0, MAX]).overflowing_mul(U256([0, 1, 0, MAX])); + assert!(overflow); + + let (_, overflow) = U256([0, MAX, 0, 0]).overflowing_mul(U256([0, MAX, 0, 0])); + assert!(!overflow); + + let (_, overflow) = U256([1, 0, 0, 0]).overflowing_mul(U256([10, 0, 0, 0])); + assert!(!overflow); + + let (_, overflow) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, MAX / 2])); + assert!(!overflow); + + let (_, overflow) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); + assert!(overflow); +} + +#[test] +fn big_endian() { + let source = U256([1, 0, 0, 0]); + let mut target = vec![0u8; 32]; + + assert_eq!(source, U256::from(1)); + + source.to_big_endian(&mut target); + assert_eq!( + vec![0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, + 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8], + target); + + let source = U256([512, 0, 0, 0]); + let mut target = vec![0u8; 32]; + + source.to_big_endian(&mut target); + assert_eq!( + vec![0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, + 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8], + target); + + let source = U256([0, 512, 0, 0]); + let mut target = vec![0u8; 32]; + + source.to_big_endian(&mut target); + assert_eq!( + vec![0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, + 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8], + target); + + let source = U256::from_str("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20").unwrap(); + source.to_big_endian(&mut target); + assert_eq!( + vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20], + target); +} + +#[test] +#[cfg_attr(feature="dev", allow(cyclomatic_complexity))] +fn u256_multi_full_mul() { + let result = U256([0, 0, 0, 0]).full_mul(U256([0, 0, 0, 0])); + assert_eq!(U512([0, 0, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([1, 0, 0, 0]).full_mul(U256([1, 0, 0, 0])); + assert_eq!(U512([1, 0, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([5, 0, 0, 0]).full_mul(U256([5, 0, 0, 0])); + assert_eq!(U512([25, 0, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([0, 5, 0, 0]).full_mul(U256([0, 5, 0, 0])); + assert_eq!(U512([0, 0, 25, 0, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 0, 4]).full_mul(U256([4, 0, 0, 0])); + assert_eq!(U512([0, 0, 0, 16, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 0, 5]).full_mul(U256([2, 0, 0, 0])); + assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 2, 0]).full_mul(U256([0, 5, 0, 0])); + assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result); + + let result = U256([0, 3, 0, 0]).full_mul(U256([0, 0, 3, 0])); + assert_eq!(U512([0, 0, 0, 9, 0, 0, 0, 0]), result); + + let result = U256([0, 0, 8, 0]).full_mul(U256([0, 0, 6, 0])); + assert_eq!(U512([0, 0, 0, 0, 48, 0, 0, 0]), result); + + let result = U256([9, 0, 0, 0]).full_mul(U256([0, 3, 0, 0])); + assert_eq!(U512([0, 27, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U512([1, MAX-1, 0, 0, 0, 0, 0, 0]), result); + + let result = U256([0, MAX, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U512([0, 1, MAX-1, 0, 0, 0, 0, 0]), result); + + let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U512([1, MAX, MAX-1, 0, 0, 0, 0, 0]), result); + + let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U512([1, MAX, MAX-1, 0, 0, 0, 0, 0]), result); + + let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U512([1, 0, MAX-1, MAX, 0, 0, 0, 0]), result); + + let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U512([1, MAX, MAX, MAX-1, 0, 0, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U512([1, MAX, MAX, MAX-1, 0, 0, 0, 0]), result); + + let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); + assert_eq!(U512([1, MAX, MAX, MAX, MAX-1, 0, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, 0, 0, 0])); + assert_eq!(U512([1, MAX, MAX, MAX, MAX-1, 0, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U512([1, 0, MAX, MAX-1, MAX, 0, 0, 0]), result); + + let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U512([1, 0, MAX, MAX-1, MAX, 0, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, 0, 0])); + assert_eq!(U512([1, 0, MAX, MAX, MAX-1, MAX, 0, 0]), result); + + let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); + assert_eq!(U512([1, 0, MAX, MAX, MAX-1, MAX, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U512([1, 0, 0, MAX-1, MAX, MAX, 0, 0]), result); + + let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); + assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); + + let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, 0])); + assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); + + let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, MAX])); + assert_eq!(U512([1, 0, 0, 0, MAX-1, MAX, MAX, MAX]), result); + + let result = U256([0, 0, 0, MAX]).full_mul(U256([0, 0, 0, MAX])); + assert_eq!(U512([0, 0, 0, 0, 0, 0, 1, MAX-1]), result); + + let result = U256([1, 0, 0, 0]).full_mul(U256([0, 0, 0, MAX])); + assert_eq!(U512([0, 0, 0, MAX, 0, 0, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([5, 0, 0, 0])); + assert_eq!(U512([5, 10, 15, 20, 0, 0, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([0, 6, 0, 0])); + assert_eq!(U512([0, 6, 12, 18, 24, 0, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 7, 0])); + assert_eq!(U512([0, 0, 7, 14, 21, 28, 0, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 0, 8])); + assert_eq!(U512([0, 0, 0, 8, 16, 24, 32, 0]), result); + + let result = U256([1, 2, 3, 4]).full_mul(U256([5, 6, 7, 8])); + assert_eq!(U512([5, 16, 34, 60, 61, 52, 32, 0]), result); +} + +#[test] +fn u256_multi_muls2() { + + let (result, _) = U256([0, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, 0])); + assert_eq!(U256([0, 0, 0, 0]), result); + + let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([1, 0, 0, 0])); + assert_eq!(U256([1, 0, 0, 0]), result); + + let (result, _) = U256([5, 0, 0, 0]).overflowing_mul(U256([5, 0, 0, 0])); + assert_eq!(U256([25, 0, 0, 0]), result); + + let (result, _) = U256([0, 5, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); + assert_eq!(U256([0, 0, 25, 0]), result); + + let (result, _) = U256([0, 0, 0, 1]).overflowing_mul(U256([1, 0, 0, 0])); + assert_eq!(U256([0, 0, 0, 1]), result); + + let (result, _) = U256([0, 0, 0, 5]).overflowing_mul(U256([2, 0, 0, 0])); + assert_eq!(U256([0, 0, 0, 10]), result); + + let (result, _) = U256([0, 0, 1, 0]).overflowing_mul(U256([0, 5, 0, 0])); + assert_eq!(U256([0, 0, 0, 5]), result); + + let (result, _) = U256([0, 0, 8, 0]).overflowing_mul(U256([0, 0, 7, 0])); + assert_eq!(U256([0, 0, 0, 0]), result); + + let (result, _) = U256([2, 0, 0, 0]).overflowing_mul(U256([0, 5, 0, 0])); + assert_eq!(U256([0, 10, 0, 0]), result); + + let (result, _) = U256([1, 0, 0, 0]).overflowing_mul(U256([0, 0, 0, u64::max_value()])); + assert_eq!(U256([0, 0, 0, u64::max_value()]), result); + + let x1: U256 = "0000000000000000000000000000000000000000000000000000012365124623".into(); + let x2sqr_right: U256 = "000000000000000000000000000000000000000000014baeef72e0378e2328c9".into(); + let x1sqr = x1 * x1; + assert_eq!(x2sqr_right, x1sqr); + + let x1cube = x1sqr * x1; + let x1cube_right: U256 = "0000000000000000000000000000000001798acde139361466f712813717897b".into(); + assert_eq!(x1cube_right, x1cube); + + let x1quad = x1cube * x1; + let x1quad_right: U256 = "000000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1".into(); + assert_eq!(x1quad_right, x1quad); + + let x1penta = x1quad * x1; + let x1penta_right: U256 = "00000000000001e92875ac24be246e1c57e0507e8c46cc8d233b77f6f4c72993".into(); + assert_eq!(x1penta_right, x1penta); + + let x1septima = x1penta * x1; + let x1septima_right: U256 = "00022cca1da3f6e5722b7d3cc5bbfb486465ebc5a708dd293042f932d7eee119".into(); + assert_eq!(x1septima_right, x1septima); +} + +#[test] +fn example() { + let mut val: U256 = 1023.into(); + for _ in 0..200 { val = val * 2.into() } + assert_eq!(&format!("{}", val), "1643897619276947051879427220465009342380213662639797070513307648"); +} + +#[test] +fn little_endian() { + let number: U256 = "00022cca1da3f6e5722b7d3cc5bbfb486465ebc5a708dd293042f932d7eee119".into(); + let expected = [ + 0x19, 0xe1, 0xee, 0xd7, + 0x32, 0xf9, 0x42, 0x30, + 0x29, 0xdd, 0x08, 0xa7, + 0xc5, 0xeb, 0x65, 0x64, + 0x48, 0xfb, 0xbb, 0xc5, + 0x3c, 0x7d, 0x2b, 0x72, + 0xe5, 0xf6, 0xa3, 0x1d, + 0xca, 0x2c, 0x02, 0x00 + ]; + let mut result = [0u8; 32]; + number.to_little_endian(&mut result); + assert_eq!(expected, result); +} + +#[test] +fn slice_roundtrip() { + let raw = [ + 1u8, 2, 3, 5, 7, 11, 13, 17, + 19, 23, 29, 31, 37, 41, 43, 47, + 53, 59, 61, 67, 71, 73, 79, 83, + 89, 97, 101, 103, 107, 109, 113, 127 + ]; + + let u256: U256 = (&raw[..]).into(); + + let mut new_raw = [0u8; 32]; + + u256.to_big_endian(&mut new_raw); + + assert_eq!(&raw, &new_raw); +} + +#[test] +fn slice_roundtrip_le() { + let raw = [ + 1u8, 2, 3, 5, 7, 11, 13, 17, + 19, 23, 29, 31, 37, 41, 43, 47, + 53, 59, 61, 67, 71, 73, 79, 83, + 89, 97, 101, 103, 107, 109, 113, 127 + ]; + + let u256 = U256::from_little_endian(&raw[..]); + + let mut new_raw = [0u8; 32]; + + u256.to_little_endian(&mut new_raw); + + assert_eq!(&raw, &new_raw); +} + +#[test] +fn slice_roundtrip_le2() { + let raw = [ + 2, 3, 5, 7, 11, 13, 17, + 19, 23, 29, 31, 37, 41, 43, 47, + 53, 59, 61, 67, 71, 73, 79, 83, + 89, 97, 101, 103, 107, 109, 113, 127 + ]; + + let u256 = U256::from_little_endian(&raw[..]); + + let mut new_raw = [0u8; 32]; + + u256.to_little_endian(&mut new_raw); + + assert_eq!(&raw, &new_raw[..31]); +} + +#[test] +fn fixed_arrays_roundtrip() { + let raw: U256 = "7094875209347850239487502394881".into(); + let array: [u8; 32] = raw.into(); + let new_raw = array.into(); + + assert_eq!(raw, new_raw); +} + +#[test] +fn from_little_endian() { + let source: [u8; 32] = [ + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + ]; + + let number = U256::from_little_endian(&source[..]); + + assert_eq!(U256::from(1), number); +} + +#[test] +fn from_big_endian() { + let source: [u8; 32] = [ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, + ]; + + let number = U256::from_big_endian(&source[..]); + + assert_eq!(U256::from(1), number); +} + +#[test] +fn leading_zeros() { + assert_eq!(U256::from("000000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1").leading_zeros(), 95); + assert_eq!(U256::from("f00000000000000000000001adbdd6bd6ff027485484b97f8a6a4c7129756dd1").leading_zeros(), 0); + assert_eq!(U256::from("0000000000000000000000000000000000000000000000000000000000000001").leading_zeros(), 255); + assert_eq!(U256::from("0000000000000000000000000000000000000000000000000000000000000000").leading_zeros(), 256); +} + +#[test] +fn trailing_zeros() { + assert_eq!(U256::from("1adbdd6bd6ff027485484b97f8a6a4c7129756dd100000000000000000000000").trailing_zeros(), 92); + assert_eq!(U256::from("1adbdd6bd6ff027485484b97f8a6a4c7129756dd10000000000000000000000f").trailing_zeros(), 0); + assert_eq!(U256::from("8000000000000000000000000000000000000000000000000000000000000000").trailing_zeros(), 255); + assert_eq!(U256::from("0000000000000000000000000000000000000000000000000000000000000000").trailing_zeros(), 256); +} + +mod laws { + construct_uint!(U128, 2); + construct_uint!(U256, 4); + construct_uint!(U512, 8); + + macro_rules! uint_arbitrary { + ($uint:ty, $n_bytes:tt) => { + impl ::quickcheck::Arbitrary for $uint { + fn arbitrary(g: &mut G) -> Self { + let mut res = [0u8; $n_bytes]; + + let p = g.next_f64(); + let range = + if p < 0.1 { + $n_bytes + } else if p < 0.2 { + $n_bytes / 2 + } else { + $n_bytes / 5 + }; + + let size = g.gen_range(0, range); + g.fill_bytes(&mut res[..size]); + + res.as_ref().into() + } + } + } + } + + uint_arbitrary!(U128, 16); + uint_arbitrary!(U256, 32); + uint_arbitrary!(U512, 64); + + macro_rules! uint_laws { + ($mod_name:ident, $uint_ty:ident) => { + mod $mod_name { + use quickcheck::TestResult; + use super::{U128, U256, U512}; + + quickcheck! { + fn associative_add(x: $uint_ty, y: $uint_ty, z: $uint_ty) -> TestResult { + if x.overflowing_add(y).1 || y.overflowing_add(z).1 || (x + y).overflowing_add(z).1 { + return TestResult::discard(); + } + + TestResult::from_bool( + (x + y) + z == x + (y + z) + ) + } + } + + quickcheck! { + fn associative_mul(x: $uint_ty, y: $uint_ty, z: $uint_ty) -> TestResult { + if x.overflowing_mul(y).1 || y.overflowing_mul(z).1 || (x * y).overflowing_mul(z).1 { + return TestResult::discard(); + } + + TestResult::from_bool( + (x * y) * z == x * (y * z) + ) + } + } + + quickcheck! { + fn commutative_add(x: $uint_ty, y: $uint_ty) -> TestResult { + if x.overflowing_add(y).1 { + return TestResult::discard(); + } + + TestResult::from_bool( + x + y == y + x + ) + } + } + + quickcheck! { + fn commutative_mul(x: $uint_ty, y: $uint_ty) -> TestResult { + if x.overflowing_mul(y).1 { + return TestResult::discard(); + } + + TestResult::from_bool( + x * y == y * x + ) + } + } + + quickcheck! { + fn identity_add(x: $uint_ty) -> bool { + x + $uint_ty::zero() == x + } + } + + quickcheck! { + fn identity_mul(x: $uint_ty) -> bool { + x * $uint_ty::one() == x + } + } + + quickcheck! { + fn identity_div(x: $uint_ty) -> bool { + x / $uint_ty::one() == x + } + } + + quickcheck! { + fn absorbing_rem(x: $uint_ty) -> bool { + x % $uint_ty::one() == $uint_ty::zero() + } + } + + quickcheck! { + fn absorbing_sub(x: $uint_ty) -> bool { + x - x == $uint_ty::zero() + } + } + + quickcheck! { + fn absorbing_mul(x: $uint_ty) -> bool { + x * $uint_ty::zero() == $uint_ty::zero() + } + } + + quickcheck! { + fn distributive_mul_over_add(x: $uint_ty, y: $uint_ty, z: $uint_ty) -> TestResult { + if y.overflowing_add(z).1 || x.overflowing_mul(y + z).1 || x.overflowing_add(y).1 || (x + y).overflowing_mul(z).1 { + return TestResult::discard(); + } + + TestResult::from_bool( + (x * (y + z) == (x * y + x * z)) && (((x + y) * z) == (x * z + y * z)) + ) + } + } + + quickcheck! { + fn pow_mul(x: $uint_ty) -> TestResult { + if x.overflowing_pow($uint_ty::from(2)).1 || x.overflowing_pow($uint_ty::from(3)).1 { + return TestResult::discard(); + } + + TestResult::from_bool( + x.pow($uint_ty::from(2)) == x * x && x.pow($uint_ty::from(3)) == x * x * x + ) + } + } + + quickcheck! { + fn add_increases(x: $uint_ty, y: $uint_ty) -> TestResult { + if y.is_zero() || x.overflowing_add(y).1 { + return TestResult::discard(); + } + + TestResult::from_bool( + x + y > x + ) + } + } + + quickcheck! { + fn mul_increases(x: $uint_ty, y: $uint_ty) -> TestResult { + if y.is_zero() || x.overflowing_mul(y).1 { + return TestResult::discard(); + } + + TestResult::from_bool( + x * y >= x + ) + } + } + + quickcheck! { + fn div_decreases_dividend(x: $uint_ty, y: $uint_ty) -> TestResult { + if y.is_zero() { + return TestResult::discard(); + } + + TestResult::from_bool( + x / y <= x + ) + } + } + + quickcheck! { + fn rem_decreases_divisor(x: $uint_ty, y: $uint_ty) -> TestResult { + if y.is_zero() { + return TestResult::discard(); + } + + TestResult::from_bool( + x % y < y + ) + } + } + } + } + } + + uint_laws!(u128, U128); + uint_laws!(u256, U256); + uint_laws!(u512, U512); +} From c3b2b5cfb243bcd8656f7476317e120c5065277f Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 30 Oct 2017 10:00:58 -0700 Subject: [PATCH 03/76] ethereum-types refactor --- Cargo.toml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6fde4f889..ee7b70f55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,16 +12,13 @@ build = "build.rs" rustc_version = "0.2" [dependencies] -rustc-hex = { version = "1.0", optional = true } -heapsize = { version = "0.4", optional = true } byteorder = { version = "1", default-features = false } - -[dev-dependencies] -quickcheck = "0.4" +heapsize = { version = "0.4", optional = true } +rustc-hex = { version = "1.0", optional = true } [features] -heapsizeof = ["heapsize", "std"] std = ["rustc-hex"] +heapsizeof = ["heapsize"] [[example]] name = "modular" From 9dec8ff8de2e55c54c849a0a22cd3c29fb66af68 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 30 Oct 2017 10:00:58 -0700 Subject: [PATCH 04/76] ethereum-types refactor --- Cargo.toml | 14 ++ src/hash.rs | 395 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 29 ++++ 3 files changed, 438 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/hash.rs create mode 100644 src/lib.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..02e6015ad --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "fixed-hash" +version = "0.1.0" +authors = ["debris "] + +[dependencies] +heapsize = { version = "0.4", optional = true } +libc = { version = "0.2", default-features = false } +rand = { version = "0.3", optional = true } +rustc-hex = { version = "1.0", optional = true } + +[features] +std = ["rustc-hex", "rand"] +heapsizeof = ["heapsize"] diff --git a/src/hash.rs b/src/hash.rs new file mode 100644 index 000000000..a1472ec2d --- /dev/null +++ b/src/hash.rs @@ -0,0 +1,395 @@ +// Copyright 2015-2017 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// Return `s` without the `0x` at the beginning of it, if any. +pub fn clean_0x(s: &str) -> &str { + if s.starts_with("0x") { + &s[2..] + } else { + s + } +} + +#[macro_export] +macro_rules! impl_hash { + ($from: ident, $size: expr) => { + #[repr(C)] + /// Unformatted binary data of fixed length. + pub struct $from (pub [u8; $size]); + + + impl From<[u8; $size]> for $from { + fn from(bytes: [u8; $size]) -> Self { + $from(bytes) + } + } + + impl From<$from> for [u8; $size] { + fn from(s: $from) -> Self { + s.0 + } + } + + impl ::core::ops::Deref for $from { + type Target = [u8]; + + #[inline] + fn deref(&self) -> &[u8] { + &self.0 + } + } + + impl AsRef<[u8]> for $from { + #[inline] + fn as_ref(&self) -> &[u8] { + &self.0 + } + } + + impl ::core::ops::DerefMut for $from { + #[inline] + fn deref_mut(&mut self) -> &mut [u8] { + &mut self.0 + } + } + + impl $from { + /// Create a new, zero-initialised, instance. + pub fn new() -> $from { + $from([0; $size]) + } + + /// Synonym for `new()`. Prefer to new as it's more readable. + pub fn zero() -> $from { + $from([0; $size]) + } + + /// Get the size of this object in bytes. + pub fn len() -> usize { + $size + } + + #[inline] + /// Assign self to be of the same value as a slice of bytes of length `len()`. + pub fn clone_from_slice(&mut self, src: &[u8]) -> usize { + let min = ::core::cmp::min($size, src.len()); + self.0[..min].copy_from_slice(&src[..min]); + min + } + + /// Convert a slice of bytes of length `len()` to an instance of this type. + pub fn from_slice(src: &[u8]) -> Self { + let mut r = Self::new(); + r.clone_from_slice(src); + r + } + + /// Copy the data of this object into some mutable slice of length `len()`. + pub fn copy_to(&self, dest: &mut[u8]) { + let min = ::core::cmp::min($size, dest.len()); + dest[..min].copy_from_slice(&self.0[..min]); + } + + /// Returns `true` if all bits set in `b` are also set in `self`. + pub fn contains<'a>(&'a self, b: &'a Self) -> bool { + &(b & self) == b + } + + /// Returns `true` if no bits are set. + pub fn is_zero(&self) -> bool { + self.eq(&Self::new()) + } + + /// Returns the lowest 8 bytes interpreted as a BigEndian integer. + pub fn low_u64(&self) -> u64 { + let mut ret = 0u64; + for i in 0..::core::cmp::min($size, 8) { + ret |= (self.0[$size - 1 - i] as u64) << (i * 8); + } + ret + } + + impl_std_for_hash_internals!($from, $size); + } + + impl ::core::fmt::Debug for $from { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + for i in &self.0[..] { + write!(f, "{:02x}", i)?; + } + Ok(()) + } + } + + impl ::core::fmt::Display for $from { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + for i in &self.0[0..2] { + write!(f, "{:02x}", i)?; + } + write!(f, "…")?; + for i in &self.0[$size - 2..$size] { + write!(f, "{:02x}", i)?; + } + Ok(()) + } + } + + impl Copy for $from {} + #[cfg_attr(feature="dev", allow(expl_impl_clone_on_copy))] + impl Clone for $from { + fn clone(&self) -> $from { + let mut ret = $from::new(); + ret.0.copy_from_slice(&self.0); + ret + } + } + + impl Eq for $from {} + + impl PartialEq for $from { + fn eq(&self, other: &Self) -> bool { + unsafe { $crate::libc::memcmp(self.0.as_ptr() as *const $crate::libc::c_void, other.0.as_ptr() as *const $crate::libc::c_void, $size) == 0 } + } + } + + impl Ord for $from { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { + let r = unsafe { $crate::libc::memcmp(self.0.as_ptr() as *const $crate::libc::c_void, other.0.as_ptr() as *const $crate::libc::c_void, $size) }; + if r < 0 { return ::core::cmp::Ordering::Less } + if r > 0 { return ::core::cmp::Ordering::Greater } + return ::core::cmp::Ordering::Equal; + } + } + + impl PartialOrd for $from { + fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> { + Some(self.cmp(other)) + } + } + + impl ::core::hash::Hash for $from { + fn hash(&self, state: &mut H) where H: ::core::hash::Hasher { + state.write(&self.0); + state.finish(); + } + } + + impl ::core::ops::Index for $from { + type Output = u8; + + fn index(&self, index: usize) -> &u8 { + &self.0[index] + } + } + impl ::core::ops::IndexMut for $from { + fn index_mut(&mut self, index: usize) -> &mut u8 { + &mut self.0[index] + } + } + impl ::core::ops::Index<::core::ops::Range> for $from { + type Output = [u8]; + + fn index(&self, index: ::core::ops::Range) -> &[u8] { + &self.0[index] + } + } + impl ::core::ops::IndexMut<::core::ops::Range> for $from { + fn index_mut(&mut self, index: ::core::ops::Range) -> &mut [u8] { + &mut self.0[index] + } + } + impl ::core::ops::Index<::core::ops::RangeFull> for $from { + type Output = [u8]; + + fn index(&self, _index: ::core::ops::RangeFull) -> &[u8] { + &self.0 + } + } + impl ::core::ops::IndexMut<::core::ops::RangeFull> for $from { + fn index_mut(&mut self, _index: ::core::ops::RangeFull) -> &mut [u8] { + &mut self.0 + } + } + + /// `BitOr` on references + impl<'a> ::core::ops::BitOr for &'a $from { + type Output = $from; + + fn bitor(self, rhs: Self) -> Self::Output { + let mut ret: $from = $from::default(); + for i in 0..$size { + ret.0[i] = self.0[i] | rhs.0[i]; + } + ret + } + } + + /// Moving `BitOr` + impl ::core::ops::BitOr for $from { + type Output = $from; + + fn bitor(self, rhs: Self) -> Self::Output { + &self | &rhs + } + } + + /// `BitAnd` on references + impl <'a> ::core::ops::BitAnd for &'a $from { + type Output = $from; + + fn bitand(self, rhs: Self) -> Self::Output { + let mut ret: $from = $from::default(); + for i in 0..$size { + ret.0[i] = self.0[i] & rhs.0[i]; + } + ret + } + } + + /// Moving `BitAnd` + impl ::core::ops::BitAnd for $from { + type Output = $from; + + fn bitand(self, rhs: Self) -> Self::Output { + &self & &rhs + } + } + + /// `BitXor` on references + impl <'a> ::core::ops::BitXor for &'a $from { + type Output = $from; + + fn bitxor(self, rhs: Self) -> Self::Output { + let mut ret: $from = $from::default(); + for i in 0..$size { + ret.0[i] = self.0[i] ^ rhs.0[i]; + } + ret + } + } + + /// Moving `BitXor` + impl ::core::ops::BitXor for $from { + type Output = $from; + + fn bitxor(self, rhs: Self) -> Self::Output { + &self ^ &rhs + } + } + + impl Default for $from { + fn default() -> Self { $from::new() } + } + + impl From for $from { + fn from(mut value: u64) -> $from { + let mut ret = $from::new(); + for i in 0..8 { + if i < $size { + ret.0[$size - i - 1] = (value & 0xff) as u8; + value >>= 8; + } + } + ret + } + } + + impl<'a> From<&'a [u8]> for $from { + fn from(s: &'a [u8]) -> $from { + $from::from_slice(s) + } + } + + impl_std_for_hash!($from, $size); + } +} + +#[cfg(feature="std")] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_std_for_hash { + ($from: ident, $size: tt) => { + impl $from { + /// Get a hex representation. + pub fn hex(&self) -> String { + format!("{:?}", self) + } + } + + impl $crate::rand::Rand for $from { + fn rand(r: &mut R) -> Self { + let mut hash = $from::new(); + r.fill_bytes(&mut hash.0); + hash + } + } + + impl ::core::str::FromStr for $from { + type Err = $crate::rustc_hex::FromHexError; + + fn from_str(s: &str) -> Result<$from, $crate::rustc_hex::FromHexError> { + use $crate::rustc_hex::FromHex; + let a = s.from_hex()?; + if a.len() != $size { + return Err($crate::rustc_hex::FromHexError::InvalidHexLength); + } + + let mut ret = [0; $size]; + ret.copy_from_slice(&a); + Ok($from(ret)) + } + } + + impl From<&'static str> for $from { + fn from(s: &'static str) -> $from { + let s = $crate::clean_0x(s); + if s.len() % 2 == 1 { + ("0".to_owned() + s).parse().unwrap() + } else { + s.parse().unwrap() + } + } + } + } +} + + +#[cfg(not(feature="std"))] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_std_for_hash { + ($from: ident, $size: tt) => {} +} + + +#[cfg(feature="std")] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_std_for_hash_internals { + ($from: ident, $size: tt) => { + /// Create a new, cryptographically random, instance. + pub fn random() -> $from { + let mut hash = $from::new(); + hash.randomize(); + hash + } + + /// Assign self have a cryptographically random value. + pub fn randomize(&mut self) { + let mut rng = $crate::rand::OsRng::new().unwrap(); + *self = $crate::rand::Rand::rand(&mut rng); + } + } +} + +#[cfg(not(feature="std"))] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_std_for_hash_internals { + ($from: ident, $size: tt) => {} +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 000000000..0888b593f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,29 @@ +// Copyright 2015-2017 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[doc(hidden)] +pub extern crate libc; + +#[cfg(feature="heapsizeof")] +#[doc(hidden)] +pub extern crate heapsize; + +#[cfg(feature="std")] +#[doc(hidden)] +pub extern crate core; + +#[cfg(feature="std")] +#[doc(hidden)] +pub extern crate rustc_hex; + +#[cfg(feature="std")] +#[doc(hidden)] +pub extern crate rand; + +mod hash; +pub use hash::*; From 845d30535937d137c8132c246f7f4cc3e9e8a001 Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 30 Oct 2017 10:00:58 -0700 Subject: [PATCH 05/76] ethereum-types refactor --- Cargo.toml | 4 ++-- src/lib.rs | 10 +++++----- src/uint_tests.rs | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 539d2ab32..6734e3731 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["debris "] [dependencies] -uint = { path = "../uint" } -ethereum-types = { path ="../ethereum-types", features = ["std", "heapsizeof"] } crunchy = "0.1.5" +ethereum-types = { path ="../ethereum-types", features = ["std", "heapsizeof"] } quickcheck = "0.4" +uint = { path = "../uint" } diff --git a/src/lib.rs b/src/lib.rs index 10da28f24..2e0befac5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,14 @@ extern crate core; +#[cfg(test)] #[macro_use] extern crate uint; extern crate ethereum_types; +#[cfg(test)] #[macro_use] extern crate crunchy; +#[cfg(test)] #[macro_use] extern crate quickcheck; -//#[macro_use] -//extern crate uint; -//extern crate rustc_hex; - -mod uint_tests; +#[cfg(test)] +pub mod uint_tests; diff --git a/src/uint_tests.rs b/src/uint_tests.rs index eebf2a89f..1c5351e94 100644 --- a/src/uint_tests.rs +++ b/src/uint_tests.rs @@ -975,7 +975,7 @@ fn trailing_zeros() { assert_eq!(U256::from("0000000000000000000000000000000000000000000000000000000000000000").trailing_zeros(), 256); } -mod laws { +pub mod laws { construct_uint!(U128, 2); construct_uint!(U256, 4); construct_uint!(U512, 8); @@ -1013,7 +1013,7 @@ mod laws { ($mod_name:ident, $uint_ty:ident) => { mod $mod_name { use quickcheck::TestResult; - use super::{U128, U256, U512}; + use super::{$uint_ty}; quickcheck! { fn associative_add(x: $uint_ty, y: $uint_ty, z: $uint_ty) -> TestResult { From 91b87cd91eaa9b5c26518cce48ba4cf55c13bd9e Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 14 Nov 2017 15:38:09 +0100 Subject: [PATCH 06/76] unify hash macro by renaming it to `construct_hash` --- Cargo.toml | 3 +++ examples/modular.rs | 9 ++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ee7b70f55..8751dc2bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,9 @@ byteorder = { version = "1", default-features = false } heapsize = { version = "0.4", optional = true } rustc-hex = { version = "1.0", optional = true } +[dev-dependencies] +crunchy = "0.1.5" + [features] std = ["rustc-hex"] heapsizeof = ["heapsize"] diff --git a/examples/modular.rs b/examples/modular.rs index 06a808a1e..1db193f8b 100644 --- a/examples/modular.rs +++ b/examples/modular.rs @@ -6,9 +6,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[cfg(feature="std")] +extern crate core; + +#[macro_use] +extern crate crunchy; + +#[macro_use] extern crate uint; -use uint::U256; +construct_uint!(U256, 32); fn main() { // Example modular arithmetic using bigint U256 primitives From 2791a94db7cc36dba3564b25ea2daddc91505c23 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 14 Nov 2017 15:38:09 +0100 Subject: [PATCH 07/76] unify hash macro by renaming it to `construct_hash` --- src/hash.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hash.rs b/src/hash.rs index a1472ec2d..fb2aeedf7 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -16,7 +16,7 @@ pub fn clean_0x(s: &str) -> &str { } #[macro_export] -macro_rules! impl_hash { +macro_rules! construct_hash { ($from: ident, $size: expr) => { #[repr(C)] /// Unformatted binary data of fixed length. From 83df0b7baa410ac67656cbfa938da5892c3154c5 Mon Sep 17 00:00:00 2001 From: snd Date: Tue, 5 Dec 2017 13:14:16 +0100 Subject: [PATCH 08/76] Issue 6 (#7) * add rustc_version to build deps of ether types (needed by build script) * ethereum-types: add build script that sets cargo:rustc-cfg=asm_available on nightly * ethereum-types: #![cfg_attr(asm_available, feature(asm))] * tests: add the whole feature asm build script to make it pass on nightly CI * add #![cfg_attr(asm_available, feature(asm))] directly where needed so users don't have to add it * remove tests/build.rs since it should not be needed anymore * move inner cfg_attr attributes to the right allowed position * remove check for asm_available in contexts that already have check for that --- src/lib.rs | 2 -- src/uint.rs | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4a3dc8afa..01d41a73a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,8 +8,6 @@ //! Efficient large, fixed-size big integers and hashes. -#![cfg_attr(asm_available, feature(asm))] - #[doc(hidden)] pub extern crate byteorder; diff --git a/src/uint.rs b/src/uint.rs index 39e7aca7e..11da94e4c 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -77,6 +77,7 @@ macro_rules! uint_overflowing_add_reg { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_add { + #![feature(asm)] (U256, $n_words:tt, $self_expr: expr, $other: expr) => ({ let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; let self_t: &[u64; $n_words] = &$self_expr.0; @@ -223,6 +224,7 @@ macro_rules! uint_overflowing_sub_reg { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_sub { + #![feature(asm)] (U256, $n_words:tt, $self_expr: expr, $other: expr) => ({ let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; let self_t: &[u64; $n_words] = &$self_expr.0; @@ -277,7 +279,7 @@ macro_rules! uint_overflowing_sub { "={al}"(overflow) /* $0 - $4 */ : "{rdi}"(&result[4] as *const u64) /* $5 */ - "{rsi}"(&self_t[4] as *const u64) /* $6 */ + "{rsi}"(&self_t[4] as *const u64) /* $6 */ "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), "m"(self_t[4]), "m"(self_t[5]), "m"(self_t[6]), "m"(self_t[7]), /* $7 - $14 */ @@ -298,6 +300,7 @@ macro_rules! uint_overflowing_sub { #[cfg(all(asm_available, target_arch="x86_64"))] #[macro_export] macro_rules! uint_overflowing_mul { + #![feature(asm)] (U256, $n_words: expr, $self_expr: expr, $other: expr) => ({ let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; let self_t: &[u64; $n_words] = &$self_expr.0; From 45f721cf6ece85e475152eb01c05cda088bc87cb Mon Sep 17 00:00:00 2001 From: snd Date: Tue, 5 Dec 2017 14:44:36 +0100 Subject: [PATCH 09/76] feature(asm) is only allowed in crate (#8) * feature(asm) is only allowed in crate * add tests/build.rs again - haven't found a way around it --- src/lib.rs | 2 ++ src/uint.rs | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 01d41a73a..4a3dc8afa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,8 @@ //! Efficient large, fixed-size big integers and hashes. +#![cfg_attr(asm_available, feature(asm))] + #[doc(hidden)] pub extern crate byteorder; diff --git a/src/uint.rs b/src/uint.rs index 11da94e4c..e3260bdb4 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -77,7 +77,6 @@ macro_rules! uint_overflowing_add_reg { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_add { - #![feature(asm)] (U256, $n_words:tt, $self_expr: expr, $other: expr) => ({ let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; let self_t: &[u64; $n_words] = &$self_expr.0; @@ -224,7 +223,6 @@ macro_rules! uint_overflowing_sub_reg { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_sub { - #![feature(asm)] (U256, $n_words:tt, $self_expr: expr, $other: expr) => ({ let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; let self_t: &[u64; $n_words] = &$self_expr.0; @@ -300,7 +298,6 @@ macro_rules! uint_overflowing_sub { #[cfg(all(asm_available, target_arch="x86_64"))] #[macro_export] macro_rules! uint_overflowing_mul { - #![feature(asm)] (U256, $n_words: expr, $self_expr: expr, $other: expr) => ({ let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; let self_t: &[u64; $n_words] = &$self_expr.0; From d0f9df071995848f3941e757acf4d1b32112f223 Mon Sep 17 00:00:00 2001 From: snd Date: Tue, 5 Dec 2017 14:44:36 +0100 Subject: [PATCH 10/76] feature(asm) is only allowed in crate (#8) * feature(asm) is only allowed in crate * add tests/build.rs again - haven't found a way around it --- Cargo.toml | 3 +++ build.rs | 17 +++++++++++++++++ src/lib.rs | 2 ++ 3 files changed, 22 insertions(+) create mode 100644 build.rs diff --git a/Cargo.toml b/Cargo.toml index 6734e3731..4450162ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,9 @@ name = "tests" version = "0.1.0" authors = ["debris "] +[build-dependencies] +rustc_version = "0.2" + [dependencies] crunchy = "0.1.5" ethereum-types = { path ="../ethereum-types", features = ["std", "heapsizeof"] } diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..432acc3f4 --- /dev/null +++ b/build.rs @@ -0,0 +1,17 @@ +// Copyright 2015-2017 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate rustc_version; + +use rustc_version::{version_meta, Channel}; + +fn main() { + if let Channel::Nightly = version_meta().unwrap().channel { + println!("cargo:rustc-cfg=asm_available"); + } +} diff --git a/src/lib.rs b/src/lib.rs index 2e0befac5..342dbefd0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(asm_available, feature(asm))] + extern crate core; #[cfg(test)] #[macro_use] From 71b84a24d446d096038763ae8e8114105630704f Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 29 Dec 2017 17:21:04 +0100 Subject: [PATCH 11/76] updated fixed-hash manifest --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 02e6015ad..968ea2a33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,9 @@ name = "fixed-hash" version = "0.1.0" authors = ["debris "] +license = "MIT" +homepage = "https://github.com/paritytech/primitives" +description = "Fixed-size hashes" [dependencies] heapsize = { version = "0.4", optional = true } From 9e23e8f4a3e80cc36d8321c980f00b7857b58982 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 29 Dec 2017 17:23:16 +0100 Subject: [PATCH 12/76] updated uint manifest --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 8751dc2bf..c37a00c96 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Large fixed-size integers arithmetics" homepage = "http://parity.io" -repository = "https://github.com/ethcore/bigint" +repository = "https://github.com/paritytech/primitives" license = "MIT/Apache-2.0" name = "uint" version = "0.1.0" From 7bae79915dccff98cdaabcff7e76b416812f6f5c Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 2 Jan 2018 15:40:16 +0100 Subject: [PATCH 13/76] fixed-hash implements heap-size, version 0.1.1 --- Cargo.toml | 2 +- src/hash.rs | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 968ea2a33..98f704516 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fixed-hash" -version = "0.1.0" +version = "0.1.1" authors = ["debris "] license = "MIT" homepage = "https://github.com/paritytech/primitives" diff --git a/src/hash.rs b/src/hash.rs index fb2aeedf7..5384f7f1b 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -306,9 +306,30 @@ macro_rules! construct_hash { } impl_std_for_hash!($from, $size); + impl_heapsize_for_hash!($from); } } +#[cfg(feature="heapsizeof")] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_heapsize_for_hash { + ($name: ident) => { + impl $crate::heapsize::HeapSizeOf for $name { + fn heap_size_of_children(&self) -> usize { + 0 + } + } + } +} + +#[cfg(not(feature="heapsizeof"))] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_heapsize_for_hash { + ($name: ident) => {} +} + #[cfg(feature="std")] #[macro_export] #[doc(hidden)] From f1e6fbee9ef8625d4e06b7adc2d8b7307ec646da Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 5 Jan 2018 17:42:29 +0100 Subject: [PATCH 14/76] ethbloom crate --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 98f704516..1049b08ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ description = "Fixed-size hashes" [dependencies] heapsize = { version = "0.4", optional = true } libc = { version = "0.2", default-features = false } -rand = { version = "0.3", optional = true } +rand = { version = "0.4", optional = true } rustc-hex = { version = "1.0", optional = true } [features] From 2ea80de13c3a4e050b96d7408c94da42de3e6163 Mon Sep 17 00:00:00 2001 From: debris Date: Fri, 5 Jan 2018 17:42:29 +0100 Subject: [PATCH 15/76] ethbloom crate --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4450162ec..4fe20430b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,5 +9,5 @@ rustc_version = "0.2" [dependencies] crunchy = "0.1.5" ethereum-types = { path ="../ethereum-types", features = ["std", "heapsizeof"] } -quickcheck = "0.4" +quickcheck = "0.6" uint = { path = "../uint" } From d741c2f686962a4a75e8ab3f4094816bf4874d0b Mon Sep 17 00:00:00 2001 From: debris Date: Sat, 20 Jan 2018 21:21:15 +0100 Subject: [PATCH 16/76] fixed-hash 0.1.2 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1049b08ce..35c976604 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fixed-hash" -version = "0.1.1" +version = "0.1.2" authors = ["debris "] license = "MIT" homepage = "https://github.com/paritytech/primitives" From 0aab3c4cbe5e53cc31ad8b46db0f46e487418d99 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 23 Jan 2018 14:25:15 +0100 Subject: [PATCH 17/76] add default serde serialization to ethereum-types --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4fe20430b..e7b2b21d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tests" version = "0.1.0" -authors = ["debris "] +authors = ["Parity Technologies "] [build-dependencies] rustc_version = "0.2" From 4c709def97ce9495f2cd52931c8650d0565f3f60 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 23 Jan 2018 14:25:15 +0100 Subject: [PATCH 18/76] add default serde serialization to ethereum-types --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 35c976604..a218d3523 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "fixed-hash" version = "0.1.2" -authors = ["debris "] +authors = ["Parity Technologies "] license = "MIT" homepage = "https://github.com/paritytech/primitives" description = "Fixed-size hashes" From ea29612eaafc394378dd52c11109d45c024b0222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 28 Jan 2018 17:03:47 +0100 Subject: [PATCH 19/76] Checked ops. --- src/uint.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src/uint.rs b/src/uint.rs index e3260bdb4..47cee3fac 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -815,6 +815,14 @@ macro_rules! construct_uint { } } + /// Checked addition. Returns `None` if overflow occurred. + pub fn checked_add(self, other: $name) -> Option<$name> { + match self.overflowing_add(other) { + (_, true) => None, + (val, _) => Some(val), + } + } + /// Subtraction which underflows and returns a flag if it does. #[inline(always)] pub fn overflowing_sub(self, other: $name) -> ($name, bool) { @@ -829,6 +837,14 @@ macro_rules! construct_uint { } } + /// Checked subtraction. Returns `None` if overflow occurred. + pub fn checked_sub(self, other: $name) -> Option<$name> { + match self.overflowing_sub(other) { + (_, true) => None, + (val, _) => Some(val), + } + } + /// Multiply with overflow, returning a flag if it does. #[inline(always)] pub fn overflowing_mul(self, other: $name) -> ($name, bool) { @@ -843,21 +859,59 @@ macro_rules! construct_uint { } } + /// Checked multiplication. Returns `None` if overflow occurred. + pub fn checked_mul(self, other: $name) -> Option<$name> { + match self.overflowing_mul(other) { + (_, true) => None, + (val, _) => Some(val), + } + } + /// Division with overflow pub fn overflowing_div(self, other: $name) -> ($name, bool) { (self / other, false) } + /// Checked division. Returns `None` if `other == 0`. + pub fn checked_div(self, other: $name) -> Option<$name> { + if other.is_zero() { + None + } else { + Some(self / other) + } + } + /// Modulus with overflow. pub fn overflowing_rem(self, other: $name) -> ($name, bool) { (self % other, false) } + /// Checked modulus. Returns `None` if `other == 0`. + pub fn checked_rem(self, other: $name) -> Option<$name> { + if other.is_zero() { + None + } else { + Some(self % other) + } + } + /// Negation with overflow. pub fn overflowing_neg(self) -> ($name, bool) { - (!self, true) + if self.is_zero() { + (self, false) + } else { + (!self, true) + } } + /// Checked negation. Returns `None` unless `self == 0`. + pub fn checked_neg(self) -> Option<$name> { + match self.overflowing_neg() { + (_, true) => None, + (zero, false) => Some(zero), + } + } + /// Multiplication by u32 pub fn mul_u32(self, other: u32) -> Self { let (ret, overflow) = self.overflowing_mul_u32(other); From 61cbcd73c6b397568b170179d74b279f0f007448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 28 Jan 2018 17:03:47 +0100 Subject: [PATCH 20/76] Checked ops. --- src/uint_tests.rs | 73 +++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/src/uint_tests.rs b/src/uint_tests.rs index 1c5351e94..9f95c6fa4 100644 --- a/src/uint_tests.rs +++ b/src/uint_tests.rs @@ -4,7 +4,32 @@ use uint::FromDecStrErr; use ethereum_types::{U128, U256, U512}; #[test] -pub fn uint256_from() { +fn uint256_checked_ops() { + let z = U256::from(0); + let a = U256::from(10); + let b = !U256::from(1); + + assert_eq!(a.checked_add(b), None); + assert_eq!(a.checked_add(a), Some(20.into())); + + assert_eq!(a.checked_sub(b), None); + assert_eq!(a.checked_sub(a), Some(0.into())); + + assert_eq!(a.checked_mul(b), None); + assert_eq!(a.checked_mul(a), Some(100.into())); + + assert_eq!(a.checked_div(z), None); + assert_eq!(a.checked_div(a), Some(1.into())); + + assert_eq!(a.checked_rem(z), None); + assert_eq!(a.checked_rem(a), Some(0.into())); + + assert_eq!(a.checked_neg(), None); + assert_eq!(z.checked_neg(), Some(z)); +} + +#[test] +fn uint256_from() { let e = U256([10, 0, 0, 0]); // test unsigned initialization @@ -58,7 +83,7 @@ pub fn uint256_from() { } #[test] -pub fn uint256_to() { +fn uint256_to() { let hex = "8090a0b0c0d0e0f00910203040506077583a2cf8264910e1436bda32571012f0"; let uint = U256::from_str(hex).unwrap(); let mut bytes = [0u8; 32]; @@ -68,7 +93,7 @@ pub fn uint256_to() { } #[test] -pub fn uint256_bits_test() { +fn uint256_bits_test() { assert_eq!(U256::from(0u64).bits(), 0); assert_eq!(U256::from(255u64).bits(), 8); assert_eq!(U256::from(256u64).bits(), 9); @@ -106,7 +131,7 @@ pub fn uint256_bits_test() { #[test] #[cfg_attr(feature="dev", allow(eq_op))] -pub fn uint256_comp_test() { +fn uint256_comp_test() { let small = U256([10u64, 0, 0, 0]); let big = U256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]); let bigger = U256([0x9C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0]); @@ -123,7 +148,7 @@ pub fn uint256_comp_test() { } #[test] -pub fn uint256_arithmetic_test() { +fn uint256_arithmetic_test() { let init = U256::from(0xDEADBEEFDEADBEEFu64); let copy = init; @@ -157,7 +182,7 @@ pub fn uint256_arithmetic_test() { } #[test] -pub fn uint256_simple_mul() { +fn uint256_simple_mul() { let a = U256::from_str("10000000000000000").unwrap(); let b = U256::from_str("10000000000000000").unwrap(); @@ -169,7 +194,7 @@ pub fn uint256_simple_mul() { } #[test] -pub fn uint256_extreme_bitshift_test() { +fn uint256_extreme_bitshift_test() { //// Shifting a u64 by 64 bits gives an undefined value, so make sure that //// we're doing the Right Thing here let init = U256::from(0xDEADBEEFDEADBEEFu64); @@ -184,7 +209,7 @@ pub fn uint256_extreme_bitshift_test() { } #[test] -pub fn uint256_exp10() { +fn uint256_exp10() { assert_eq!(U256::exp10(0), U256::from(1u64)); println!("\none: {:?}", U256::from(1u64)); println!("ten: {:?}", U256::from(10u64)); @@ -195,7 +220,7 @@ pub fn uint256_exp10() { } #[test] -pub fn uint256_mul32() { +fn uint256_mul32() { assert_eq!(U256::from(0u64).mul_u32(2), U256::from(0u64)); assert_eq!(U256::from(1u64).mul_u32(2), U256::from(2u64)); assert_eq!(U256::from(10u64).mul_u32(2), U256::from(20u64)); @@ -243,12 +268,12 @@ fn uint256_overflowing_pow() { } #[test] -pub fn uint256_mul1() { +fn uint256_mul1() { assert_eq!(U256::from(1u64) * U256::from(10u64), U256::from(10u64)); } #[test] -pub fn uint256_mul2() { +fn uint256_mul2() { let a = U512::from_str("10000000000000000fffffffffffffffe").unwrap(); let b = U512::from_str("ffffffffffffffffffffffffffffffff").unwrap(); @@ -256,7 +281,7 @@ pub fn uint256_mul2() { } #[test] -pub fn uint256_overflowing_mul() { +fn uint256_overflowing_mul() { assert_eq!( U256::from_str("100000000000000000000000000000000").unwrap().overflowing_mul( U256::from_str("100000000000000000000000000000000").unwrap() @@ -266,7 +291,7 @@ pub fn uint256_overflowing_mul() { } #[test] -pub fn uint128_add() { +fn uint128_add() { assert_eq!( U128::from_str("fffffffffffffffff").unwrap() + U128::from_str("fffffffffffffffff").unwrap(), U128::from_str("1ffffffffffffffffe").unwrap() @@ -274,7 +299,7 @@ pub fn uint128_add() { } #[test] -pub fn uint128_add_overflow() { +fn uint128_add_overflow() { assert_eq!( U128::from_str("ffffffffffffffffffffffffffffffff").unwrap() .overflowing_add( @@ -287,21 +312,21 @@ pub fn uint128_add_overflow() { #[test] #[should_panic] #[cfg(debug_assertions)] -pub fn uint128_add_overflow_panic() { +fn uint128_add_overflow_panic() { U128::from_str("ffffffffffffffffffffffffffffffff").unwrap() + U128::from_str("ffffffffffffffffffffffffffffffff").unwrap(); } #[test] -pub fn uint128_mul() { +fn uint128_mul() { assert_eq!( U128::from_str("fffffffff").unwrap() * U128::from_str("fffffffff").unwrap(), U128::from_str("ffffffffe000000001").unwrap()); } #[test] -pub fn uint512_mul() { +fn uint512_mul() { assert_eq!( U512::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() * @@ -311,7 +336,7 @@ pub fn uint512_mul() { } #[test] -pub fn uint256_mul_overflow() { +fn uint256_mul_overflow() { assert_eq!( U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() .overflowing_mul( @@ -323,14 +348,14 @@ pub fn uint256_mul_overflow() { #[test] #[should_panic] -pub fn uint256_mul_overflow_panic() { +fn uint256_mul_overflow_panic() { U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() * U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap(); } #[test] -pub fn uint256_sub_overflow() { +fn uint256_sub_overflow() { assert_eq!( U256::from_str("0").unwrap() .overflowing_sub( @@ -342,14 +367,14 @@ pub fn uint256_sub_overflow() { #[test] #[should_panic] -pub fn uint256_sub_overflow_panic() { +fn uint256_sub_overflow_panic() { U256::from_str("0").unwrap() - U256::from_str("1").unwrap(); } #[test] -pub fn uint256_shl() { +fn uint256_shl() { assert_eq!( U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() << 4, @@ -358,7 +383,7 @@ pub fn uint256_shl() { } #[test] -pub fn uint256_shl_words() { +fn uint256_shl_words() { assert_eq!( U256::from_str("0000000000000001ffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() << 64, @@ -372,7 +397,7 @@ pub fn uint256_shl_words() { } #[test] -pub fn uint256_mul() { +fn uint256_mul() { assert_eq!( U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() * From 6daac629e3f1b3a1ea74872cc2adfa6bd2e3a5a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 28 Jan 2018 17:26:50 +0100 Subject: [PATCH 21/76] LowerHex and small cleanup. --- src/uint.rs | 66 +++++++++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 43 deletions(-) diff --git a/src/uint.rs b/src/uint.rs index e3260bdb4..28f0f7d81 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -717,7 +717,7 @@ macro_rules! construct_uint { pub fn exp10(n: usize) -> Self { match n { 0 => Self::from(1u64), - _ => Self::exp10(n - 1).mul_u32(10) + _ => Self::exp10(n - 1) * 10u32 } } @@ -858,13 +858,6 @@ macro_rules! construct_uint { (!self, true) } - /// Multiplication by u32 - pub fn mul_u32(self, other: u32) -> Self { - let (ret, overflow) = self.overflowing_mul_u32(other); - panic_on_overflow!(overflow); - ret - } - /// Overflowing multiplication by u32 #[allow(dead_code)] // not used when multiplied with inline assembly fn overflowing_mul_u32(self, other: u32) -> (Self, bool) { @@ -915,8 +908,6 @@ macro_rules! construct_uint { $name(ret) } - - impl_std_for_uint_internals!($name, $n_words); } impl Default for $name { @@ -982,6 +973,16 @@ macro_rules! construct_uint { } } + impl ::core::ops::Mul for $name { + type Output = $name; + + fn mul(self, other: u32) -> $name { + let (ret, overflow) = self.overflowing_mul_u32(other); + panic_on_overflow!(overflow); + ret + } + } + impl ::core::ops::Mul<$name> for $name { type Output = $name; @@ -1169,28 +1170,6 @@ macro_rules! construct_uint { ); } -#[cfg(feature="std")] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_std_for_uint_internals { - ($name: ident, $n_words: tt) => { - /// Convert to hex string. - #[inline] - pub fn to_hex(&self) -> String { - use core::cmp; - use $crate::rustc_hex::ToHex;; - - if self.is_zero() { return "0".to_owned(); } // special case. - let mut bytes = [0u8; 8 * $n_words]; - self.to_big_endian(&mut bytes); - let bp7 = self.bits() + 7; - let len = cmp::max(bp7 / 8, 1); - let bytes_hex = bytes[bytes.len() - len..].to_hex(); - (&bytes_hex[1 - bp7 % 8 / 4..]).to_owned() - } - } -} - #[cfg(feature="std")] #[macro_export] #[doc(hidden)] @@ -1239,15 +1218,23 @@ macro_rules! impl_std_for_uint { impl ::core::fmt::LowerHex for $name { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - let &$name(ref data) = self; - try!(write!(f, "0x")); + let &$name(ref data) = self; + // special case. + if self.is_zero() { + return write!(f, "0x0"); + } + + write!(f, "0x")?; let mut latch = false; for ch in data.iter().rev() { for x in 0..16 { let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64); - if !latch { latch = nibble != 0 } + if !latch { + latch = nibble != 0; + } + if latch { - try!(write!(f, "{:x}", nibble)); + write!(f, "{:x}", nibble)?; } } } @@ -1263,13 +1250,6 @@ macro_rules! impl_std_for_uint { } } -#[cfg(not(feature="std"))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_std_for_uint_internals { - ($name: ident, $n_words: tt) => {} -} - #[cfg(not(feature="std"))] #[macro_export] #[doc(hidden)] From be5ce475c47f6514af12d59d74dfd218c2c58cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 28 Jan 2018 17:26:50 +0100 Subject: [PATCH 22/76] LowerHex and small cleanup. --- src/uint_tests.rs | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/uint_tests.rs b/src/uint_tests.rs index 1c5351e94..0d1535298 100644 --- a/src/uint_tests.rs +++ b/src/uint_tests.rs @@ -141,7 +141,7 @@ pub fn uint256_arithmetic_test() { let sub = overflowing!(incr.overflowing_sub(init)); assert_eq!(sub, U256([0x9F30411021524112u64, 0x0001BD5B7DDFBD5A, 0, 0])); // Multiplication - let mult = sub.mul_u32(300); + let mult = sub * 300u32; assert_eq!(mult, U256([0x8C8C3EE70C644118u64, 0x0209E7378231E632, 0, 0])); // Division assert_eq!(U256::from(105u8) / U256::from(5u8), U256::from(21u8)); @@ -196,11 +196,11 @@ pub fn uint256_exp10() { #[test] pub fn uint256_mul32() { - assert_eq!(U256::from(0u64).mul_u32(2), U256::from(0u64)); - assert_eq!(U256::from(1u64).mul_u32(2), U256::from(2u64)); - assert_eq!(U256::from(10u64).mul_u32(2), U256::from(20u64)); - assert_eq!(U256::from(10u64).mul_u32(5), U256::from(50u64)); - assert_eq!(U256::from(1000u64).mul_u32(50), U256::from(50000u64)); + assert_eq!(U256::from(0u64) * 2u32, U256::from(0u64)); + assert_eq!(U256::from(1u64) * 2u32, U256::from(2u64)); + assert_eq!(U256::from(10u64) * 2u32, U256::from(20u64)); + assert_eq!(U256::from(10u64) * 5u32, U256::from(50u64)); + assert_eq!(U256::from(1000u64) * 50u32, U256::from(50000u64)); } #[test] @@ -219,23 +219,27 @@ fn uint256_pow_overflow_panic() { } #[test] -fn should_format_hex_correctly() { - assert_eq!(&U256::from(0).to_hex(), &"0"); - assert_eq!(&U256::from(0x1).to_hex(), &"1"); - assert_eq!(&U256::from(0xf).to_hex(), &"f"); - assert_eq!(&U256::from(0x10).to_hex(), &"10"); - assert_eq!(&U256::from(0xff).to_hex(), &"ff"); - assert_eq!(&U256::from(0x100).to_hex(), &"100"); - assert_eq!(&U256::from(0xfff).to_hex(), &"fff"); - assert_eq!(&U256::from(0x1000).to_hex(), &"1000"); +fn should_format_and_debug_correctly() { + let test = |x: usize, hex: &'static str, dbg: &'static str| { + assert_eq!(format!("{:?}", U256::from(x)), dbg); + assert_eq!(format!("{:x}", U256::from(x)), hex); + }; + + test(0x1, "0x1", "1"); + test(0xf, "0xf", "15"); + test(0x10, "0x10", "16"); + test(0xff, "0xff", "255"); + test(0x100, "0x100", "256"); + test(0xfff, "0xfff", "4095"); + test(0x1000, "0x1000", "4096"); } #[test] fn uint256_overflowing_pow() { - // assert_eq!( - // U256::from(2).overflowing_pow(U256::from(0xff)), - // (U256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap(), false) - // ); + assert_eq!( + U256::from(2).overflowing_pow(U256::from(0xff)), + (U256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap(), false) + ); assert_eq!( U256::from(2).overflowing_pow(U256::from(0x100)), (U256::zero(), true) @@ -846,7 +850,7 @@ fn u256_multi_muls2() { #[test] fn example() { let mut val: U256 = 1023.into(); - for _ in 0..200 { val = val * 2.into() } + for _ in 0..200 { val = val * U256::from(2) } assert_eq!(&format!("{}", val), "1643897619276947051879427220465009342380213662639797070513307648"); } From 8e5fd03d36d2a77331bf3838fa6ac4b9cf635ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 28 Jan 2018 17:26:50 +0100 Subject: [PATCH 23/76] LowerHex and small cleanup. --- src/hash.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/hash.rs b/src/hash.rs index 5384f7f1b..21bdfc017 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -139,6 +139,12 @@ macro_rules! construct_hash { } } + impl ::core::fmt::LowerHex for $from { + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Debug::fmt(self, f) + } + } + impl Copy for $from {} #[cfg_attr(feature="dev", allow(expl_impl_clone_on_copy))] impl Clone for $from { @@ -335,13 +341,6 @@ macro_rules! impl_heapsize_for_hash { #[doc(hidden)] macro_rules! impl_std_for_hash { ($from: ident, $size: tt) => { - impl $from { - /// Get a hex representation. - pub fn hex(&self) -> String { - format!("{:?}", self) - } - } - impl $crate::rand::Rand for $from { fn rand(r: &mut R) -> Self { let mut hash = $from::new(); From 447984acf83bb2754055e8631d439abd36ce5acb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 28 Jan 2018 17:45:15 +0100 Subject: [PATCH 24/76] Fix indentation. --- src/uint.rs | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/uint.rs b/src/uint.rs index 28f0f7d81..f7db4789e 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -93,7 +93,7 @@ macro_rules! uint_overflowing_add { " : "=r"(result[0]), "=r"(result[1]), "=r"(result[2]), "=r"(result[3]), "={al}"(overflow) : "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), - "mr"(other_t[0]), "mr"(other_t[1]), "mr"(other_t[2]), "mr"(other_t[3]) + "mr"(other_t[0]), "mr"(other_t[1]), "mr"(other_t[2]), "mr"(other_t[3]) : : ); @@ -129,16 +129,16 @@ macro_rules! uint_overflowing_add { ": "=r"(result[0]), "=r"(result[1]), "=r"(result[2]), "=r"(result[3]), - "={al}"(overflow) /* $0 - $4 */ + "={al}"(overflow) /* $0 - $4 */ - : "{rdi}"(&result[4] as *const u64) /* $5 */ - "{rsi}"(&other_t[4] as *const u64) /* $6 */ - "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), - "m"(self_t[4]), "m"(self_t[5]), "m"(self_t[6]), "m"(self_t[7]), - /* $7 - $14 */ + : "{rdi}"(&result[4] as *const u64) /* $5 */ + "{rsi}"(&other_t[4] as *const u64) /* $6 */ + "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), + "m"(self_t[4]), "m"(self_t[5]), "m"(self_t[6]), "m"(self_t[7]), + /* $7 - $14 */ - "mr"(other_t[0]), "mr"(other_t[1]), "mr"(other_t[2]), "mr"(other_t[3]), - "m"(other_t[4]), "m"(other_t[5]), "m"(other_t[6]), "m"(other_t[7]) /* $15 - $22 */ + "mr"(other_t[0]), "mr"(other_t[1]), "mr"(other_t[2]), "mr"(other_t[3]), + "m"(other_t[4]), "m"(other_t[5]), "m"(other_t[6]), "m"(other_t[7]) /* $15 - $22 */ : "rdi", "rsi" : ); @@ -274,16 +274,16 @@ macro_rules! uint_overflowing_sub { " : "=r"(result[0]), "=r"(result[1]), "=r"(result[2]), "=r"(result[3]), - "={al}"(overflow) /* $0 - $4 */ + "={al}"(overflow) /* $0 - $4 */ : "{rdi}"(&result[4] as *const u64) /* $5 */ "{rsi}"(&self_t[4] as *const u64) /* $6 */ - "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), - "m"(self_t[4]), "m"(self_t[5]), "m"(self_t[6]), "m"(self_t[7]), - /* $7 - $14 */ + "0"(self_t[0]), "1"(self_t[1]), "2"(self_t[2]), "3"(self_t[3]), + "m"(self_t[4]), "m"(self_t[5]), "m"(self_t[6]), "m"(self_t[7]), + /* $7 - $14 */ - "m"(other_t[0]), "m"(other_t[1]), "m"(other_t[2]), "m"(other_t[3]), - "m"(other_t[4]), "m"(other_t[5]), "m"(other_t[6]), "m"(other_t[7]) /* $15 - $22 */ + "m"(other_t[0]), "m"(other_t[1]), "m"(other_t[2]), "m"(other_t[3]), + "m"(other_t[4]), "m"(other_t[5]), "m"(other_t[6]), "m"(other_t[7]) /* $15 - $22 */ : "rdi", "rsi" : ); @@ -399,12 +399,12 @@ macro_rules! uint_overflowing_mul { 2: " : /* $0 */ "={r8}"(result[0]), /* $1 */ "={r9}"(result[1]), /* $2 */ "={r10}"(result[2]), - /* $3 */ "={r11}"(result[3]), /* $4 */ "={rcx}"(overflow) + /* $3 */ "={r11}"(result[3]), /* $4 */ "={rcx}"(overflow) : /* $5 */ "m"(self_t[0]), /* $6 */ "m"(self_t[1]), /* $7 */ "m"(self_t[2]), - /* $8 */ "m"(self_t[3]), /* $9 */ "m"(other_t[0]), /* $10 */ "m"(other_t[1]), - /* $11 */ "m"(other_t[2]), /* $12 */ "m"(other_t[3]) - : "rax", "rdx" + /* $8 */ "m"(self_t[3]), /* $9 */ "m"(other_t[0]), /* $10 */ "m"(other_t[1]), + /* $11 */ "m"(other_t[2]), /* $12 */ "m"(other_t[3]) + : "rax", "rdx" : ); @@ -1218,11 +1218,11 @@ macro_rules! impl_std_for_uint { impl ::core::fmt::LowerHex for $name { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - let &$name(ref data) = self; - // special case. - if self.is_zero() { - return write!(f, "0x0"); - } + let &$name(ref data) = self; + // special case. + if self.is_zero() { + return write!(f, "0x0"); + } write!(f, "0x")?; let mut latch = false; @@ -1230,8 +1230,8 @@ macro_rules! impl_std_for_uint { for x in 0..16 { let nibble = (ch & (15u64 << ((15 - x) * 4) as u64)) >> (((15 - x) * 4) as u64); if !latch { - latch = nibble != 0; - } + latch = nibble != 0; + } if latch { write!(f, "{:x}", nibble)?; From d0e82be2865a485703620f22d2cbe1f8c5fc67e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 28 Jan 2018 17:51:53 +0100 Subject: [PATCH 25/76] Fix indentation. --- src/uint.rs | 82 ++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/uint.rs b/src/uint.rs index 47cee3fac..4d355d746 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -815,13 +815,13 @@ macro_rules! construct_uint { } } - /// Checked addition. Returns `None` if overflow occurred. - pub fn checked_add(self, other: $name) -> Option<$name> { - match self.overflowing_add(other) { - (_, true) => None, - (val, _) => Some(val), - } - } + /// Checked addition. Returns `None` if overflow occurred. + pub fn checked_add(self, other: $name) -> Option<$name> { + match self.overflowing_add(other) { + (_, true) => None, + (val, _) => Some(val), + } + } /// Subtraction which underflows and returns a flag if it does. #[inline(always)] @@ -837,13 +837,13 @@ macro_rules! construct_uint { } } - /// Checked subtraction. Returns `None` if overflow occurred. - pub fn checked_sub(self, other: $name) -> Option<$name> { - match self.overflowing_sub(other) { - (_, true) => None, - (val, _) => Some(val), - } - } + /// Checked subtraction. Returns `None` if overflow occurred. + pub fn checked_sub(self, other: $name) -> Option<$name> { + match self.overflowing_sub(other) { + (_, true) => None, + (val, _) => Some(val), + } + } /// Multiply with overflow, returning a flag if it does. #[inline(always)] @@ -859,27 +859,27 @@ macro_rules! construct_uint { } } - /// Checked multiplication. Returns `None` if overflow occurred. - pub fn checked_mul(self, other: $name) -> Option<$name> { - match self.overflowing_mul(other) { - (_, true) => None, - (val, _) => Some(val), - } - } + /// Checked multiplication. Returns `None` if overflow occurred. + pub fn checked_mul(self, other: $name) -> Option<$name> { + match self.overflowing_mul(other) { + (_, true) => None, + (val, _) => Some(val), + } + } /// Division with overflow pub fn overflowing_div(self, other: $name) -> ($name, bool) { (self / other, false) } - /// Checked division. Returns `None` if `other == 0`. - pub fn checked_div(self, other: $name) -> Option<$name> { - if other.is_zero() { - None - } else { - Some(self / other) - } - } + /// Checked division. Returns `None` if `other == 0`. + pub fn checked_div(self, other: $name) -> Option<$name> { + if other.is_zero() { + None + } else { + Some(self / other) + } + } /// Modulus with overflow. pub fn overflowing_rem(self, other: $name) -> ($name, bool) { @@ -888,11 +888,11 @@ macro_rules! construct_uint { /// Checked modulus. Returns `None` if `other == 0`. pub fn checked_rem(self, other: $name) -> Option<$name> { - if other.is_zero() { - None - } else { - Some(self % other) - } + if other.is_zero() { + None + } else { + Some(self % other) + } } /// Negation with overflow. @@ -904,13 +904,13 @@ macro_rules! construct_uint { } } - /// Checked negation. Returns `None` unless `self == 0`. - pub fn checked_neg(self) -> Option<$name> { - match self.overflowing_neg() { - (_, true) => None, - (zero, false) => Some(zero), - } - } + /// Checked negation. Returns `None` unless `self == 0`. + pub fn checked_neg(self) -> Option<$name> { + match self.overflowing_neg() { + (_, true) => None, + (zero, false) => Some(zero), + } + } /// Multiplication by u32 pub fn mul_u32(self, other: u32) -> Self { From 978bd142f6496ebab4111ffb784e89f00e6b7c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 28 Jan 2018 17:51:53 +0100 Subject: [PATCH 26/76] Fix indentation. --- src/uint_tests.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/uint_tests.rs b/src/uint_tests.rs index 9f95c6fa4..cf6ad3eac 100644 --- a/src/uint_tests.rs +++ b/src/uint_tests.rs @@ -5,27 +5,27 @@ use ethereum_types::{U128, U256, U512}; #[test] fn uint256_checked_ops() { - let z = U256::from(0); - let a = U256::from(10); - let b = !U256::from(1); - - assert_eq!(a.checked_add(b), None); - assert_eq!(a.checked_add(a), Some(20.into())); + let z = U256::from(0); + let a = U256::from(10); + let b = !U256::from(1); - assert_eq!(a.checked_sub(b), None); - assert_eq!(a.checked_sub(a), Some(0.into())); + assert_eq!(a.checked_add(b), None); + assert_eq!(a.checked_add(a), Some(20.into())); - assert_eq!(a.checked_mul(b), None); - assert_eq!(a.checked_mul(a), Some(100.into())); + assert_eq!(a.checked_sub(b), None); + assert_eq!(a.checked_sub(a), Some(0.into())); - assert_eq!(a.checked_div(z), None); - assert_eq!(a.checked_div(a), Some(1.into())); + assert_eq!(a.checked_mul(b), None); + assert_eq!(a.checked_mul(a), Some(100.into())); - assert_eq!(a.checked_rem(z), None); - assert_eq!(a.checked_rem(a), Some(0.into())); + assert_eq!(a.checked_div(z), None); + assert_eq!(a.checked_div(a), Some(1.into())); - assert_eq!(a.checked_neg(), None); - assert_eq!(z.checked_neg(), Some(z)); + assert_eq!(a.checked_rem(z), None); + assert_eq!(a.checked_rem(a), Some(0.into())); + + assert_eq!(a.checked_neg(), None); + assert_eq!(z.checked_neg(), Some(z)); } #[test] From 74a227f2628a45439c76e75983665ed708dd31b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 28 Jan 2018 18:13:51 +0100 Subject: [PATCH 27/76] Remove 0x to be aligned with std LowerHex. --- src/uint_tests.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/uint_tests.rs b/src/uint_tests.rs index 0d1535298..87b6dfd69 100644 --- a/src/uint_tests.rs +++ b/src/uint_tests.rs @@ -225,13 +225,13 @@ fn should_format_and_debug_correctly() { assert_eq!(format!("{:x}", U256::from(x)), hex); }; - test(0x1, "0x1", "1"); - test(0xf, "0xf", "15"); - test(0x10, "0x10", "16"); - test(0xff, "0xff", "255"); - test(0x100, "0x100", "256"); - test(0xfff, "0xfff", "4095"); - test(0x1000, "0x1000", "4096"); + test(0x1, "1", "1"); + test(0xf, "f", "15"); + test(0x10, "10", "16"); + test(0xff, "ff", "255"); + test(0x100, "100", "256"); + test(0xfff, "fff", "4095"); + test(0x1000, "1000", "4096"); } #[test] From 68d0fab8a6cd25f67398ed575269683dae8500de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Sun, 28 Jan 2018 18:13:51 +0100 Subject: [PATCH 28/76] Remove 0x to be aligned with std LowerHex. --- src/uint.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/uint.rs b/src/uint.rs index f7db4789e..99da3312d 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -1220,11 +1220,10 @@ macro_rules! impl_std_for_uint { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { let &$name(ref data) = self; // special case. - if self.is_zero() { - return write!(f, "0x0"); + if self.is_zero() { + return write!(f, "0"); } - write!(f, "0x")?; let mut latch = false; for ch in data.iter().rev() { for x in 0..16 { From ceb5f74a1d403bf5dcf740c435bc9097851c8c43 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 31 Jan 2018 21:48:47 +0100 Subject: [PATCH 29/76] use ASM only with feature --- Cargo.toml | 3 +++ build.rs | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e7b2b21d6..e46630260 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,6 @@ crunchy = "0.1.5" ethereum-types = { path ="../ethereum-types", features = ["std", "heapsizeof"] } quickcheck = "0.6" uint = { path = "../uint" } + +[features] +use_asm = ["uint/use_asm", "ethereum-types/use_asm"] \ No newline at end of file diff --git a/build.rs b/build.rs index 432acc3f4..3ba1687eb 100644 --- a/build.rs +++ b/build.rs @@ -11,7 +11,9 @@ extern crate rustc_version; use rustc_version::{version_meta, Channel}; fn main() { - if let Channel::Nightly = version_meta().unwrap().channel { - println!("cargo:rustc-cfg=asm_available"); + if cfg!(feature = "use_asm") { + if let Channel::Nightly = version_meta().unwrap().channel { + println!("cargo:rustc-cfg=asm_available"); + } } } From 3059ca71284a9cdb760088667f580b6f790b2bbb Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 31 Jan 2018 21:48:47 +0100 Subject: [PATCH 30/76] use ASM only with feature --- Cargo.toml | 3 ++- build.rs | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c37a00c96..8433f2a4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ homepage = "http://parity.io" repository = "https://github.com/paritytech/primitives" license = "MIT/Apache-2.0" name = "uint" -version = "0.1.0" +version = "0.1.1" authors = ["Parity Technologies "] build = "build.rs" @@ -22,6 +22,7 @@ crunchy = "0.1.5" [features] std = ["rustc-hex"] heapsizeof = ["heapsize"] +use_asm = [] [[example]] name = "modular" diff --git a/build.rs b/build.rs index 432acc3f4..3ba1687eb 100644 --- a/build.rs +++ b/build.rs @@ -11,7 +11,9 @@ extern crate rustc_version; use rustc_version::{version_meta, Channel}; fn main() { - if let Channel::Nightly = version_meta().unwrap().channel { - println!("cargo:rustc-cfg=asm_available"); + if cfg!(feature = "use_asm") { + if let Channel::Nightly = version_meta().unwrap().channel { + println!("cargo:rustc-cfg=asm_available"); + } } } From a9e0f50a686066279d837e01b815dce0cf048ed8 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Wed, 31 Jan 2018 22:08:38 +0100 Subject: [PATCH 31/76] build script and feature cleanup --- build.rs | 19 ------------------- src/lib.rs | 4 +--- 2 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 build.rs diff --git a/build.rs b/build.rs deleted file mode 100644 index 3ba1687eb..000000000 --- a/build.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2015-2017 Parity Technologies -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -extern crate rustc_version; - -use rustc_version::{version_meta, Channel}; - -fn main() { - if cfg!(feature = "use_asm") { - if let Channel::Nightly = version_meta().unwrap().channel { - println!("cargo:rustc-cfg=asm_available"); - } - } -} diff --git a/src/lib.rs b/src/lib.rs index 342dbefd0..1ceb03645 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -#![cfg_attr(asm_available, feature(asm))] - extern crate core; #[cfg(test)] #[macro_use] @@ -13,4 +11,4 @@ extern crate crunchy; extern crate quickcheck; #[cfg(test)] -pub mod uint_tests; +pub mod uint_tests; \ No newline at end of file From 6b776e958b105f4b0fa28405b06dba03d6b30e8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 2 Feb 2018 12:42:32 +0100 Subject: [PATCH 32/76] Avoid heap allocations in deserialization. --- Cargo.toml | 3 +- src/lib.rs | 9 ++++- src/serialization.rs | 95 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 src/serialization.rs diff --git a/Cargo.toml b/Cargo.toml index e46630260..20e942af1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,8 @@ rustc_version = "0.2" crunchy = "0.1.5" ethereum-types = { path ="../ethereum-types", features = ["std", "heapsizeof"] } quickcheck = "0.6" +serde_json = "1.0" uint = { path = "../uint" } [features] -use_asm = ["uint/use_asm", "ethereum-types/use_asm"] \ No newline at end of file +use_asm = ["uint/use_asm", "ethereum-types/use_asm"] diff --git a/src/lib.rs b/src/lib.rs index 1ceb03645..1040b47d9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,19 @@ extern crate core; +extern crate ethereum_types; + #[cfg(test)] #[macro_use] extern crate uint; -extern crate ethereum_types; #[cfg(test)] #[macro_use] extern crate crunchy; #[cfg(test)] #[macro_use] extern crate quickcheck; +#[cfg(test)] +extern crate serde_json; #[cfg(test)] -pub mod uint_tests; \ No newline at end of file +pub mod uint_tests; +#[cfg(test)] +pub mod serialization; diff --git a/src/serialization.rs b/src/serialization.rs new file mode 100644 index 000000000..a926e670d --- /dev/null +++ b/src/serialization.rs @@ -0,0 +1,95 @@ +use ethereum_types::{U256, U512, H160, H256}; +use serde_json as ser; + +macro_rules! test { + ($name: ident, $test_name: ident) => { + #[test] + fn $test_name() { + let tests = vec![ + ($name::from(0), "0x0"), + ($name::from(1), "0x1"), + ($name::from(2), "0x2"), + ($name::from(10), "0xa"), + ($name::from(15), "0xf"), + ($name::from(15), "0xf"), + ($name::from(16), "0x10"), + ($name::from(1_000), "0x3e8"), + ($name::from(100_000), "0x186a0"), + ($name::from(u64::max_value()), "0xffffffffffffffff"), + ($name::from(u64::max_value()) + 1.into(), "0x10000000000000000"), + ]; + + for (number, expected) in tests { + assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); + assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); + } + + // Invalid examples + assert!(ser::from_str::<$name>("\"0x\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"0xg\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"10\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"0\"").unwrap_err().is_data()); + } + } +} + +test!(U256, test_u256); +test!(U512, test_u512); + +#[test] +fn test_large_values() { + assert_eq!( + ser::to_string_pretty(&!U256::zero()).unwrap(), + "\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" + ); + assert!( + ser::from_str::("\"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"").unwrap_err().is_data() + ); +} + +#[test] +fn test_h160() { + let tests = vec![ + (H160::from(0), "0x0000000000000000000000000000000000000000"), + (H160::from(2), "0x0000000000000000000000000000000000000002"), + (H160::from(15), "0x000000000000000000000000000000000000000f"), + (H160::from(16), "0x0000000000000000000000000000000000000010"), + (H160::from(1_000), "0x00000000000000000000000000000000000003e8"), + (H160::from(100_000), "0x00000000000000000000000000000000000186a0"), + (H160::from(u64::max_value()), "0x000000000000000000000000ffffffffffffffff"), + ]; + + for (number, expected) in tests { + assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); + assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); + } +} + +#[test] +fn test_h256() { + let tests = vec![ + (H256::from(0), "0x0000000000000000000000000000000000000000000000000000000000000000"), + (H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"), + (H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"), + (H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"), + (H256::from(1_000), "0x00000000000000000000000000000000000000000000000000000000000003e8"), + (H256::from(100_000), "0x00000000000000000000000000000000000000000000000000000000000186a0"), + (H256::from(u64::max_value()), "0x000000000000000000000000000000000000000000000000ffffffffffffffff"), + ]; + + for (number, expected) in tests { + assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); + assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); + } +} + +#[test] +fn test_invalid() { + assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000g\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0x00000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"10\"").unwrap_err().is_data()); +} From ed37a350232748822c8ae7f69411932a7be058ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 2 Feb 2018 13:47:33 +0100 Subject: [PATCH 33/76] Fix indentation. --- src/serialization.rs | 134 +++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/src/serialization.rs b/src/serialization.rs index a926e670d..8054e320a 100644 --- a/src/serialization.rs +++ b/src/serialization.rs @@ -2,36 +2,36 @@ use ethereum_types::{U256, U512, H160, H256}; use serde_json as ser; macro_rules! test { - ($name: ident, $test_name: ident) => { - #[test] - fn $test_name() { - let tests = vec![ - ($name::from(0), "0x0"), - ($name::from(1), "0x1"), - ($name::from(2), "0x2"), - ($name::from(10), "0xa"), - ($name::from(15), "0xf"), - ($name::from(15), "0xf"), - ($name::from(16), "0x10"), - ($name::from(1_000), "0x3e8"), - ($name::from(100_000), "0x186a0"), - ($name::from(u64::max_value()), "0xffffffffffffffff"), - ($name::from(u64::max_value()) + 1.into(), "0x10000000000000000"), - ]; + ($name: ident, $test_name: ident) => { + #[test] + fn $test_name() { + let tests = vec![ + ($name::from(0), "0x0"), + ($name::from(1), "0x1"), + ($name::from(2), "0x2"), + ($name::from(10), "0xa"), + ($name::from(15), "0xf"), + ($name::from(15), "0xf"), + ($name::from(16), "0x10"), + ($name::from(1_000), "0x3e8"), + ($name::from(100_000), "0x186a0"), + ($name::from(u64::max_value()), "0xffffffffffffffff"), + ($name::from(u64::max_value()) + 1.into(), "0x10000000000000000"), + ]; - for (number, expected) in tests { - assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); - assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); - } + for (number, expected) in tests { + assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); + assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); + } - // Invalid examples - assert!(ser::from_str::<$name>("\"0x\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"0xg\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"10\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"0\"").unwrap_err().is_data()); - } - } + // Invalid examples + assert!(ser::from_str::<$name>("\"0x\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"0xg\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"10\"").unwrap_err().is_data()); + assert!(ser::from_str::<$name>("\"0\"").unwrap_err().is_data()); + } + } } test!(U256, test_u256); @@ -39,57 +39,57 @@ test!(U512, test_u512); #[test] fn test_large_values() { - assert_eq!( - ser::to_string_pretty(&!U256::zero()).unwrap(), - "\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" - ); - assert!( - ser::from_str::("\"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"").unwrap_err().is_data() - ); + assert_eq!( + ser::to_string_pretty(&!U256::zero()).unwrap(), + "\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" + ); + assert!( + ser::from_str::("\"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"").unwrap_err().is_data() + ); } #[test] fn test_h160() { - let tests = vec![ - (H160::from(0), "0x0000000000000000000000000000000000000000"), - (H160::from(2), "0x0000000000000000000000000000000000000002"), - (H160::from(15), "0x000000000000000000000000000000000000000f"), - (H160::from(16), "0x0000000000000000000000000000000000000010"), - (H160::from(1_000), "0x00000000000000000000000000000000000003e8"), - (H160::from(100_000), "0x00000000000000000000000000000000000186a0"), - (H160::from(u64::max_value()), "0x000000000000000000000000ffffffffffffffff"), - ]; + let tests = vec![ + (H160::from(0), "0x0000000000000000000000000000000000000000"), + (H160::from(2), "0x0000000000000000000000000000000000000002"), + (H160::from(15), "0x000000000000000000000000000000000000000f"), + (H160::from(16), "0x0000000000000000000000000000000000000010"), + (H160::from(1_000), "0x00000000000000000000000000000000000003e8"), + (H160::from(100_000), "0x00000000000000000000000000000000000186a0"), + (H160::from(u64::max_value()), "0x000000000000000000000000ffffffffffffffff"), + ]; - for (number, expected) in tests { - assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); - assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); - } + for (number, expected) in tests { + assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); + assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); + } } #[test] fn test_h256() { - let tests = vec![ - (H256::from(0), "0x0000000000000000000000000000000000000000000000000000000000000000"), - (H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"), - (H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"), - (H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"), - (H256::from(1_000), "0x00000000000000000000000000000000000000000000000000000000000003e8"), - (H256::from(100_000), "0x00000000000000000000000000000000000000000000000000000000000186a0"), - (H256::from(u64::max_value()), "0x000000000000000000000000000000000000000000000000ffffffffffffffff"), - ]; + let tests = vec![ + (H256::from(0), "0x0000000000000000000000000000000000000000000000000000000000000000"), + (H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"), + (H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"), + (H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"), + (H256::from(1_000), "0x00000000000000000000000000000000000000000000000000000000000003e8"), + (H256::from(100_000), "0x00000000000000000000000000000000000000000000000000000000000186a0"), + (H256::from(u64::max_value()), "0x000000000000000000000000000000000000000000000000ffffffffffffffff"), + ]; - for (number, expected) in tests { - assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); - assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); - } + for (number, expected) in tests { + assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); + assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); + } } #[test] fn test_invalid() { - assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000g\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0x00000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"10\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000g\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0x00000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"0\"").unwrap_err().is_data()); + assert!(ser::from_str::("\"10\"").unwrap_err().is_data()); } From 1d70028a79d963c692e5a6fcf192414e168c3b77 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 4 Feb 2018 12:53:35 +0100 Subject: [PATCH 34/76] next release --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8433f2a4d..5d5a5ce66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ homepage = "http://parity.io" repository = "https://github.com/paritytech/primitives" license = "MIT/Apache-2.0" name = "uint" -version = "0.1.1" +version = "0.1.2" authors = ["Parity Technologies "] build = "build.rs" @@ -13,7 +13,7 @@ rustc_version = "0.2" [dependencies] byteorder = { version = "1", default-features = false } -heapsize = { version = "0.4", optional = true } +heapsize = { version = "0.4.2", optional = true } rustc-hex = { version = "1.0", optional = true } [dev-dependencies] From 3fe9fe605b4a4b8ee3aca5b5dfd443ade07ef969 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 4 Feb 2018 12:53:35 +0100 Subject: [PATCH 35/76] next release --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a218d3523..db1ef8419 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fixed-hash" -version = "0.1.2" +version = "0.1.3" authors = ["Parity Technologies "] license = "MIT" homepage = "https://github.com/paritytech/primitives" From aaa28a8e2e8315fbf5496dd726d971ea8da30db1 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 5 Feb 2018 22:03:20 +0100 Subject: [PATCH 36/76] get compiling for wasm --- Cargo.toml | 3 ++- src/hash.rs | 70 +++++++++++++++++++++++++++++++++++++++++------------ src/lib.rs | 5 ++++ 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index db1ef8419..9b2a91e23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,10 +8,11 @@ description = "Fixed-size hashes" [dependencies] heapsize = { version = "0.4", optional = true } -libc = { version = "0.2", default-features = false } +libc = { version = "0.2", optional = true, default-features = false } rand = { version = "0.4", optional = true } rustc-hex = { version = "1.0", optional = true } [features] +default = ["libc"] std = ["rustc-hex", "rand"] heapsizeof = ["heapsize"] diff --git a/src/hash.rs b/src/hash.rs index 58c561a17..1c0109ef7 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -157,21 +157,6 @@ macro_rules! construct_hash { impl Eq for $from {} - impl PartialEq for $from { - fn eq(&self, other: &Self) -> bool { - unsafe { $crate::libc::memcmp(self.0.as_ptr() as *const $crate::libc::c_void, other.0.as_ptr() as *const $crate::libc::c_void, $size) == 0 } - } - } - - impl Ord for $from { - fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - let r = unsafe { $crate::libc::memcmp(self.0.as_ptr() as *const $crate::libc::c_void, other.0.as_ptr() as *const $crate::libc::c_void, $size) }; - if r < 0 { return ::core::cmp::Ordering::Less } - if r > 0 { return ::core::cmp::Ordering::Greater } - return ::core::cmp::Ordering::Equal; - } - } - impl PartialOrd for $from { fn partial_cmp(&self, other: &Self) -> Option<::core::cmp::Ordering> { Some(self.cmp(other)) @@ -313,6 +298,7 @@ macro_rules! construct_hash { impl_std_for_hash!($from, $size); impl_heapsize_for_hash!($from); + impl_libc_for_hash!($from, $size); } } @@ -421,3 +407,57 @@ macro_rules! impl_std_for_hash_internals { macro_rules! impl_std_for_hash_internals { ($from: ident, $size: tt) => {} } + +#[cfg(feature="libc")] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_heapsize_for_hash { + ($name: ident) => { + impl $crate::heapsize::HeapSizeOf for $name { + fn heap_size_of_children(&self) -> usize { + 0 + } + } + } +} + +#[cfg(feature="libc")] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_libc_for_hash { + ($from: ident, $size: expr) => { + impl PartialEq for $from { + fn eq(&self, other: &Self) -> bool { + unsafe { $crate::libc::memcmp(self.0.as_ptr() as *const $crate::libc::c_void, other.0.as_ptr() as *const $crate::libc::c_void, $size) == 0 } + } + } + + impl Ord for $from { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { + let r = unsafe { $crate::libc::memcmp(self.0.as_ptr() as *const $crate::libc::c_void, other.0.as_ptr() as *const $crate::libc::c_void, $size) }; + if r < 0 { return ::core::cmp::Ordering::Less } + if r > 0 { return ::core::cmp::Ordering::Greater } + return ::core::cmp::Ordering::Equal; + } + } + } +} + +#[cfg(not(feature="libc"))] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_libc_for_hash { + ($from: ident, $size: expr) => { + impl PartialEq for $from { + fn eq(&self, other: &Self) -> bool { + &self.0[..] == &other.0[..] + } + } + + impl Ord for $from { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { + self.0[..].cmp(&other.0[..]) + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 0888b593f..8cbf255c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,9 +6,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[cfg(feature="libc")] #[doc(hidden)] pub extern crate libc; +#[cfg(not(feature="libc"))] +#[doc(hidden)] +pub mod libc { } + #[cfg(feature="heapsizeof")] #[doc(hidden)] pub extern crate heapsize; From edce37c06ce78dea7864732ad1ed1f942b95b2a1 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Mon, 5 Feb 2018 22:03:20 +0100 Subject: [PATCH 37/76] get compiling for wasm --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 20e942af1..d1bd50353 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ rustc_version = "0.2" [dependencies] crunchy = "0.1.5" -ethereum-types = { path ="../ethereum-types", features = ["std", "heapsizeof"] } +ethereum-types = { version = "0.2.3", path ="../ethereum-types", features = ["std", "heapsizeof"] } quickcheck = "0.6" serde_json = "1.0" uint = { path = "../uint" } From 24abdc843bbd12e3c9e96fe9c5f461d84097ae59 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 12:56:51 +0100 Subject: [PATCH 38/76] no_std attributes --- Cargo.toml | 2 +- src/lib.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5d5a5ce66..cdb3dd353 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ rustc-hex = { version = "1.0", optional = true } crunchy = "0.1.5" [features] -std = ["rustc-hex"] +std = ["rustc-hex", "byteorder/std"] heapsizeof = ["heapsize"] use_asm = [] diff --git a/src/lib.rs b/src/lib.rs index 4a3dc8afa..e764031dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ //! Efficient large, fixed-size big integers and hashes. #![cfg_attr(asm_available, feature(asm))] +#![cfg_attr(not(feature = "std"), no_std)] #[doc(hidden)] pub extern crate byteorder; From 2c237884711e4fe7300e92b6a4acc233688b1eeb Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Tue, 6 Feb 2018 12:56:51 +0100 Subject: [PATCH 39/76] no_std attributes --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 8cbf255c4..cf5d72f09 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![cfg_attr(not(feature = "std"), no_std)] + #[cfg(feature="libc")] #[doc(hidden)] pub extern crate libc; From 6ff6c7810f1d24c3735f72b1c46c00fa8be1d8e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 6 Feb 2018 16:19:42 +0100 Subject: [PATCH 40/76] Add 0x when printing hex values. --- src/uint.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/uint.rs b/src/uint.rs index c8d0482aa..b07d0985b 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -1252,7 +1252,8 @@ macro_rules! impl_std_for_uint { ($name: ident, $n_words: tt) => { impl ::core::fmt::Debug for $name { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - ::core::fmt::Display::fmt(self, f) + write!(f, "0x")?; + ::core::fmt::LowerHex::fmt(self, f) } } From 431cd0ebed725c7f627fe5315413639be19593c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 6 Feb 2018 16:19:42 +0100 Subject: [PATCH 41/76] Add 0x when printing hex values. --- src/hash_tests.rs | 20 ++++++++++++++++++++ src/lib.rs | 2 ++ src/uint_tests.rs | 5 +++-- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/hash_tests.rs diff --git a/src/hash_tests.rs b/src/hash_tests.rs new file mode 100644 index 000000000..cb3174e6d --- /dev/null +++ b/src/hash_tests.rs @@ -0,0 +1,20 @@ +use ethereum_types::{U128, H128}; + +#[test] +fn should_format_and_debug_correctly() { + let test = |x: usize, hex: &'static str, display: &'static str| { + let hash = H128::from(U128::from(x)); + assert_eq!(format!("{}", hash), format!("0x{}", display)); + assert_eq!(format!("{:?}", hash), format!("0x{}", hex)); + assert_eq!(format!("{:x}", hash), hex); + }; + + test(0x1, "00000000000000000000000000000001", "0000…0001"); + test(0xf, "0000000000000000000000000000000f", "0000…000f"); + test(0x10, "00000000000000000000000000000010", "0000…0010"); + test(0xff, "000000000000000000000000000000ff", "0000…00ff"); + test(0x100, "00000000000000000000000000000100", "0000…0100"); + test(0xfff, "00000000000000000000000000000fff", "0000…0fff"); + test(0x1000, "00000000000000000000000000001000", "0000…1000"); +} + diff --git a/src/lib.rs b/src/lib.rs index 1040b47d9..374be6458 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,8 @@ extern crate quickcheck; #[cfg(test)] extern crate serde_json; +#[cfg(test)] +pub mod hash_tests; #[cfg(test)] pub mod uint_tests; #[cfg(test)] diff --git a/src/uint_tests.rs b/src/uint_tests.rs index 1a5f0a797..6697d6818 100644 --- a/src/uint_tests.rs +++ b/src/uint_tests.rs @@ -254,8 +254,9 @@ fn uint256_pow_overflow_panic() { #[test] fn should_format_and_debug_correctly() { - let test = |x: usize, hex: &'static str, dbg: &'static str| { - assert_eq!(format!("{:?}", U256::from(x)), dbg); + let test = |x: usize, hex: &'static str, display: &'static str| { + assert_eq!(format!("{}", U256::from(x)), display); + assert_eq!(format!("{:?}", U256::from(x)), format!("0x{}", hex)); assert_eq!(format!("{:x}", U256::from(x)), hex); }; From c06346cc4bed388f112ac80b6daa1fb90a700808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 6 Feb 2018 16:19:42 +0100 Subject: [PATCH 42/76] Add 0x when printing hex values. --- src/hash.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/hash.rs b/src/hash.rs index 58c561a17..5e4696a7c 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -119,15 +119,14 @@ macro_rules! construct_hash { impl ::core::fmt::Debug for $from { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - for i in &self.0[..] { - write!(f, "{:02x}", i)?; - } - Ok(()) + write!(f, "0x")?; + ::core::fmt::LowerHex::fmt(self, f) } } impl ::core::fmt::Display for $from { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + write!(f, "0x")?; for i in &self.0[0..2] { write!(f, "{:02x}", i)?; } @@ -141,7 +140,10 @@ macro_rules! construct_hash { impl ::core::fmt::LowerHex for $from { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - ::core::fmt::Debug::fmt(self, f) + for i in &self.0[..] { + write!(f, "{:02x}", i)?; + } + Ok(()) } } From 206529b7f92ebac1ce051a54805a8513115a414a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 16 Feb 2018 09:34:03 +0100 Subject: [PATCH 43/76] expose feature gated quickcheck arbitrary impl for uints --- Cargo.toml | 2 ++ src/lib.rs | 4 ++++ src/uint.rs | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index cdb3dd353..f6982c33c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ rustc_version = "0.2" byteorder = { version = "1", default-features = false } heapsize = { version = "0.4.2", optional = true } rustc-hex = { version = "1.0", optional = true } +quickcheck = { version = "0.6", optional = true } [dev-dependencies] crunchy = "0.1.5" @@ -23,6 +24,7 @@ crunchy = "0.1.5" std = ["rustc-hex", "byteorder/std"] heapsizeof = ["heapsize"] use_asm = [] +impl_quickcheck_arbitrary = ["quickcheck"] [[example]] name = "modular" diff --git a/src/lib.rs b/src/lib.rs index e764031dc..40a3a8dfe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,5 +26,9 @@ pub extern crate core; #[doc(hidden)] pub extern crate rustc_hex; +#[cfg(feature="impl_quickcheck_arbitrary")] +#[doc(hidden)] +pub extern crate quickcheck; + mod uint; pub use uint::*; diff --git a/src/uint.rs b/src/uint.rs index b07d0985b..ea5872900 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -1229,6 +1229,9 @@ macro_rules! construct_uint { impl_std_for_uint!($name, $n_words); impl_heapsize_for_uint!($name); + // `$n_words * 8` because macro expects bytes and + // uints use 64 bit (8 byte) words + impl_quickcheck_arbitrary_for_uint!($name, ($n_words * 8)); ); } @@ -1358,3 +1361,38 @@ macro_rules! impl_heapsize_for_uint { macro_rules! impl_heapsize_for_uint { ($name: ident) => {} } + +#[cfg(feature="impl_quickcheck_arbitrary")] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_quickcheck_arbitrary_for_uint { + ($uint: ty, $n_bytes: tt) => { + impl $crate::quickcheck::Arbitrary for $uint { + fn arbitrary(g: &mut G) -> Self { + let mut res = [0u8; $n_bytes]; + + let p = g.next_f64(); + let range = + if p < 0.1 { + $n_bytes + } else if p < 0.2 { + $n_bytes / 2 + } else { + $n_bytes / 5 + }; + + let size = g.gen_range(0, range); + g.fill_bytes(&mut res[..size]); + + res.as_ref().into() + } + } + } +} + +#[cfg(not(feature="impl_quickcheck_arbitrary"))] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_quickcheck_arbitrary_for_uint { + ($uint: ty, $n_bytes: tt) => {} +} From 8cdb623a4f0e31514b1d3c6b9a098ae54aebed80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 16 Feb 2018 09:34:03 +0100 Subject: [PATCH 44/76] expose feature gated quickcheck arbitrary impl for uints --- Cargo.toml | 2 +- src/uint_tests.rs | 41 ++++++++--------------------------------- 2 files changed, 9 insertions(+), 34 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d1bd50353..f45cbd13d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ crunchy = "0.1.5" ethereum-types = { version = "0.2.3", path ="../ethereum-types", features = ["std", "heapsizeof"] } quickcheck = "0.6" serde_json = "1.0" -uint = { path = "../uint" } +uint = { path = "../uint" , features = ["impl_quickcheck_arbitrary"] } [features] use_asm = ["uint/use_asm", "ethereum-types/use_asm"] diff --git a/src/uint_tests.rs b/src/uint_tests.rs index 6697d6818..980521a2c 100644 --- a/src/uint_tests.rs +++ b/src/uint_tests.rs @@ -1015,39 +1015,6 @@ fn trailing_zeros() { } pub mod laws { - construct_uint!(U128, 2); - construct_uint!(U256, 4); - construct_uint!(U512, 8); - - macro_rules! uint_arbitrary { - ($uint:ty, $n_bytes:tt) => { - impl ::quickcheck::Arbitrary for $uint { - fn arbitrary(g: &mut G) -> Self { - let mut res = [0u8; $n_bytes]; - - let p = g.next_f64(); - let range = - if p < 0.1 { - $n_bytes - } else if p < 0.2 { - $n_bytes / 2 - } else { - $n_bytes / 5 - }; - - let size = g.gen_range(0, range); - g.fill_bytes(&mut res[..size]); - - res.as_ref().into() - } - } - } - } - - uint_arbitrary!(U128, 16); - uint_arbitrary!(U256, 32); - uint_arbitrary!(U512, 64); - macro_rules! uint_laws { ($mod_name:ident, $uint_ty:ident) => { mod $mod_name { @@ -1213,7 +1180,15 @@ pub mod laws { } } + construct_uint!(U64, 1); + construct_uint!(U128, 2); + construct_uint!(U256, 4); + construct_uint!(U512, 8); + construct_uint!(U1024, 16); + + uint_laws!(u64, U64); uint_laws!(u128, U128); uint_laws!(u256, U256); uint_laws!(u512, U512); + uint_laws!(u1024, U1024); } From c3624193affc86a665e8e5abf12124491f401374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 16 Feb 2018 09:34:52 +0100 Subject: [PATCH 45/76] fix some indentation: spaces -> tabs --- src/uint.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/uint.rs b/src/uint.rs index ea5872900..6d3ab5880 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -10,7 +10,7 @@ // Rust Bitcoin Library // Written in 2014 by -// Andrew Poelstra +// Andrew Poelstra // // To the extent possible under law, the author(s) have dedicated all // copyright and related and neighboring rights to this software to @@ -399,7 +399,7 @@ macro_rules! uint_overflowing_mul { 2: " : /* $0 */ "={r8}"(result[0]), /* $1 */ "={r9}"(result[1]), /* $2 */ "={r10}"(result[2]), - /* $3 */ "={r11}"(result[3]), /* $4 */ "={rcx}"(overflow) + /* $3 */ "={r11}"(result[3]), /* $4 */ "={rcx}"(overflow) : /* $5 */ "m"(self_t[0]), /* $6 */ "m"(self_t[1]), /* $7 */ "m"(self_t[2]), /* $8 */ "m"(self_t[3]), /* $9 */ "m"(other_t[0]), /* $10 */ "m"(other_t[1]), @@ -897,11 +897,11 @@ macro_rules! construct_uint { /// Negation with overflow. pub fn overflowing_neg(self) -> ($name, bool) { - if self.is_zero() { - (self, false) - } else { - (!self, true) - } + if self.is_zero() { + (self, false) + } else { + (!self, true) + } } /// Checked negation. Returns `None` unless `self == 0`. @@ -914,9 +914,9 @@ macro_rules! construct_uint { /// Multiplication by u32 #[deprecated(note = "Use Mul instead.")] - pub fn mul_u32(self, other: u32) -> Self { + pub fn mul_u32(self, other: u32) -> Self { self * other - } + } /// Overflowing multiplication by u32 #[allow(dead_code)] // not used when multiplied with inline assembly From 548aabfe490f072b13ec6834605ea0a9913063aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 16 Feb 2018 09:34:52 +0100 Subject: [PATCH 46/76] fix some indentation: spaces -> tabs --- src/uint_tests.rs | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/uint_tests.rs b/src/uint_tests.rs index 980521a2c..1e005d24a 100644 --- a/src/uint_tests.rs +++ b/src/uint_tests.rs @@ -254,19 +254,19 @@ fn uint256_pow_overflow_panic() { #[test] fn should_format_and_debug_correctly() { - let test = |x: usize, hex: &'static str, display: &'static str| { - assert_eq!(format!("{}", U256::from(x)), display); - assert_eq!(format!("{:?}", U256::from(x)), format!("0x{}", hex)); - assert_eq!(format!("{:x}", U256::from(x)), hex); - }; - - test(0x1, "1", "1"); - test(0xf, "f", "15"); - test(0x10, "10", "16"); - test(0xff, "ff", "255"); - test(0x100, "100", "256"); - test(0xfff, "fff", "4095"); - test(0x1000, "1000", "4096"); + let test = |x: usize, hex: &'static str, display: &'static str| { + assert_eq!(format!("{}", U256::from(x)), display); + assert_eq!(format!("{:?}", U256::from(x)), format!("0x{}", hex)); + assert_eq!(format!("{:x}", U256::from(x)), hex); + }; + + test(0x1, "1", "1"); + test(0xf, "f", "15"); + test(0x10, "10", "16"); + test(0xff, "ff", "255"); + test(0x100, "100", "256"); + test(0xfff, "fff", "4095"); + test(0x1000, "1000", "4096"); } #[test] @@ -422,9 +422,9 @@ fn uint256_mul() { #[test] fn uint256_div() { - assert_eq!(U256::from(10u64) / U256::from(1u64), U256::from(10u64)); - assert_eq!(U256::from(10u64) / U256::from(2u64), U256::from(5u64)); - assert_eq!(U256::from(10u64) / U256::from(3u64), U256::from(3u64)); + assert_eq!(U256::from(10u64) / U256::from(1u64), U256::from(10u64)); + assert_eq!(U256::from(10u64) / U256::from(2u64), U256::from(5u64)); + assert_eq!(U256::from(10u64) / U256::from(3u64), U256::from(3u64)); } #[test] @@ -797,10 +797,10 @@ fn u256_multi_full_mul() { assert_eq!(U512([1, 0, 0, MAX-1, MAX, MAX, 0, 0]), result); let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); + assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); + assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, MAX])); assert_eq!(U512([1, 0, 0, 0, MAX-1, MAX, MAX, MAX]), result); From 7e3a4fb4aa14bbc0d5c0c36a55504c00aaababb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 16 Feb 2018 09:56:08 +0100 Subject: [PATCH 47/76] impl feature gated quickcheck arbitrary for hash --- Cargo.toml | 2 ++ src/hash.rs | 23 +++++++++++++++++++++++ src/lib.rs | 4 ++++ 3 files changed, 29 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 9b2a91e23..722dd5fc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,8 +11,10 @@ heapsize = { version = "0.4", optional = true } libc = { version = "0.2", optional = true, default-features = false } rand = { version = "0.4", optional = true } rustc-hex = { version = "1.0", optional = true } +quickcheck = { version = "0.6", optional = true } [features] default = ["libc"] std = ["rustc-hex", "rand"] heapsizeof = ["heapsize"] +impl_quickcheck_arbitrary = ["quickcheck"] diff --git a/src/hash.rs b/src/hash.rs index 990294bea..156f828cd 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -301,6 +301,7 @@ macro_rules! construct_hash { impl_std_for_hash!($from, $size); impl_heapsize_for_hash!($from); impl_libc_for_hash!($from, $size); + impl_quickcheck_arbitrary_for_hash!($from, $size); } } @@ -463,3 +464,25 @@ macro_rules! impl_libc_for_hash { } } } + +#[cfg(feature="impl_quickcheck_arbitrary")] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_quickcheck_arbitrary_for_hash { + ($name: ty, $n_bytes: tt) => { + impl $crate::quickcheck::Arbitrary for $name { + fn arbitrary(g: &mut G) -> Self { + let mut res = [0u8; $n_bytes]; + g.fill_bytes(&mut res[..$n_bytes]); + res.as_ref().into() + } + } + } +} + +#[cfg(not(feature="impl_quickcheck_arbitrary"))] +#[macro_export] +#[doc(hidden)] +macro_rules! impl_quickcheck_arbitrary_for_hash { + ($name: ty, $n_bytes: tt) => {} +} diff --git a/src/lib.rs b/src/lib.rs index cf5d72f09..77d9f0d44 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,5 +32,9 @@ pub extern crate rustc_hex; #[doc(hidden)] pub extern crate rand; +#[cfg(feature="impl_quickcheck_arbitrary")] +#[doc(hidden)] +pub extern crate quickcheck; + mod hash; pub use hash::*; From 37aabc3b6bbb0c046cb2e17196e843e9e3b1c2b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 16 Feb 2018 09:59:00 +0100 Subject: [PATCH 48/76] add comment explaining arbitrary gen for uint --- src/uint.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/uint.rs b/src/uint.rs index 6d3ab5880..a14ba7085 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -1372,11 +1372,16 @@ macro_rules! impl_quickcheck_arbitrary_for_uint { let mut res = [0u8; $n_bytes]; let p = g.next_f64(); + // make it more likely to generate smaller numbers that + // don't use up the full $n_bytes let range = + // 10% chance to generate number that uses up to $n_bytes if p < 0.1 { $n_bytes + // 20% chance to generate number that uses up to $n_bytes / 2 } else if p < 0.2 { $n_bytes / 2 + // 70% chance to generate number that uses up to $n_bytes / 5 } else { $n_bytes / 5 }; From d541e8822f8bb39cabb5cdaf56b6d50a064c0eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kru=CC=88ger?= Date: Fri, 16 Feb 2018 10:17:51 +0100 Subject: [PATCH 49/76] fix percentages in comment explaining uint arbitrary impl --- src/uint.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uint.rs b/src/uint.rs index a14ba7085..c807d2c87 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -1378,10 +1378,10 @@ macro_rules! impl_quickcheck_arbitrary_for_uint { // 10% chance to generate number that uses up to $n_bytes if p < 0.1 { $n_bytes - // 20% chance to generate number that uses up to $n_bytes / 2 + // 10% chance to generate number that uses up to $n_bytes / 2 } else if p < 0.2 { $n_bytes / 2 - // 70% chance to generate number that uses up to $n_bytes / 5 + // 80% chance to generate number that uses up to $n_bytes / 5 } else { $n_bytes / 5 }; From 3eba48bc152fbe5e0a4fcf50d56d0f5b2b5c712d Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 21 Feb 2018 14:09:10 +0100 Subject: [PATCH 50/76] impl AsRef for primitives --- src/hash.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/hash.rs b/src/hash.rs index 156f828cd..f02c59d2d 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -51,6 +51,13 @@ macro_rules! construct_hash { } } + impl AsRef<$from> for $from { + #[inline] + fn as_ref(&self) -> &$from { + &self + } + } + impl ::core::ops::DerefMut for $from { #[inline] fn deref_mut(&mut self) -> &mut [u8] { From 3d43653d9f1e9feba45844b2adbe706d0cf96e36 Mon Sep 17 00:00:00 2001 From: debris Date: Wed, 21 Feb 2018 14:09:10 +0100 Subject: [PATCH 51/76] impl AsRef for primitives --- src/uint.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/uint.rs b/src/uint.rs index c807d2c87..0dd9dc801 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -551,6 +551,12 @@ macro_rules! construct_uint { #[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct $name(pub [u64; $n_words]); + impl AsRef<$name> for $name { + fn as_ref(&self) -> &$name { + &self + } + } + impl $name { /// Convert from a decimal string. pub fn from_dec_str(value: &str) -> Result { From eaec0856625da0a163e7f4e0e226335ace1f9b2e Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Thu, 15 Mar 2018 09:41:01 +0100 Subject: [PATCH 52/76] Don't use libc with wasm32-unknown-unknown (#27) --- Cargo.toml | 4 +++- src/hash.rs | 6 +++--- src/lib.rs | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 722dd5fc5..0e19b1ceb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,11 +8,13 @@ description = "Fixed-size hashes" [dependencies] heapsize = { version = "0.4", optional = true } -libc = { version = "0.2", optional = true, default-features = false } rand = { version = "0.4", optional = true } rustc-hex = { version = "1.0", optional = true } quickcheck = { version = "0.6", optional = true } +[target.'cfg(not(target_os = "unknown"))'.dependencies] +libc = { version = "0.2", optional = true, default-features = false } + [features] default = ["libc"] std = ["rustc-hex", "rand"] diff --git a/src/hash.rs b/src/hash.rs index f02c59d2d..b5a0dfae1 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -418,7 +418,7 @@ macro_rules! impl_std_for_hash_internals { ($from: ident, $size: tt) => {} } -#[cfg(feature="libc")] +#[cfg(all(feature="libc", not(target_os = "unknown")))] #[macro_export] #[doc(hidden)] macro_rules! impl_heapsize_for_hash { @@ -431,7 +431,7 @@ macro_rules! impl_heapsize_for_hash { } } -#[cfg(feature="libc")] +#[cfg(all(feature="libc", not(target_os = "unknown")))] #[macro_export] #[doc(hidden)] macro_rules! impl_libc_for_hash { @@ -453,7 +453,7 @@ macro_rules! impl_libc_for_hash { } } -#[cfg(not(feature="libc"))] +#[cfg(any(not(feature="libc"), target_os = "unknown"))] #[macro_export] #[doc(hidden)] macro_rules! impl_libc_for_hash { diff --git a/src/lib.rs b/src/lib.rs index 77d9f0d44..50d58922e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,7 @@ #![cfg_attr(not(feature = "std"), no_std)] -#[cfg(feature="libc")] +#[cfg(all(feature="libc", not(target_os = "unknown")))] #[doc(hidden)] pub extern crate libc; From 5064f859c0375ef4b900cf6b8110bbb023723cdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 15 Mar 2018 09:42:10 +0100 Subject: [PATCH 53/76] Bump versions. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 0e19b1ceb..694b45c66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fixed-hash" -version = "0.1.3" +version = "0.2.0" authors = ["Parity Technologies "] license = "MIT" homepage = "https://github.com/paritytech/primitives" From 6a339bd230ed7108525680ef7c2cc775340f6fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 15 Mar 2018 09:42:10 +0100 Subject: [PATCH 54/76] Bump versions. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f45cbd13d..11e40a4ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ rustc_version = "0.2" [dependencies] crunchy = "0.1.5" -ethereum-types = { version = "0.2.3", path ="../ethereum-types", features = ["std", "heapsizeof"] } +ethereum-types = { version = "0.3.0", path ="../ethereum-types", features = ["std", "heapsizeof"] } quickcheck = "0.6" serde_json = "1.0" uint = { path = "../uint" , features = ["impl_quickcheck_arbitrary"] } From 10b77ed9eacbf13f5b143598fb667eb386c9bd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 15 Mar 2018 09:42:10 +0100 Subject: [PATCH 55/76] Bump versions. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index f6982c33c..3423df1d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ homepage = "http://parity.io" repository = "https://github.com/paritytech/primitives" license = "MIT/Apache-2.0" name = "uint" -version = "0.1.2" +version = "0.2.0" authors = ["Parity Technologies "] build = "build.rs" From 77c648eaadc20aa26a5e337524496016c97d77ef Mon Sep 17 00:00:00 2001 From: Toralf Wittner Date: Tue, 10 Apr 2018 16:02:09 +0200 Subject: [PATCH 56/76] Add `AsMut` impl in `construct_hash` macro. --- src/hash.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/hash.rs b/src/hash.rs index b5a0dfae1..1d67bed5a 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -51,6 +51,13 @@ macro_rules! construct_hash { } } + impl AsMut<[u8]> for $from { + #[inline] + fn as_mut(&mut self) -> &mut [u8] { + &mut self.0 + } + } + impl AsRef<$from> for $from { #[inline] fn as_ref(&self) -> &$from { From ab497004ea56405461ffdd8bf83e2c67ab636c0a Mon Sep 17 00:00:00 2001 From: Toralf Wittner Date: Wed, 11 Apr 2018 09:34:33 +0200 Subject: [PATCH 57/76] Increment versions. (#30) For `ethereum-types` and `fixed-hash`. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 11e40a4ec..3f759296f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ rustc_version = "0.2" [dependencies] crunchy = "0.1.5" -ethereum-types = { version = "0.3.0", path ="../ethereum-types", features = ["std", "heapsizeof"] } +ethereum-types = { version = "0.3.1", path ="../ethereum-types", features = ["std", "heapsizeof"] } quickcheck = "0.6" serde_json = "1.0" uint = { path = "../uint" , features = ["impl_quickcheck_arbitrary"] } From f064ce5782f38ef2b6c52313458ad520d2b7b24e Mon Sep 17 00:00:00 2001 From: Toralf Wittner Date: Wed, 11 Apr 2018 09:34:33 +0200 Subject: [PATCH 58/76] Increment versions. (#30) For `ethereum-types` and `fixed-hash`. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 694b45c66..0fe7bfad6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fixed-hash" -version = "0.2.0" +version = "0.2.1" authors = ["Parity Technologies "] license = "MIT" homepage = "https://github.com/paritytech/primitives" From f1912b87102ccb08c2d77384f604e4a117dbf22f Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 21 May 2018 11:02:09 +0100 Subject: [PATCH 59/76] Prefix `0x` for lower hex with alternate flag (#33) * Prefix `Ox` for lower hex for alternate flag Should fix https://github.com/paritytech/parity/issues/8393 As per https://doc.rust-lang.org/std/fmt/trait.LowerHex.html * Use hex alternate format for debug --- src/uint.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/uint.rs b/src/uint.rs index 0dd9dc801..13bcd05f7 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -1261,8 +1261,7 @@ macro_rules! impl_std_for_uint { ($name: ident, $n_words: tt) => { impl ::core::fmt::Debug for $name { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "0x")?; - ::core::fmt::LowerHex::fmt(self, f) + write!(f, "{:#x}", self) } } @@ -1304,6 +1303,9 @@ macro_rules! impl_std_for_uint { impl ::core::fmt::LowerHex for $name { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { let &$name(ref data) = self; + if f.alternate() { + write!(f, "0x"); + } // special case. if self.is_zero() { return write!(f, "0"); From 24b94af449394d790124d8a08a0c3bf7db7b8608 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 21 May 2018 11:02:09 +0100 Subject: [PATCH 60/76] Prefix `0x` for lower hex with alternate flag (#33) * Prefix `Ox` for lower hex for alternate flag Should fix https://github.com/paritytech/parity/issues/8393 As per https://doc.rust-lang.org/std/fmt/trait.LowerHex.html * Use hex alternate format for debug --- src/uint_tests.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/uint_tests.rs b/src/uint_tests.rs index 1e005d24a..d4bb88795 100644 --- a/src/uint_tests.rs +++ b/src/uint_tests.rs @@ -258,6 +258,7 @@ fn should_format_and_debug_correctly() { assert_eq!(format!("{}", U256::from(x)), display); assert_eq!(format!("{:?}", U256::from(x)), format!("0x{}", hex)); assert_eq!(format!("{:x}", U256::from(x)), hex); + assert_eq!(format!("{:#x}", U256::from(x)), format!("0x{}", hex)); }; test(0x1, "1", "1"); From ccb2bdd70b7d8fb50441149c5dbd9e8539ebc581 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 21 May 2018 11:32:45 +0100 Subject: [PATCH 61/76] Increment `patch` for uint and ethereum-types --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3423df1d0..3cbe5fb3d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ homepage = "http://parity.io" repository = "https://github.com/paritytech/primitives" license = "MIT/Apache-2.0" name = "uint" -version = "0.2.0" +version = "0.2.1" authors = ["Parity Technologies "] build = "build.rs" From 12f9448a932eee6f77ce942b3f78e7f5db9d30f7 Mon Sep 17 00:00:00 2001 From: kingoflolz Date: Mon, 4 Jun 2018 20:49:30 +0800 Subject: [PATCH 62/76] add *Assign operators, make most operators work on Into and make most operators work on references on uint (#31) --- src/serialization.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/serialization.rs b/src/serialization.rs index 8054e320a..531a20a66 100644 --- a/src/serialization.rs +++ b/src/serialization.rs @@ -16,7 +16,7 @@ macro_rules! test { ($name::from(1_000), "0x3e8"), ($name::from(100_000), "0x186a0"), ($name::from(u64::max_value()), "0xffffffffffffffff"), - ($name::from(u64::max_value()) + 1.into(), "0x10000000000000000"), + ($name::from(u64::max_value()) + 1, "0x10000000000000000"), ]; for (number, expected) in tests { From 53eff543b7a0b12ae55f847dfbd81759af4d1108 Mon Sep 17 00:00:00 2001 From: kingoflolz Date: Mon, 4 Jun 2018 20:49:30 +0800 Subject: [PATCH 63/76] add *Assign operators, make most operators work on Into and make most operators work on references on uint (#31) --- examples/modular.rs | 12 +- src/uint.rs | 294 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 258 insertions(+), 48 deletions(-) diff --git a/examples/modular.rs b/examples/modular.rs index 1db193f8b..b7ce44a14 100644 --- a/examples/modular.rs +++ b/examples/modular.rs @@ -31,22 +31,22 @@ fn main() { // (p-1) + (p+1) = 0 // (p - 1) mod p - let p_minus_1 = (p - 1u64.into()) % p; + let p_minus_1 = (p - 1) % p; // (p + 1) mod p - let p_plus_1 = (p + 1u64.into()) % p; + let p_plus_1 = (p + 1) % p; // ((p - 1) mod p + (p + 1) mod p) mod p let sum = (p_minus_1 + p_plus_1) % p; assert_eq!(sum, 0.into()); // on this field, // (p-1) + (p-1) = p-2 - let p_minus_1 = (p - 1u64.into()) % p; + let p_minus_1 = (p - 1) % p; let sum = (p_minus_1 + p_minus_1) % p; - assert_eq!(sum, p - 2.into()); + assert_eq!(sum, p - 2); // on this field, // (p-1) * 3 = p-3 - let p_minus_1 = (p - 1u64.into()) % p; + let p_minus_1 = (p - 1) % p; // multiplication is a series of additions let multiplicator = 3; @@ -58,5 +58,5 @@ fn main() { result }; - assert_eq!(mul, p - 3.into()); + assert_eq!(mul, p - 3); } diff --git a/src/uint.rs b/src/uint.rs index 13bcd05f7..d270823c3 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -54,7 +54,7 @@ macro_rules! impl_map_from { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_add { - ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ uint_overflowing_add_reg!($name, $n_words, $self_expr, $other) }) } @@ -62,7 +62,7 @@ macro_rules! uint_overflowing_add { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_add_reg { - ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ uint_overflowing_binop!( $name, $n_words, @@ -77,7 +77,7 @@ macro_rules! uint_overflowing_add_reg { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_add { - (U256, $n_words:tt, $self_expr: expr, $other: expr) => ({ + (U256, $n_words: tt, $self_expr: expr, $other: expr) => ({ let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; let self_t: &[u64; $n_words] = &$self_expr.0; let other_t: &[u64; $n_words] = &$other.0; @@ -100,7 +100,7 @@ macro_rules! uint_overflowing_add { } (U256(result), overflow != 0) }); - (U512, $n_words:tt, $self_expr: expr, $other: expr) => ({ + (U512, $n_words: tt, $self_expr: expr, $other: expr) => ({ let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; let self_t: &[u64; $n_words] = &$self_expr.0; let other_t: &[u64; $n_words] = &$other.0; @@ -146,7 +146,7 @@ macro_rules! uint_overflowing_add { (U512(result), overflow != 0) }); - ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ( + ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ( uint_overflowing_add_reg!($name, $n_words, $self_expr, $other) ) } @@ -155,7 +155,7 @@ macro_rules! uint_overflowing_add { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_sub { - ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ uint_overflowing_sub_reg!($name, $n_words, $self_expr, $other) }) } @@ -163,7 +163,7 @@ macro_rules! uint_overflowing_sub { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_binop { - ($name:ident, $n_words:tt, $self_expr: expr, $other: expr, $fn:expr) => ({ + ($name:ident, $n_words: tt, $self_expr: expr, $other: expr, $fn:expr) => ({ let $name(ref me) = $self_expr; let $name(ref you) = $other; @@ -208,7 +208,7 @@ macro_rules! uint_overflowing_binop { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_sub_reg { - ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ uint_overflowing_binop!( $name, $n_words, @@ -223,7 +223,7 @@ macro_rules! uint_overflowing_sub_reg { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_sub { - (U256, $n_words:tt, $self_expr: expr, $other: expr) => ({ + (U256, $n_words: tt, $self_expr: expr, $other: expr) => ({ let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; let self_t: &[u64; $n_words] = &$self_expr.0; let other_t: &[u64; $n_words] = &$other.0; @@ -245,7 +245,7 @@ macro_rules! uint_overflowing_sub { } (U256(result), overflow != 0) }); - (U512, $n_words:tt, $self_expr: expr, $other: expr) => ({ + (U512, $n_words: tt, $self_expr: expr, $other: expr) => ({ let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; let self_t: &[u64; $n_words] = &$self_expr.0; let other_t: &[u64; $n_words] = &$other.0; @@ -290,7 +290,7 @@ macro_rules! uint_overflowing_sub { } (U512(result), overflow != 0) }); - ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ uint_overflowing_sub_reg!($name, $n_words, $self_expr, $other) }) } @@ -298,7 +298,7 @@ macro_rules! uint_overflowing_sub { #[cfg(all(asm_available, target_arch="x86_64"))] #[macro_export] macro_rules! uint_overflowing_mul { - (U256, $n_words: expr, $self_expr: expr, $other: expr) => ({ + (U256, $n_words: tt, $self_expr: expr, $other: expr) => ({ let mut result: [u64; $n_words] = unsafe { ::core::mem::uninitialized() }; let self_t: &[u64; $n_words] = &$self_expr.0; let other_t: &[u64; $n_words] = &$other.0; @@ -411,7 +411,7 @@ macro_rules! uint_overflowing_mul { } (U256(result), overflow > 0) }); - ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ( + ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ( uint_overflowing_mul_reg!($name, $n_words, $self_expr, $other) ) } @@ -420,7 +420,7 @@ macro_rules! uint_overflowing_mul { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_mul { - ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ uint_overflowing_mul_reg!($name, $n_words, $self_expr, $other) }) } @@ -428,7 +428,7 @@ macro_rules! uint_overflowing_mul { #[macro_export] #[doc(hidden)] macro_rules! uint_full_mul_reg { - ($name:ident, $n_words:tt, $self_expr:expr, $other:expr) => ({{ + ($name:ident, $n_words: tt, $self_expr:expr, $other:expr) => ({{ #![allow(unused_assignments)] let $name(ref me) = $self_expr; @@ -472,7 +472,7 @@ macro_rules! uint_full_mul_reg { #[macro_export] #[doc(hidden)] macro_rules! uint_overflowing_mul_reg { - ($name:ident, $n_words:tt, $self_expr: expr, $other: expr) => ({ + ($name:ident, $n_words: tt, $self_expr: expr, $other: expr) => ({ let ret: [u64; $n_words * 2] = uint_full_mul_reg!($name, $n_words, $self_expr, $other); // The safety of this is enforced by the compiler @@ -524,6 +524,69 @@ macro_rules! panic_on_overflow { } } +#[macro_export] +#[doc(hidden)] +macro_rules! impl_mul_from { + ($name: ty, $other: ident) => { + impl ::core::ops::Mul<$other> for $name { + type Output = $name; + + fn mul(self, other: $other) -> $name { + let bignum: $name = other.into(); + let (result, overflow) = self.overflowing_mul(bignum); + panic_on_overflow!(overflow); + result + } + } + + impl<'a> ::core::ops::Mul<&'a $other> for $name { + type Output = $name; + + fn mul(self, other: &'a $other) -> $name { + let bignum: $name = (*other).into(); + let (result, overflow) = self.overflowing_mul(bignum); + panic_on_overflow!(overflow); + result + } + } + + impl<'a> ::core::ops::Mul<&'a $other> for &'a $name { + type Output = $name; + + fn mul(self, other: &'a $other) -> $name { + let bignum: $name = (*other).into(); + let (result, overflow) = self.overflowing_mul(bignum); + panic_on_overflow!(overflow); + result + } + } + + impl<'a> ::core::ops::Mul<$other> for &'a $name { + type Output = $name; + + fn mul(self, other: $other) -> $name { + let bignum: $name = other.into(); + let (result, overflow) = self.overflowing_mul(bignum); + panic_on_overflow!(overflow); + result + } + } + } +} + +#[macro_export] +#[doc(hidden)] +macro_rules! impl_mulassign_from { + ($name: ident, $other: ident) => { + impl::core::ops::MulAssign<$other> for $name { + fn mul_assign(&mut self, other: $other) { + let result = *self * other; + *self = result + } + } + } +} + #[inline(always)] #[doc(hidden)] pub fn mul_u32(a: (u64, u64), b: u64, carry: u64) -> (u64, u64) { @@ -545,7 +608,7 @@ pub fn split(a: u64) -> (u64, u64) { #[macro_export] macro_rules! construct_uint { - ($name:ident, $n_words:tt) => ( + ($name:ident, $n_words: tt) => ( /// Little-endian large integer type #[repr(C)] #[derive(Copy, Clone, Eq, PartialEq, Hash)] @@ -557,6 +620,12 @@ macro_rules! construct_uint { } } + impl<'a> From<&'a $name> for $name { + fn from(x: &'a $name) -> $name { + *x + } + } + impl $name { /// Convert from a decimal string. pub fn from_dec_str(value: &str) -> Result { @@ -623,6 +692,25 @@ macro_rules! construct_uint { arr[0] } + /// Conversion to usize with overflow checking + /// + /// # Panics + /// + /// Panics if the number is larger than usize::max_value(). + #[inline] + pub fn as_usize(&self) -> usize { + let &$name(ref arr) = self; + for i in 1..$n_words { + if arr[i] != 0 { + panic!("Integer overflow when casting U256") + } + } + if arr[0] > usize::max_value() as u64 { + panic!("Integer overflow when casting U256") + } + arr[0] as usize + } + /// Whether this is zero. #[inline] pub fn is_zero(&self) -> bool { @@ -768,13 +856,13 @@ macro_rules! construct_uint { while n > u_one { if is_even(&n) { x = x * x; - n = n >> 1; + n = n >> 1usize; } else { y = x * y; x = x * x; // to reduce odd number by 1 we should just clear the last bit n.0[$n_words-1] = n.0[$n_words-1] & ((!0u64)>>1); - n = n >> 1; + n = n >> 1usize; } } x * y @@ -796,11 +884,11 @@ macro_rules! construct_uint { while n > u_one { if is_even(&n) { x = overflowing!(x.overflowing_mul(x), overflow); - n = n >> 1; + n = n >> 1usize; } else { y = overflowing!(x.overflowing_mul(y), overflow); x = overflowing!(x.overflowing_mul(x), overflow); - n = (n - u_one) >> 1; + n = (n - u_one) >> 1usize; } } let res = overflowing!(x.overflowing_mul(y), overflow); @@ -1019,28 +1107,60 @@ macro_rules! construct_uint { } } + impl ::core::ops::Add for $name where T: Into<$name> { + type Output = $name; + + fn add(self, other: T) -> $name { + let (result, overflow) = self.overflowing_add(other.into()); + panic_on_overflow!(overflow); + result + } + } - impl ::core::ops::Add<$name> for $name { + impl<'a, T> ::core::ops::Add for &'a $name where T: Into<$name> { type Output = $name; - fn add(self, other: $name) -> $name { + fn add(self, other: T) -> $name { + *self + other + } + } + + impl ::core::ops::AddAssign<$name> for $name { + fn add_assign(&mut self, other: $name) { let (result, overflow) = self.overflowing_add(other); panic_on_overflow!(overflow); - result + *self = result } } - impl ::core::ops::Sub<$name> for $name { + impl ::core::ops::Sub for $name where T: Into<$name> { type Output = $name; #[inline] - fn sub(self, other: $name) -> $name { - let (result, overflow) = self.overflowing_sub(other); + fn sub(self, other: T) -> $name { + let (result, overflow) = self.overflowing_sub(other.into()); panic_on_overflow!(overflow); result } } + impl<'a, T> ::core::ops::Sub for &'a $name where T: Into<$name> { + type Output = $name; + + fn sub(self, other: T) -> $name { + *self - other + } + } + + impl ::core::ops::SubAssign<$name> for $name { + fn sub_assign(&mut self, other: $name) { + let (result, overflow) = self.overflowing_sub(other); + panic_on_overflow!(overflow); + *self = result + } + } + + // specialization for u32 impl ::core::ops::Mul for $name { type Output = $name; @@ -1051,20 +1171,51 @@ macro_rules! construct_uint { } } - impl ::core::ops::Mul<$name> for $name { + impl<'a> ::core::ops::Mul for &'a $name { type Output = $name; - fn mul(self, other: $name) -> $name { - let (result, overflow) = self.overflowing_mul(other); - panic_on_overflow!(overflow); - result + fn mul(self, other: u32) -> $name { + *self * other + } + } + + impl ::core::ops::MulAssign for $name { + fn mul_assign(&mut self, other: u32) { + let result = *self * other; + *self = result } } - impl ::core::ops::Div<$name> for $name { + // all other impls + impl_mul_from!($name, u8); + impl_mul_from!($name, u16); + impl_mul_from!($name, u64); + impl_mul_from!($name, usize); + + impl_mul_from!($name, i8); + impl_mul_from!($name, i16); + impl_mul_from!($name, i64); + impl_mul_from!($name, isize); + + impl_mul_from!($name, $name); + + impl_mulassign_from!($name, u8); + impl_mulassign_from!($name, u16); + impl_mulassign_from!($name, u64); + impl_mulassign_from!($name, usize); + + impl_mulassign_from!($name, i8); + impl_mulassign_from!($name, i16); + impl_mulassign_from!($name, i64); + impl_mulassign_from!($name, isize); + + impl_mulassign_from!($name, $name); + + impl ::core::ops::Div for $name where T: Into<$name> { type Output = $name; - fn div(self, other: $name) -> $name { + fn div(self, other: T) -> $name { + let other: Self = other.into(); let mut sub_copy = self; let mut shift_copy = other; let mut ret = [0u64; $n_words]; @@ -1088,7 +1239,7 @@ macro_rules! construct_uint { ret[shift / 64] |= 1 << (shift % 64); sub_copy = overflowing!(sub_copy.overflowing_sub(shift_copy)); } - shift_copy = shift_copy >> 1; + shift_copy = shift_copy >> 1usize; if shift == 0 { break; } shift -= 1; } @@ -1097,12 +1248,43 @@ macro_rules! construct_uint { } } - impl ::core::ops::Rem<$name> for $name { + impl<'a, T> ::core::ops::Div for &'a $name where T: Into<$name> { + type Output = $name; + + fn div(self, other: T) -> $name { + *self / other + } + } + + impl ::core::ops::DivAssign for $name where T: Into<$name> { + fn div_assign(&mut self, other: T) { + let (result, overflow) = self.overflowing_div(other.into()); + panic_on_overflow!(overflow); + *self = result + } + } + + impl ::core::ops::Rem for $name where T: Into<$name> + Copy { type Output = $name; - fn rem(self, other: $name) -> $name { + fn rem(self, other: T) -> $name { let times = self / other; - self - (times * other) + self - (times * other.into()) + } + } + + impl<'a, T> ::core::ops::Rem for &'a $name where T: Into<$name> + Copy { + type Output = $name; + + fn rem(self, other: T) -> $name { + *self % other + } + } + + impl ::core::ops::RemAssign for $name where T: Into<$name> + Copy { + fn rem_assign(&mut self, other: T) { + let times = *self / other; + *self -= times * other.into() } } @@ -1165,10 +1347,11 @@ macro_rules! construct_uint { } } - impl ::core::ops::Shl for $name { + impl ::core::ops::Shl for $name where T: Into<$name> { type Output = $name; - fn shl(self, shift: usize) -> $name { + fn shl(self, shift: T) -> $name { + let shift = shift.into().as_usize(); let $name(ref original) = self; let mut ret = [0u64; $n_words]; let word_shift = shift / 64; @@ -1188,10 +1371,24 @@ macro_rules! construct_uint { } } - impl ::core::ops::Shr for $name { + impl<'a, T> ::core::ops::Shl for &'a $name where T: Into<$name> { + type Output = $name; + fn shl(self, shift: T) -> $name { + *self << shift + } + } + + impl ::core::ops::ShlAssign for $name where T: Into<$name> { + fn shl_assign(&mut self, shift: T) { + *self = *self << shift; + } + } + + impl ::core::ops::Shr for $name where T: Into<$name> { type Output = $name; - fn shr(self, shift: usize) -> $name { + fn shr(self, shift: T) -> $name { + let shift = shift.into().as_usize(); let $name(ref original) = self; let mut ret = [0u64; $n_words]; let word_shift = shift / 64; @@ -1213,6 +1410,19 @@ macro_rules! construct_uint { } } + impl<'a, T> ::core::ops::Shr for &'a $name where T: Into<$name> { + type Output = $name; + fn shr(self, shift: T) -> $name { + *self >> shift + } + } + + impl ::core::ops::ShrAssign for $name where T: Into<$name> { + fn shr_assign(&mut self, shift: T) { + *self = *self >> shift; + } + } + impl Ord for $name { fn cmp(&self, other: &$name) -> ::core::cmp::Ordering { let &$name(ref me) = self; From 40818ee8e284d145d97f04e76e8443d6f001d701 Mon Sep 17 00:00:00 2001 From: Boyu Yang Date: Mon, 11 Jun 2018 22:50:26 +0800 Subject: [PATCH 64/76] Prefix '0x' for lower hex with alternate flag. --- src/hash.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/hash.rs b/src/hash.rs index 1d67bed5a..682a5283b 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -133,8 +133,7 @@ macro_rules! construct_hash { impl ::core::fmt::Debug for $from { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "0x")?; - ::core::fmt::LowerHex::fmt(self, f) + write!(f, "{:#x}", self) } } @@ -154,6 +153,9 @@ macro_rules! construct_hash { impl ::core::fmt::LowerHex for $from { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + if f.alternate() { + write!(f, "0x"); + } for i in &self.0[..] { write!(f, "{:02x}", i)?; } From baff4372f187c5986ca21162bb8ea24c6ad6d1f8 Mon Sep 17 00:00:00 2001 From: Boyu Yang Date: Mon, 11 Jun 2018 22:50:26 +0800 Subject: [PATCH 65/76] Prefix '0x' for lower hex with alternate flag. --- src/hash_tests.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hash_tests.rs b/src/hash_tests.rs index cb3174e6d..b21b56050 100644 --- a/src/hash_tests.rs +++ b/src/hash_tests.rs @@ -7,6 +7,7 @@ fn should_format_and_debug_correctly() { assert_eq!(format!("{}", hash), format!("0x{}", display)); assert_eq!(format!("{:?}", hash), format!("0x{}", hex)); assert_eq!(format!("{:x}", hash), hex); + assert_eq!(format!("{:#x}", hash), format!("0x{}", hex)); }; test(0x1, "00000000000000000000000000000001", "0000…0001"); From a530eec63ea4dfcf1671c47652ff9946e935eced Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Thu, 5 Jul 2018 11:33:17 +0200 Subject: [PATCH 66/76] ethereum-types `make it work in no_std` (#42) * fix error on nightly * make it work on no-std by disabling default ft --- src/hash.rs | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/hash.rs b/src/hash.rs index 1d67bed5a..c89a1c442 100644 --- a/src/hash.rs +++ b/src/hash.rs @@ -319,7 +319,7 @@ macro_rules! construct_hash { } } -#[cfg(feature="heapsizeof")] +#[cfg(all(feature="heapsizeof", feature="libc", not(target_os = "unknown")))] #[macro_export] #[doc(hidden)] macro_rules! impl_heapsize_for_hash { @@ -332,7 +332,7 @@ macro_rules! impl_heapsize_for_hash { } } -#[cfg(not(feature="heapsizeof"))] +#[cfg(any(not(feature="heapsizeof"), not(feature="libc"), target_os = "unknown"))] #[macro_export] #[doc(hidden)] macro_rules! impl_heapsize_for_hash { @@ -425,19 +425,6 @@ macro_rules! impl_std_for_hash_internals { ($from: ident, $size: tt) => {} } -#[cfg(all(feature="libc", not(target_os = "unknown")))] -#[macro_export] -#[doc(hidden)] -macro_rules! impl_heapsize_for_hash { - ($name: ident) => { - impl $crate::heapsize::HeapSizeOf for $name { - fn heap_size_of_children(&self) -> usize { - 0 - } - } - } -} - #[cfg(all(feature="libc", not(target_os = "unknown")))] #[macro_export] #[doc(hidden)] From 043569906ba7a817abde33877fe1f71cdbc87749 Mon Sep 17 00:00:00 2001 From: Niklas Adolfsson Date: Thu, 5 Jul 2018 11:33:55 +0200 Subject: [PATCH 67/76] nits (#39) * Use b`x` instead of `x` as u8 -> no casting required * Use more human-friendly repr of hex value --- src/uint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uint.rs b/src/uint.rs index d270823c3..b5ee3d0c7 100644 --- a/src/uint.rs +++ b/src/uint.rs @@ -603,7 +603,7 @@ pub fn mul_u32(a: (u64, u64), b: u64, carry: u64) -> (u64, u64) { #[inline(always)] #[doc(hidden)] pub fn split(a: u64) -> (u64, u64) { - (a >> 32, a & 0xFFFFFFFF) + (a >> 32, a & 0xFFFF_FFFF) } #[macro_export] From d2e4ec5b31000366c7db4f890a0836eaab757bb4 Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 13 Jul 2018 10:32:10 +0200 Subject: [PATCH 68/76] Fix warning about unused result Fix homepage in manifest Add sanity-check test --- Cargo.toml | 1 + fixed-hash/Cargo.toml | 4 ++-- fixed-hash/src/hash.rs | 21 ++++++++++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 13d5684ef..313d6789f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "fixed-hash", "hashdb", "keccak-hash", "kvdb", diff --git a/fixed-hash/Cargo.toml b/fixed-hash/Cargo.toml index 0fe7bfad6..09b7d2efd 100644 --- a/fixed-hash/Cargo.toml +++ b/fixed-hash/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "fixed-hash" -version = "0.2.1" +version = "0.2.2" authors = ["Parity Technologies "] license = "MIT" -homepage = "https://github.com/paritytech/primitives" +homepage = "https://github.com/paritytech/parity-common" description = "Fixed-size hashes" [dependencies] diff --git a/fixed-hash/src/hash.rs b/fixed-hash/src/hash.rs index b5baf411b..5d994f040 100644 --- a/fixed-hash/src/hash.rs +++ b/fixed-hash/src/hash.rs @@ -154,7 +154,7 @@ macro_rules! construct_hash { impl ::core::fmt::LowerHex for $from { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { if f.alternate() { - write!(f, "0x"); + write!(f, "0x")?; } for i in &self.0[..] { write!(f, "{:02x}", i)?; @@ -489,3 +489,22 @@ macro_rules! impl_quickcheck_arbitrary_for_hash { macro_rules! impl_quickcheck_arbitrary_for_hash { ($name: ty, $n_bytes: tt) => {} } + +#[cfg(test)] +mod tests { + construct_hash!(H10, 10); + #[test] + fn test_construct_hash() { + assert_eq!(H10::default(), H10::new()); + assert_eq!(H10::new(), H10::zero()); + assert_eq!(H10::len(), 10); + } + + #[cfg(feature="heapsizeof")] + #[test] + fn test_heapsizeof() { + use heapsize::HeapSizeOf; + let h = H10::zero(); + assert_eq!(h.heap_size_of_children(),0); + } +} \ No newline at end of file From bd8ea85d50b1468ef74c743b3618e0c358522114 Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 13 Jul 2018 12:23:15 +0200 Subject: [PATCH 69/76] Add uint to workspace Fix compiler warning Bump version --- Cargo.toml | 1 + uint/Cargo.toml | 2 +- uint/src/uint.rs | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 313d6789f..ee0135963 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,4 +15,5 @@ members = [ "rlp", "trie-standardmap", "triehash", + "uint" ] \ No newline at end of file diff --git a/uint/Cargo.toml b/uint/Cargo.toml index 3cbe5fb3d..22b1fb0e1 100644 --- a/uint/Cargo.toml +++ b/uint/Cargo.toml @@ -4,7 +4,7 @@ homepage = "http://parity.io" repository = "https://github.com/paritytech/primitives" license = "MIT/Apache-2.0" name = "uint" -version = "0.2.1" +version = "0.2.2" authors = ["Parity Technologies "] build = "build.rs" diff --git a/uint/src/uint.rs b/uint/src/uint.rs index b5ee3d0c7..9a72a9917 100644 --- a/uint/src/uint.rs +++ b/uint/src/uint.rs @@ -1514,7 +1514,7 @@ macro_rules! impl_std_for_uint { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { let &$name(ref data) = self; if f.alternate() { - write!(f, "0x"); + write!(f, "0x")?; } // special case. if self.is_zero() { From 716691c42b794ad004d95df5ecdc77fe7d3b9d3b Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 13 Jul 2018 14:29:10 +0200 Subject: [PATCH 70/76] Remove uint (moved to parity-common) --- Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3f759296f..4b651c3c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,9 @@ crunchy = "0.1.5" ethereum-types = { version = "0.3.1", path ="../ethereum-types", features = ["std", "heapsizeof"] } quickcheck = "0.6" serde_json = "1.0" -uint = { path = "../uint" , features = ["impl_quickcheck_arbitrary"] } +# TODO: remove `branch` when https://github.com/paritytech/parity-common/pull/12 lands +uint = { git = "https://github.com/paritytech/parity-common", branch = "add-fixed-hash", features = ["impl_quickcheck_arbitrary"] } + [features] use_asm = ["uint/use_asm", "ethereum-types/use_asm"] From 91447023165ce63fb094a21b87a0b2e5c4c3264d Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 13 Jul 2018 15:12:00 +0200 Subject: [PATCH 71/76] Move formatting test from `primitives` --- fixed-hash/src/hash.rs | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/fixed-hash/src/hash.rs b/fixed-hash/src/hash.rs index 5d994f040..f24280360 100644 --- a/fixed-hash/src/hash.rs +++ b/fixed-hash/src/hash.rs @@ -492,19 +492,40 @@ macro_rules! impl_quickcheck_arbitrary_for_hash { #[cfg(test)] mod tests { - construct_hash!(H10, 10); + construct_hash!(H128, 16); + #[test] fn test_construct_hash() { - assert_eq!(H10::default(), H10::new()); - assert_eq!(H10::new(), H10::zero()); - assert_eq!(H10::len(), 10); + assert_eq!(H128::default(), H128::new()); + assert_eq!(H128::new(), H128::zero()); + assert_eq!(H128::len(), 16); } #[cfg(feature="heapsizeof")] #[test] fn test_heapsizeof() { use heapsize::HeapSizeOf; - let h = H10::zero(); + let h = H128::zero(); assert_eq!(h.heap_size_of_children(),0); } + + #[cfg(feature="std")] + #[test] + fn should_format_and_debug_correctly() { + let test = |x: u64, hex: &'static str, display: &'static str| { + let hash = H128::from(x); + assert_eq!(format!("{}", hash), format!("0x{}", display)); + assert_eq!(format!("{:?}", hash), format!("0x{}", hex)); + assert_eq!(format!("{:x}", hash), hex); + assert_eq!(format!("{:#x}", hash), format!("0x{}", hex)); + }; + + test(0x1, "00000000000000000000000000000001", "0000…0001"); + test(0xf, "0000000000000000000000000000000f", "0000…000f"); + test(0x10, "00000000000000000000000000000010", "0000…0010"); + test(0xff, "000000000000000000000000000000ff", "0000…00ff"); + test(0x100, "00000000000000000000000000000100", "0000…0100"); + test(0xfff, "00000000000000000000000000000fff", "0000…0fff"); + test(0x1000, "00000000000000000000000000001000", "0000…1000"); + } } \ No newline at end of file From f8ee2e6e1a85c5eff4949f75b63e069b6009392d Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 13 Jul 2018 17:58:26 +0200 Subject: [PATCH 72/76] Move tests from `primitives/tests` to `uint` Fix wonky example causing long compile times --- uint/Cargo.toml | 1 + uint/README.md | 8 ++ uint/examples/modular.rs | 4 +- uint/tests/Cargo.toml | 19 --- uint/tests/src/hash_tests.rs | 21 --- uint/tests/src/lib.rs | 21 --- uint/tests/src/serialization.rs | 95 ------------- uint/tests/{src => }/uint_tests.rs | 212 +++++++++++++---------------- 8 files changed, 106 insertions(+), 275 deletions(-) create mode 100644 uint/README.md delete mode 100644 uint/tests/Cargo.toml delete mode 100644 uint/tests/src/hash_tests.rs delete mode 100644 uint/tests/src/lib.rs delete mode 100644 uint/tests/src/serialization.rs rename uint/tests/{src => }/uint_tests.rs (87%) diff --git a/uint/Cargo.toml b/uint/Cargo.toml index 22b1fb0e1..8623c944c 100644 --- a/uint/Cargo.toml +++ b/uint/Cargo.toml @@ -19,6 +19,7 @@ quickcheck = { version = "0.6", optional = true } [dev-dependencies] crunchy = "0.1.5" +quickcheck = "0.6" [features] std = ["rustc-hex", "byteorder/std"] diff --git a/uint/README.md b/uint/README.md new file mode 100644 index 000000000..4a0388bac --- /dev/null +++ b/uint/README.md @@ -0,0 +1,8 @@ +# Big unsigned integer types + +Implementation of a various large-but-fixed sized unsigned integer types. +The functions here are designed to be fast. There are optional `x86_64` +implementations for even more speed, hidden behind the `x64_arithmetic` +feature flag. + +Run tests with `cargo test --features=std,impl_quickcheck_arbitrary`. \ No newline at end of file diff --git a/uint/examples/modular.rs b/uint/examples/modular.rs index b7ce44a14..c06e62bad 100644 --- a/uint/examples/modular.rs +++ b/uint/examples/modular.rs @@ -15,7 +15,7 @@ extern crate crunchy; #[macro_use] extern crate uint; -construct_uint!(U256, 32); +construct_uint!(U256, 4); fn main() { // Example modular arithmetic using bigint U256 primitives @@ -52,7 +52,7 @@ fn main() { let multiplicator = 3; let mul = { let mut result = p_minus_1; - for _ in 0..multiplicator-1 { + for _ in 0..multiplicator-1 { result = (p_minus_1 + result) % p; } result diff --git a/uint/tests/Cargo.toml b/uint/tests/Cargo.toml deleted file mode 100644 index 4b651c3c9..000000000 --- a/uint/tests/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "tests" -version = "0.1.0" -authors = ["Parity Technologies "] - -[build-dependencies] -rustc_version = "0.2" - -[dependencies] -crunchy = "0.1.5" -ethereum-types = { version = "0.3.1", path ="../ethereum-types", features = ["std", "heapsizeof"] } -quickcheck = "0.6" -serde_json = "1.0" -# TODO: remove `branch` when https://github.com/paritytech/parity-common/pull/12 lands -uint = { git = "https://github.com/paritytech/parity-common", branch = "add-fixed-hash", features = ["impl_quickcheck_arbitrary"] } - - -[features] -use_asm = ["uint/use_asm", "ethereum-types/use_asm"] diff --git a/uint/tests/src/hash_tests.rs b/uint/tests/src/hash_tests.rs deleted file mode 100644 index b21b56050..000000000 --- a/uint/tests/src/hash_tests.rs +++ /dev/null @@ -1,21 +0,0 @@ -use ethereum_types::{U128, H128}; - -#[test] -fn should_format_and_debug_correctly() { - let test = |x: usize, hex: &'static str, display: &'static str| { - let hash = H128::from(U128::from(x)); - assert_eq!(format!("{}", hash), format!("0x{}", display)); - assert_eq!(format!("{:?}", hash), format!("0x{}", hex)); - assert_eq!(format!("{:x}", hash), hex); - assert_eq!(format!("{:#x}", hash), format!("0x{}", hex)); - }; - - test(0x1, "00000000000000000000000000000001", "0000…0001"); - test(0xf, "0000000000000000000000000000000f", "0000…000f"); - test(0x10, "00000000000000000000000000000010", "0000…0010"); - test(0xff, "000000000000000000000000000000ff", "0000…00ff"); - test(0x100, "00000000000000000000000000000100", "0000…0100"); - test(0xfff, "00000000000000000000000000000fff", "0000…0fff"); - test(0x1000, "00000000000000000000000000001000", "0000…1000"); -} - diff --git a/uint/tests/src/lib.rs b/uint/tests/src/lib.rs deleted file mode 100644 index 374be6458..000000000 --- a/uint/tests/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -extern crate core; -extern crate ethereum_types; - -#[cfg(test)] -#[macro_use] -extern crate uint; -#[cfg(test)] -#[macro_use] -extern crate crunchy; -#[cfg(test)] -#[macro_use] -extern crate quickcheck; -#[cfg(test)] -extern crate serde_json; - -#[cfg(test)] -pub mod hash_tests; -#[cfg(test)] -pub mod uint_tests; -#[cfg(test)] -pub mod serialization; diff --git a/uint/tests/src/serialization.rs b/uint/tests/src/serialization.rs deleted file mode 100644 index 531a20a66..000000000 --- a/uint/tests/src/serialization.rs +++ /dev/null @@ -1,95 +0,0 @@ -use ethereum_types::{U256, U512, H160, H256}; -use serde_json as ser; - -macro_rules! test { - ($name: ident, $test_name: ident) => { - #[test] - fn $test_name() { - let tests = vec![ - ($name::from(0), "0x0"), - ($name::from(1), "0x1"), - ($name::from(2), "0x2"), - ($name::from(10), "0xa"), - ($name::from(15), "0xf"), - ($name::from(15), "0xf"), - ($name::from(16), "0x10"), - ($name::from(1_000), "0x3e8"), - ($name::from(100_000), "0x186a0"), - ($name::from(u64::max_value()), "0xffffffffffffffff"), - ($name::from(u64::max_value()) + 1, "0x10000000000000000"), - ]; - - for (number, expected) in tests { - assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); - assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); - } - - // Invalid examples - assert!(ser::from_str::<$name>("\"0x\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"0xg\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"10\"").unwrap_err().is_data()); - assert!(ser::from_str::<$name>("\"0\"").unwrap_err().is_data()); - } - } -} - -test!(U256, test_u256); -test!(U512, test_u512); - -#[test] -fn test_large_values() { - assert_eq!( - ser::to_string_pretty(&!U256::zero()).unwrap(), - "\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"" - ); - assert!( - ser::from_str::("\"0x1ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\"").unwrap_err().is_data() - ); -} - -#[test] -fn test_h160() { - let tests = vec![ - (H160::from(0), "0x0000000000000000000000000000000000000000"), - (H160::from(2), "0x0000000000000000000000000000000000000002"), - (H160::from(15), "0x000000000000000000000000000000000000000f"), - (H160::from(16), "0x0000000000000000000000000000000000000010"), - (H160::from(1_000), "0x00000000000000000000000000000000000003e8"), - (H160::from(100_000), "0x00000000000000000000000000000000000186a0"), - (H160::from(u64::max_value()), "0x000000000000000000000000ffffffffffffffff"), - ]; - - for (number, expected) in tests { - assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); - assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); - } -} - -#[test] -fn test_h256() { - let tests = vec![ - (H256::from(0), "0x0000000000000000000000000000000000000000000000000000000000000000"), - (H256::from(2), "0x0000000000000000000000000000000000000000000000000000000000000002"), - (H256::from(15), "0x000000000000000000000000000000000000000000000000000000000000000f"), - (H256::from(16), "0x0000000000000000000000000000000000000000000000000000000000000010"), - (H256::from(1_000), "0x00000000000000000000000000000000000000000000000000000000000003e8"), - (H256::from(100_000), "0x00000000000000000000000000000000000000000000000000000000000186a0"), - (H256::from(u64::max_value()), "0x000000000000000000000000000000000000000000000000ffffffffffffffff"), - ]; - - for (number, expected) in tests { - assert_eq!(format!("{:?}", expected), ser::to_string_pretty(&number).unwrap()); - assert_eq!(number, ser::from_str(&format!("{:?}", expected)).unwrap()); - } -} - -#[test] -fn test_invalid() { - assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0x000000000000000000000000000000000000000000000000000000000000000g\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0x00000000000000000000000000000000000000000000000000000000000000000\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"0\"").unwrap_err().is_data()); - assert!(ser::from_str::("\"10\"").unwrap_err().is_data()); -} diff --git a/uint/tests/src/uint_tests.rs b/uint/tests/uint_tests.rs similarity index 87% rename from uint/tests/src/uint_tests.rs rename to uint/tests/uint_tests.rs index d4bb88795..fbb87a81f 100644 --- a/uint/tests/src/uint_tests.rs +++ b/uint/tests/uint_tests.rs @@ -1,7 +1,23 @@ +extern crate core; + +#[cfg(test)] +#[macro_use] +extern crate uint; +#[cfg(test)] +#[macro_use] +extern crate crunchy; +#[cfg(test)] +#[macro_use] +extern crate quickcheck; + use std::u64::MAX; use std::str::FromStr; use uint::FromDecStrErr; -use ethereum_types::{U128, U256, U512}; + +#[cfg(feature="std")] +construct_uint!(U128, 2); +construct_uint!(U256, 4); +construct_uint!(U512, 8); #[test] fn uint256_checked_ops() { @@ -80,6 +96,83 @@ fn uint256_from() { U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap() ); + let sa = U256::from_str("0a").unwrap(); + assert_eq!(e, sa); + assert_eq!(U256([0x1010, 0, 0, 0]), U256::from_str("1010").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0 , 0, 0]), U256::from_str("0000000012f0").unwrap()); + assert_eq!(U256([0x12f0, 1 , 0, 0]), U256::from_str("0100000000000012f0").unwrap()); + assert_eq!( + U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), + U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap() + ); + let sa = U256::from_str("0a").unwrap(); + assert_eq!(e, sa); + assert_eq!(U256([0x1010, 0, 0, 0]), U256::from_str("1010").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0 , 0, 0]), U256::from_str("0000000012f0").unwrap()); + assert_eq!(U256([0x12f0, 1 , 0, 0]), U256::from_str("0100000000000012f0").unwrap()); + assert_eq!( + U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), + U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap() + ); + let sa = U256::from_str("0a").unwrap(); + assert_eq!(e, sa); + assert_eq!(U256([0x1010, 0, 0, 0]), U256::from_str("1010").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0 , 0, 0]), U256::from_str("0000000012f0").unwrap()); + assert_eq!(U256([0x12f0, 1 , 0, 0]), U256::from_str("0100000000000012f0").unwrap()); + assert_eq!( + U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), + U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap() + ); + let sa = U256::from_str("0a").unwrap(); + assert_eq!(e, sa); + assert_eq!(U256([0x1010, 0, 0, 0]), U256::from_str("1010").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0 , 0, 0]), U256::from_str("0000000012f0").unwrap()); + assert_eq!(U256([0x12f0, 1 , 0, 0]), U256::from_str("0100000000000012f0").unwrap()); + assert_eq!( + U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), + U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap() + ); + let sa = U256::from_str("0a").unwrap(); + assert_eq!(e, sa); + assert_eq!(U256([0x1010, 0, 0, 0]), U256::from_str("1010").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0 , 0, 0]), U256::from_str("0000000012f0").unwrap()); + assert_eq!(U256([0x12f0, 1 , 0, 0]), U256::from_str("0100000000000012f0").unwrap()); + assert_eq!( + U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), + U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap() + ); + let sa = U256::from_str("0a").unwrap(); + assert_eq!(e, sa); + assert_eq!(U256([0x1010, 0, 0, 0]), U256::from_str("1010").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0 , 0, 0]), U256::from_str("0000000012f0").unwrap()); + assert_eq!(U256([0x12f0, 1 , 0, 0]), U256::from_str("0100000000000012f0").unwrap()); + assert_eq!( + U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), + U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap() + ); + let sa = U256::from_str("0a").unwrap(); + assert_eq!(e, sa); + assert_eq!(U256([0x1010, 0, 0, 0]), U256::from_str("1010").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0, 0, 0]), U256::from_str("12f0").unwrap()); + assert_eq!(U256([0x12f0, 0 , 0, 0]), U256::from_str("0000000012f0").unwrap()); + assert_eq!(U256([0x12f0, 1 , 0, 0]), U256::from_str("0100000000000012f0").unwrap()); + assert_eq!( + U256([0x12f0, 1 , 0x0910203040506077, 0x8090a0b0c0d0e0f0]), + U256::from_str("8090a0b0c0d0e0f00910203040506077000000000000000100000000000012f0").unwrap() + ); } #[test] @@ -506,7 +599,6 @@ fn u256_multi_adds() { assert!(overflow); } - #[test] fn u256_multi_subs() { let (result, _) = U256([0, 0, 0, 0]).overflowing_sub(U256([0, 0, 0, 0])); @@ -722,112 +814,6 @@ fn big_endian() { target); } -#[test] -#[cfg_attr(feature="dev", allow(cyclomatic_complexity))] -fn u256_multi_full_mul() { - let result = U256([0, 0, 0, 0]).full_mul(U256([0, 0, 0, 0])); - assert_eq!(U512([0, 0, 0, 0, 0, 0, 0, 0]), result); - - let result = U256([1, 0, 0, 0]).full_mul(U256([1, 0, 0, 0])); - assert_eq!(U512([1, 0, 0, 0, 0, 0, 0, 0]), result); - - let result = U256([5, 0, 0, 0]).full_mul(U256([5, 0, 0, 0])); - assert_eq!(U512([25, 0, 0, 0, 0, 0, 0, 0]), result); - - let result = U256([0, 5, 0, 0]).full_mul(U256([0, 5, 0, 0])); - assert_eq!(U512([0, 0, 25, 0, 0, 0, 0, 0]), result); - - let result = U256([0, 0, 0, 4]).full_mul(U256([4, 0, 0, 0])); - assert_eq!(U512([0, 0, 0, 16, 0, 0, 0, 0]), result); - - let result = U256([0, 0, 0, 5]).full_mul(U256([2, 0, 0, 0])); - assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result); - - let result = U256([0, 0, 2, 0]).full_mul(U256([0, 5, 0, 0])); - assert_eq!(U512([0, 0, 0, 10, 0, 0, 0, 0]), result); - - let result = U256([0, 3, 0, 0]).full_mul(U256([0, 0, 3, 0])); - assert_eq!(U512([0, 0, 0, 9, 0, 0, 0, 0]), result); - - let result = U256([0, 0, 8, 0]).full_mul(U256([0, 0, 6, 0])); - assert_eq!(U512([0, 0, 0, 0, 48, 0, 0, 0]), result); - - let result = U256([9, 0, 0, 0]).full_mul(U256([0, 3, 0, 0])); - assert_eq!(U512([0, 27, 0, 0, 0, 0, 0, 0]), result); - - let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U512([1, MAX-1, 0, 0, 0, 0, 0, 0]), result); - - let result = U256([0, MAX, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U512([0, 1, MAX-1, 0, 0, 0, 0, 0]), result); - - let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U512([1, MAX, MAX-1, 0, 0, 0, 0, 0]), result); - - let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U512([1, MAX, MAX-1, 0, 0, 0, 0, 0]), result); - - let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U512([1, 0, MAX-1, MAX, 0, 0, 0, 0]), result); - - let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U512([1, MAX, MAX, MAX-1, 0, 0, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U512([1, MAX, MAX, MAX-1, 0, 0, 0, 0]), result); - - let result = U256([MAX, 0, 0, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U512([1, MAX, MAX, MAX, MAX-1, 0, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, 0, 0, 0])); - assert_eq!(U512([1, MAX, MAX, MAX, MAX-1, 0, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U512([1, 0, MAX, MAX-1, MAX, 0, 0, 0]), result); - - let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U512([1, 0, MAX, MAX-1, MAX, 0, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, 0, 0])); - assert_eq!(U512([1, 0, MAX, MAX, MAX-1, MAX, 0, 0]), result); - - let result = U256([MAX, MAX, 0, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U512([1, 0, MAX, MAX, MAX-1, MAX, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U512([1, 0, 0, MAX-1, MAX, MAX, 0, 0]), result); - - let result = U256([MAX, MAX, MAX, 0]).full_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); - - let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, 0])); - assert_eq!(U512([1, 0, 0, MAX, MAX-1, MAX, MAX, 0]), result); - - let result = U256([MAX, MAX, MAX, MAX]).full_mul(U256([MAX, MAX, MAX, MAX])); - assert_eq!(U512([1, 0, 0, 0, MAX-1, MAX, MAX, MAX]), result); - - let result = U256([0, 0, 0, MAX]).full_mul(U256([0, 0, 0, MAX])); - assert_eq!(U512([0, 0, 0, 0, 0, 0, 1, MAX-1]), result); - - let result = U256([1, 0, 0, 0]).full_mul(U256([0, 0, 0, MAX])); - assert_eq!(U512([0, 0, 0, MAX, 0, 0, 0, 0]), result); - - let result = U256([1, 2, 3, 4]).full_mul(U256([5, 0, 0, 0])); - assert_eq!(U512([5, 10, 15, 20, 0, 0, 0, 0]), result); - - let result = U256([1, 2, 3, 4]).full_mul(U256([0, 6, 0, 0])); - assert_eq!(U512([0, 6, 12, 18, 24, 0, 0, 0]), result); - - let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 7, 0])); - assert_eq!(U512([0, 0, 7, 14, 21, 28, 0, 0]), result); - - let result = U256([1, 2, 3, 4]).full_mul(U256([0, 0, 0, 8])); - assert_eq!(U512([0, 0, 0, 8, 16, 24, 32, 0]), result); - - let result = U256([1, 2, 3, 4]).full_mul(U256([5, 6, 7, 8])); - assert_eq!(U512([5, 16, 34, 60, 61, 52, 32, 0]), result); -} - #[test] fn u256_multi_muls2() { @@ -962,15 +948,6 @@ fn slice_roundtrip_le2() { assert_eq!(&raw, &new_raw[..31]); } -#[test] -fn fixed_arrays_roundtrip() { - let raw: U256 = "7094875209347850239487502394881".into(); - let array: [u8; 32] = raw.into(); - let new_raw = array.into(); - - assert_eq!(raw, new_raw); -} - #[test] fn from_little_endian() { let source: [u8; 32] = [ @@ -1015,6 +992,7 @@ fn trailing_zeros() { assert_eq!(U256::from("0000000000000000000000000000000000000000000000000000000000000000").trailing_zeros(), 256); } +#[cfg(feature="impl_quickcheck_arbitrary")] pub mod laws { macro_rules! uint_laws { ($mod_name:ident, $uint_ty:ident) => { From 70a778a43c23402f980c298133b7a8f8b72010fc Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 13 Jul 2018 18:35:00 +0200 Subject: [PATCH 73/76] cleanup --- uint/tests/uint_tests.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/uint/tests/uint_tests.rs b/uint/tests/uint_tests.rs index fbb87a81f..d506a57fd 100644 --- a/uint/tests/uint_tests.rs +++ b/uint/tests/uint_tests.rs @@ -1,12 +1,9 @@ extern crate core; -#[cfg(test)] #[macro_use] extern crate uint; -#[cfg(test)] #[macro_use] extern crate crunchy; -#[cfg(test)] #[macro_use] extern crate quickcheck; From 4e4347fc9aaf5d100975ca4d165f1d122a2d18ed Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 13 Jul 2018 19:08:07 +0200 Subject: [PATCH 74/76] Fix travis --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8b52a358f..1d384aa37 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,5 @@ matrix: - rust: nightly script: - cargo build - - cargo test + - cargo test --all --exclude uint + - cd uint/ && cargo test --features=std,impl_quickcheck_arbitrary From dfc1c7959a018f7b4f5d637b9fe8f9b00fa6b5f0 Mon Sep 17 00:00:00 2001 From: David Palm Date: Mon, 30 Jul 2018 15:20:41 +0200 Subject: [PATCH 75/76] Silence warnings when running tests --- uint/tests/uint_tests.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/uint/tests/uint_tests.rs b/uint/tests/uint_tests.rs index d506a57fd..238cf11e8 100644 --- a/uint/tests/uint_tests.rs +++ b/uint/tests/uint_tests.rs @@ -319,7 +319,9 @@ fn uint256_mul32() { } #[test] +#[allow(deprecated)] fn uint256_mul32_old() { + assert_eq!(U256::from(0u64).mul_u32(2), U256::from(0u64)); assert_eq!(U256::from(0u64).mul_u32(2), U256::from(0u64)); assert_eq!(U256::from(1u64).mul_u32(2), U256::from(2u64)); assert_eq!(U256::from(10u64).mul_u32(2), U256::from(20u64)); @@ -417,6 +419,7 @@ fn uint128_add_overflow() { #[test] #[should_panic] #[cfg(debug_assertions)] +#[allow(unused_must_use)] fn uint128_add_overflow_panic() { U128::from_str("ffffffffffffffffffffffffffffffff").unwrap() + @@ -453,6 +456,7 @@ fn uint256_mul_overflow() { #[test] #[should_panic] +#[allow(unused_must_use)] fn uint256_mul_overflow_panic() { U256::from_str("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap() * @@ -472,6 +476,7 @@ fn uint256_sub_overflow() { #[test] #[should_panic] +#[allow(unused_must_use)] fn uint256_sub_overflow_panic() { U256::from_str("0").unwrap() - From b0cf5d1cf5bf0d284fae8e724df00fcb52673542 Mon Sep 17 00:00:00 2001 From: David Palm Date: Mon, 30 Jul 2018 16:10:31 +0200 Subject: [PATCH 76/76] Remove duplicated line --- uint/tests/uint_tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/uint/tests/uint_tests.rs b/uint/tests/uint_tests.rs index 238cf11e8..718cb8dad 100644 --- a/uint/tests/uint_tests.rs +++ b/uint/tests/uint_tests.rs @@ -321,7 +321,6 @@ fn uint256_mul32() { #[test] #[allow(deprecated)] fn uint256_mul32_old() { - assert_eq!(U256::from(0u64).mul_u32(2), U256::from(0u64)); assert_eq!(U256::from(0u64).mul_u32(2), U256::from(0u64)); assert_eq!(U256::from(1u64).mul_u32(2), U256::from(2u64)); assert_eq!(U256::from(10u64).mul_u32(2), U256::from(20u64));