From 6a97ea0ba74b51c06adb1ba6b3334f971ad02d3b Mon Sep 17 00:00:00 2001 From: Anton Lisanin Date: Wed, 9 Jun 2021 08:44:02 +0300 Subject: [PATCH 1/2] Optimize U256 conversions --- core/src/eval/misc.rs | 2 +- core/src/primitive_types.rs | 22 ++++++++++++++++++++++ core/src/stack.rs | 4 ++-- runtime/src/eval/macros.rs | 8 +++----- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/core/src/eval/misc.rs b/core/src/eval/misc.rs index 102b1fb71..c23faaae3 100644 --- a/core/src/eval/misc.rs +++ b/core/src/eval/misc.rs @@ -153,7 +153,7 @@ pub fn msize(state: &mut Machine) -> Control { pub fn push(state: &mut Machine, n: usize, position: usize) -> Control { let end = min(position + 1 + n, state.code.len()); - let val = U256::from(&state.code[(position + 1)..end]); + let val = U256::from_big_endian_fast(&state.code[(position + 1)..end]); push_u256!(state, val); trace_op!("Push [@{}]: {}", state.stack.len() - 1, val); diff --git a/core/src/primitive_types.rs b/core/src/primitive_types.rs index ba09c85a6..8d4376e82 100644 --- a/core/src/primitive_types.rs +++ b/core/src/primitive_types.rs @@ -171,4 +171,26 @@ impl<'de> serde::Deserialize<'de> for U256 { deserializer.deserialize_bytes(Visitor) } +} + + +impl U256 { + pub fn into_big_endian_fast(self, buffer: &mut [u8]) { + let data: [u8; 32] = unsafe { core::mem::transmute(self) }; + + let buffer = &mut buffer[0..32]; + buffer.copy_from_slice(&data[..]); + buffer.reverse(); + } + + pub fn from_big_endian_fast(buffer: &[u8]) -> U256 { + assert!(32 >= buffer.len()); + + let mut data = [0u8; 32]; + + data[32 - buffer.len()..32].copy_from_slice(buffer); + data.reverse(); + + unsafe { core::mem::transmute(data) } + } } \ No newline at end of file diff --git a/core/src/stack.rs b/core/src/stack.rs index 8fa1c1f28..e129872f9 100644 --- a/core/src/stack.rs +++ b/core/src/stack.rs @@ -83,7 +83,7 @@ impl Stack { self.data.pop() .map(|d| { let mut value = H256::default(); - d.to_big_endian(&mut value[..]); + d.into_big_endian_fast(&mut value[..]); value }) .ok_or(ExitError::StackUnderflow) @@ -95,7 +95,7 @@ impl Stack { if self.data.len() + 1 > self.limit { return Err(ExitError::StackOverflow) } - self.data.push(U256::from_big_endian(&value[..])); + self.data.push(U256::from_big_endian_fast(&value[..])); Ok(()) } diff --git a/runtime/src/eval/macros.rs b/runtime/src/eval/macros.rs index fa2caab08..ca8538497 100644 --- a/runtime/src/eval/macros.rs +++ b/runtime/src/eval/macros.rs @@ -21,8 +21,8 @@ macro_rules! pop { macro_rules! pop_u256 { ( $machine:expr, $( $x:ident ),* ) => ( $( - let $x = match $machine.machine.stack_mut().pop() { - Ok(value) => U256::from_big_endian(&value[..]), + let $x = match $machine.machine.stack_mut().pop_u256() { + Ok(value) => value, Err(e) => return Control::Exit(e.into()), }; )* @@ -43,9 +43,7 @@ macro_rules! push { macro_rules! push_u256 { ( $machine:expr, $( $x:expr ),* ) => ( $( - let mut value = H256::default(); - $x.to_big_endian(&mut value[..]); - match $machine.machine.stack_mut().push(value) { + match $machine.machine.stack_mut().push_u256($x) { Ok(()) => (), Err(e) => return Control::Exit(e.into()), } From b1c4832ac00885723e554089947e1f7d17929b3b Mon Sep 17 00:00:00 2001 From: Anton Lisanin Date: Wed, 9 Jun 2021 08:44:28 +0300 Subject: [PATCH 2/2] Optimize calldataload --- core/src/eval/misc.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/core/src/eval/misc.rs b/core/src/eval/misc.rs index c23faaae3..6eccff754 100644 --- a/core/src/eval/misc.rs +++ b/core/src/eval/misc.rs @@ -28,17 +28,11 @@ pub fn calldataload(state: &mut Machine) -> Control { pop_u256!(state, index); trace_op!("CallDataLoad: {}", index); + let index = as_usize_or_fail!(index); + let len = if index > state.data.len() { 0 } else { min(32, state.data.len() - index) }; + let mut load = [0u8; 32]; - for i in 0..32 { - if let Some(p) = index.checked_add(U256::from(i)) { - if p <= U256::from(usize::max_value()) { - let p = p.as_usize(); - if p < state.data.len() { - load[i] = state.data[p]; - } - } - } - } + load[0..len].copy_from_slice(&state.data[index..index + len]); push!(state, H256::from(load)); Control::Continue(1)