Some obvious evm & uint optimizations (#1576)

* fix name and tests for endians

* using renamed func

* zero and sign opt
This commit is contained in:
Nikolay Volf 2016-07-10 20:18:23 +02:00 committed by Gav Wood
parent d7caae2241
commit e15f631ec7
5 changed files with 62 additions and 20 deletions

View File

@ -94,13 +94,7 @@ impl Memory for Vec<u8> {
fn write(&mut self, offset: U256, value: U256) { fn write(&mut self, offset: U256, value: U256) {
let off = offset.low_u64() as usize; let off = offset.low_u64() as usize;
let mut val = value; value.to_big_endian(&mut self[off..off+32]);
let end = off + 32;
for pos in 0..32 {
self[end - pos - 1] = val.low_u64() as u8;
val = val >> 8;
}
} }
fn write_byte(&mut self, offset: U256, value: U256) { fn write_byte(&mut self, offset: U256, value: U256) {

View File

@ -303,9 +303,9 @@ impl<Cost: CostType> Interpreter<Cost> {
let out_size = stack.pop_back(); let out_size = stack.pop_back();
// Add stipend (only CALL|CALLCODE when value > 0) // 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() { let call_gas = call_gas + value.map_or_else(|| Cost::from(0), |val| match val.is_zero() {
true => Cost::from(ext.schedule().call_stipend), false => Cost::from(ext.schedule().call_stipend),
false => Cost::from(0) true => Cost::from(0)
}); });
// Get sender & receive addresses, check if we have balance // Get sender & receive addresses, check if we have balance
@ -550,7 +550,7 @@ impl<Cost: CostType> Interpreter<Cost> {
} }
fn is_zero(&self, val: &U256) -> bool { fn is_zero(&self, val: &U256) -> bool {
&U256::zero() == val val.is_zero()
} }
fn bool_to_u256(&self, val: bool) -> U256 { fn bool_to_u256(&self, val: bool) -> U256 {
@ -782,7 +782,8 @@ impl<Cost: CostType> Interpreter<Cost> {
} }
fn get_and_reset_sign(value: U256) -> (U256, bool) { 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) (set_sign(value, sign), sign)
} }

View File

@ -50,7 +50,7 @@ macro_rules! impl_uint {
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer { fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: serde::Serializer {
let mut hex = "0x".to_owned(); let mut hex = "0x".to_owned();
let mut bytes = [0u8; 8 * $size]; 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); let len = cmp::max((self.0.bits() + 7) / 8, 1);
hex.push_str(&bytes[bytes.len() - len..].to_hex()); hex.push_str(&bytes[bytes.len() - len..].to_hex());
serializer.serialize_str(&hex) serializer.serialize_str(&hex)

View File

@ -524,9 +524,8 @@ pub trait Uint: Sized + Default + FromStr + From<u64> + fmt::Debug + fmt::Displa
fn bit(&self, index: usize) -> bool; fn bit(&self, index: usize) -> bool;
/// Return single byte /// Return single byte
fn byte(&self, index: usize) -> u8; fn byte(&self, index: usize) -> u8;
/// Get this Uint as slice of bytes /// Convert U256 to the sequence of bytes with a big endian
fn to_raw_bytes(&self, bytes: &mut[u8]); fn to_big_endian(&self, bytes: &mut[u8]);
/// Create `Uint(10**n)` /// Create `Uint(10**n)`
fn exp10(n: usize) -> Self; fn exp10(n: usize) -> Self;
/// Return eponentation `self**other`. Panic on overflow. /// Return eponentation `self**other`. Panic on overflow.
@ -551,6 +550,9 @@ pub trait Uint: Sized + Default + FromStr + From<u64> + fmt::Debug + fmt::Displa
/// Returns negation of this `Uint` and overflow (always true) /// Returns negation of this `Uint` and overflow (always true)
fn overflowing_neg(self) -> (Self, bool); fn overflowing_neg(self) -> (Self, bool);
/// Returns
fn is_zero(&self) -> bool;
} }
macro_rules! construct_uint { macro_rules! construct_uint {
@ -616,6 +618,13 @@ macro_rules! construct_uint {
arr[0] 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 /// Return the least number of bits needed to represent the number
#[inline] #[inline]
fn bits(&self) -> usize { fn bits(&self) -> usize {
@ -638,7 +647,7 @@ macro_rules! construct_uint {
(arr[index / 8] >> (((index % 8)) * 8)) as u8 (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()); assert!($n_words * 8 == bytes.len());
let &$name(ref arr) = self; let &$name(ref arr) = self;
for i in 0..bytes.len() { for i in 0..bytes.len() {
@ -1454,7 +1463,7 @@ mod tests {
let hex = "8090a0b0c0d0e0f00910203040506077583a2cf8264910e1436bda32571012f0"; let hex = "8090a0b0c0d0e0f00910203040506077583a2cf8264910e1436bda32571012f0";
let uint = U256::from_str(hex).unwrap(); let uint = U256::from_str(hex).unwrap();
let mut bytes = [0u8; 32]; let mut bytes = [0u8; 32];
uint.to_raw_bytes(&mut bytes); uint.to_big_endian(&mut bytes);
let uint2 = U256::from(&bytes[..]); let uint2 = U256::from(&bytes[..]);
assert_eq!(uint, uint2); assert_eq!(uint, uint2);
} }
@ -2021,6 +2030,44 @@ mod tests {
assert!(overflow); 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] #[test]
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))] #[cfg_attr(feature="dev", allow(cyclomatic_complexity))]

View File

@ -445,7 +445,7 @@ macro_rules! impl_hash {
impl From<U256> for H256 { impl From<U256> for H256 {
fn from(value: U256) -> H256 { fn from(value: U256) -> H256 {
let mut ret = H256::new(); let mut ret = H256::new();
value.to_raw_bytes(&mut ret); value.to_big_endian(&mut ret);
ret ret
} }
} }
@ -453,7 +453,7 @@ impl From<U256> for H256 {
impl<'a> From<&'a U256> for H256 { impl<'a> From<&'a U256> for H256 {
fn from(value: &'a U256) -> H256 { fn from(value: &'a U256) -> H256 {
let mut ret: H256 = H256::new(); let mut ret: H256 = H256::new();
value.to_raw_bytes(&mut ret); value.to_big_endian(&mut ret);
ret ret
} }
} }