From e15f631ec702f976f2b75078bce4450a72d23776 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Sun, 10 Jul 2016 20:18:23 +0200 Subject: [PATCH] Some obvious evm & uint optimizations (#1576) * fix name and tests for endians * using renamed func * zero and sign opt --- ethcore/src/evm/interpreter/memory.rs | 8 +--- ethcore/src/evm/interpreter/mod.rs | 11 +++--- rpc/src/v1/types/uint.rs | 2 +- util/bigint/src/uint.rs | 57 ++++++++++++++++++++++++--- util/src/hash.rs | 4 +- 5 files changed, 62 insertions(+), 20 deletions(-) diff --git a/ethcore/src/evm/interpreter/memory.rs b/ethcore/src/evm/interpreter/memory.rs index a77a6d494..8195a0da3 100644 --- a/ethcore/src/evm/interpreter/memory.rs +++ b/ethcore/src/evm/interpreter/memory.rs @@ -94,13 +94,7 @@ impl Memory for Vec { fn write(&mut self, offset: U256, value: U256) { let off = offset.low_u64() as usize; - let mut val = value; - - let end = off + 32; - for pos in 0..32 { - self[end - pos - 1] = val.low_u64() as u8; - val = val >> 8; - } + value.to_big_endian(&mut self[off..off+32]); } fn write_byte(&mut self, offset: U256, value: U256) { diff --git a/ethcore/src/evm/interpreter/mod.rs b/ethcore/src/evm/interpreter/mod.rs index 2e03f44b8..e0021dc6b 100644 --- a/ethcore/src/evm/interpreter/mod.rs +++ b/ethcore/src/evm/interpreter/mod.rs @@ -303,9 +303,9 @@ impl Interpreter { let out_size = stack.pop_back(); // Add stipend (only CALL|CALLCODE when value > 0) - let call_gas = call_gas + value.map_or_else(|| Cost::from(0), |val| match val > U256::zero() { - true => Cost::from(ext.schedule().call_stipend), - false => Cost::from(0) + let call_gas = call_gas + value.map_or_else(|| Cost::from(0), |val| match val.is_zero() { + false => Cost::from(ext.schedule().call_stipend), + true => Cost::from(0) }); // Get sender & receive addresses, check if we have balance @@ -550,7 +550,7 @@ impl Interpreter { } fn is_zero(&self, val: &U256) -> bool { - &U256::zero() == val + val.is_zero() } fn bool_to_u256(&self, val: bool) -> U256 { @@ -782,7 +782,8 @@ impl Interpreter { } fn get_and_reset_sign(value: U256) -> (U256, bool) { - let sign = (value >> 255).low_u64() == 1; + let U256(arr) = value; + let sign = arr[3].leading_zeros() == 0; (set_sign(value, sign), sign) } diff --git a/rpc/src/v1/types/uint.rs b/rpc/src/v1/types/uint.rs index 5111f3a42..b1cb0521f 100644 --- a/rpc/src/v1/types/uint.rs +++ b/rpc/src/v1/types/uint.rs @@ -50,7 +50,7 @@ macro_rules! impl_uint { fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer { let mut hex = "0x".to_owned(); let mut bytes = [0u8; 8 * $size]; - self.0.to_raw_bytes(&mut bytes); + self.0.to_big_endian(&mut bytes); let len = cmp::max((self.0.bits() + 7) / 8, 1); hex.push_str(&bytes[bytes.len() - len..].to_hex()); serializer.serialize_str(&hex) diff --git a/util/bigint/src/uint.rs b/util/bigint/src/uint.rs index 2f58061d4..8e08e590a 100644 --- a/util/bigint/src/uint.rs +++ b/util/bigint/src/uint.rs @@ -524,9 +524,8 @@ pub trait Uint: Sized + Default + FromStr + From + fmt::Debug + fmt::Displa fn bit(&self, index: usize) -> bool; /// Return single byte fn byte(&self, index: usize) -> u8; - /// Get this Uint as slice of bytes - fn to_raw_bytes(&self, bytes: &mut[u8]); - + /// Convert U256 to the sequence of bytes with a big endian + fn to_big_endian(&self, bytes: &mut[u8]); /// Create `Uint(10**n)` fn exp10(n: usize) -> Self; /// Return eponentation `self**other`. Panic on overflow. @@ -551,6 +550,9 @@ pub trait Uint: Sized + Default + FromStr + From + fmt::Debug + fmt::Displa /// Returns negation of this `Uint` and overflow (always true) fn overflowing_neg(self) -> (Self, bool); + + /// Returns + fn is_zero(&self) -> bool; } macro_rules! construct_uint { @@ -616,6 +618,13 @@ macro_rules! construct_uint { arr[0] } + #[inline] + 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] fn bits(&self) -> usize { @@ -638,7 +647,7 @@ macro_rules! construct_uint { (arr[index / 8] >> (((index % 8)) * 8)) as u8 } - fn to_raw_bytes(&self, bytes: &mut[u8]) { + fn to_big_endian(&self, bytes: &mut[u8]) { assert!($n_words * 8 == bytes.len()); let &$name(ref arr) = self; for i in 0..bytes.len() { @@ -1454,7 +1463,7 @@ mod tests { let hex = "8090a0b0c0d0e0f00910203040506077583a2cf8264910e1436bda32571012f0"; let uint = U256::from_str(hex).unwrap(); let mut bytes = [0u8; 32]; - uint.to_raw_bytes(&mut bytes); + uint.to_big_endian(&mut bytes); let uint2 = U256::from(&bytes[..]); assert_eq!(uint, uint2); } @@ -2021,6 +2030,44 @@ mod tests { 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))] diff --git a/util/src/hash.rs b/util/src/hash.rs index 95e8f8c8c..1b868b87b 100644 --- a/util/src/hash.rs +++ b/util/src/hash.rs @@ -445,7 +445,7 @@ macro_rules! impl_hash { impl From for H256 { fn from(value: U256) -> H256 { let mut ret = H256::new(); - value.to_raw_bytes(&mut ret); + value.to_big_endian(&mut ret); ret } } @@ -453,7 +453,7 @@ impl From for H256 { impl<'a> From<&'a U256> for H256 { fn from(value: &'a U256) -> H256 { let mut ret: H256 = H256::new(); - value.to_raw_bytes(&mut ret); + value.to_big_endian(&mut ret); ret } }