Skip to content

Commit fcaac7f

Browse files
authored
Feat: optimizations - CALLDATALOAD, add constants for U256, code refactoring (#87)
* Optimizations: CALLDATALOAD, added constants for U256: ZERO, ONE * Memory optimizations * Refactoring and omptimizations * Changed const init for: U256_ZERO, U256_ONE
1 parent 17aeb0a commit fcaac7f

18 files changed

Lines changed: 266 additions & 343 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ members = [
88
[workspace.package]
99
authors = ["Aurora Labs <hello@aurora.dev>"]
1010
edition = "2021"
11-
version = "2.0.0"
11+
version = "2.1.0"
1212
description = "Aurora Ethereum Virtual Machine implementation written in pure Rust"
1313
categories = ["no-std", "compilers", "cryptography::cryptocurrencies"]
1414
keywords = ["aurora-evm", "evm", "ethereum", "blockchain", "no_std"]

evm/src/backend/memory.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::{Apply, ApplyBackend, Backend, Basic, Log};
2+
use crate::core::utils::{U256_ONE, U256_ZERO};
23
use crate::prelude::*;
34
use primitive_types::{H160, H256, U256};
45

@@ -106,12 +107,12 @@ impl Backend for MemoryBackend<'_> {
106107
}
107108
fn block_hash(&self, number: U256) -> H256 {
108109
if number >= self.vicinity.block_number
109-
|| self.vicinity.block_number - number - U256::one()
110+
|| self.vicinity.block_number - number - U256_ONE
110111
>= U256::from(self.vicinity.block_hashes.len())
111112
{
112113
H256::default()
113114
} else {
114-
let index = (self.vicinity.block_number - number - U256::one()).as_usize();
115+
let index = (self.vicinity.block_number - number - U256_ONE).as_usize();
115116
self.vicinity.block_hashes[index]
116117
}
117118
}
@@ -233,8 +234,8 @@ impl ApplyBackend for MemoryBackend<'_> {
233234
}
234235
}
235236

236-
account.balance == U256::zero()
237-
&& account.nonce == U256::zero()
237+
account.balance == U256_ZERO
238+
&& account.nonce == U256_ZERO
238239
&& account.code.is_empty()
239240
};
240241

evm/src/core/eval/arithmetic.rs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use crate::core::utils::I256;
2+
use crate::utils::{U256_ONE, U256_VALUE_32, U256_ZERO};
23
use core::convert::TryInto;
34
use core::ops::Rem;
45
use primitive_types::{U256, U512};
56

67
#[inline]
78
pub fn div(op1: U256, op2: U256) -> U256 {
8-
if op2 == U256::zero() {
9-
U256::zero()
9+
if op2 == U256_ZERO {
10+
U256_ZERO
1011
} else {
1112
op1 / op2
1213
}
@@ -22,17 +23,17 @@ pub fn sdiv(op1: U256, op2: U256) -> U256 {
2223

2324
#[inline]
2425
pub fn rem(op1: U256, op2: U256) -> U256 {
25-
if op2 == U256::zero() {
26-
U256::zero()
26+
if op2 == U256_ZERO {
27+
U256_ZERO
2728
} else {
2829
op1.rem(op2)
2930
}
3031
}
3132

3233
#[inline]
3334
pub fn srem(op1: U256, op2: U256) -> U256 {
34-
if op2 == U256::zero() {
35-
U256::zero()
35+
if op2 == U256_ZERO {
36+
U256_ZERO
3637
} else {
3738
let op1: I256 = op1.into();
3839
let op2: I256 = op2.into();
@@ -48,11 +49,10 @@ pub fn addmod(op1: U256, op2: U256, op3: U256) -> U256 {
4849
let op3: U512 = op3.into();
4950

5051
if op3 == U512::zero() {
51-
U256::zero()
52+
U256_ZERO
5253
} else {
5354
let v = (op1 + op2) % op3;
54-
v.try_into()
55-
.expect("op3 is less than U256::MAX, thus it never overflows; qed")
55+
v.try_into().expect("ADDMOD_OP3_OVERFLOW")
5656
}
5757
}
5858

@@ -63,11 +63,10 @@ pub fn mulmod(op1: U256, op2: U256, op3: U256) -> U256 {
6363
let op3: U512 = op3.into();
6464

6565
if op3 == U512::zero() {
66-
U256::zero()
66+
U256_ZERO
6767
} else {
6868
let v = (op1 * op2) % op3;
69-
v.try_into()
70-
.expect("op3 is less than U256::MAX, thus it never overflows; qed")
69+
v.try_into().expect("MULMOD_OP3_OVERFLOW")
7170
}
7271
}
7372

@@ -77,8 +76,8 @@ pub fn exp(op1: U256, op2: U256) -> U256 {
7776
let mut op2 = op2;
7877
let mut r: U256 = 1.into();
7978

80-
while op2 != 0.into() {
81-
if op2 & 1.into() != 0.into() {
79+
while op2 != U256_ZERO {
80+
if op2 & U256_ONE != U256_ZERO {
8281
r = r.overflowing_mul(op1).0;
8382
}
8483
op2 >>= 1;
@@ -105,12 +104,12 @@ pub fn exp(op1: U256, op2: U256) -> U256 {
105104
/// bits from `b`; this is equal to `y & mask` where `&` is bitwise `AND`.
106105
#[inline]
107106
pub fn signextend(op1: U256, op2: U256) -> U256 {
108-
if op1 < U256::from(32) {
107+
if op1 < U256_VALUE_32 {
109108
// `low_u32` works since op1 < 32
110109
#[allow(clippy::as_conversions)]
111110
let bit_index = (8 * op1.low_u32() + 7) as usize;
112111
let bit = op2.bit(bit_index);
113-
let mask = (U256::one() << bit_index) - U256::one();
112+
let mask = (U256_ONE << bit_index) - U256_ONE;
114113
if bit {
115114
op2 | !mask
116115
} else {
@@ -124,21 +123,22 @@ pub fn signextend(op1: U256, op2: U256) -> U256 {
124123
#[cfg(test)]
125124
mod tests {
126125
use super::{signextend, U256};
126+
use crate::utils::{U256_ONE, U256_VALUE_32, U256_ZERO};
127127

128128
/// Test to ensure new (optimized) `signextend` implementation is equivalent to the previous
129129
/// implementation.
130130
#[test]
131131
fn test_signextend() {
132132
let test_values = vec![
133-
U256::zero(),
134-
U256::one(),
133+
U256_ZERO,
134+
U256_ONE,
135135
U256::from(8),
136136
U256::from(10),
137137
U256::from(65),
138138
U256::from(100),
139139
U256::from(128),
140-
U256::from(11) * (U256::one() << 65),
141-
U256::from(7) * (U256::one() << 123),
140+
U256::from(11) * (U256_ONE << 65),
141+
U256::from(7) * (U256_ONE << 123),
142142
U256::MAX / 167,
143143
U256::MAX,
144144
];
@@ -157,16 +157,16 @@ mod tests {
157157
}
158158

159159
fn old_signextend(op1: U256, op2: U256) -> U256 {
160-
if op1 > U256::from(32) {
160+
if op1 > U256_VALUE_32 {
161161
op2
162162
} else {
163-
let mut ret = U256::zero();
163+
let mut ret = U256_ZERO;
164164
let len: usize = op1.as_usize();
165165
let t: usize = 8 * (len + 1) - 1;
166-
let t_bit_mask = U256::one() << t;
166+
let t_bit_mask = U256_ONE << t;
167167
let t_value = (op2 & t_bit_mask) >> t;
168168
for i in 0..256 {
169-
let bit_mask = U256::one() << i;
169+
let bit_mask = U256_ONE << i;
170170
let i_value = (op2 & bit_mask) >> i;
171171
if i <= t {
172172
ret = ret.overflowing_add(i_value << i).0;

evm/src/core/eval/bitwise.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::core::utils::{Sign, I256};
2+
use crate::utils::{U256_ONE, U256_VALUE_256, U256_VALUE_32, U256_ZERO};
23
use primitive_types::U256;
34

45
#[inline]
@@ -7,9 +8,9 @@ pub fn slt(op1: U256, op2: U256) -> U256 {
78
let op2: I256 = op2.into();
89

910
if op1.lt(&op2) {
10-
U256::one()
11+
U256_ONE
1112
} else {
12-
U256::zero()
13+
U256_ZERO
1314
}
1415
}
1516

@@ -19,18 +20,18 @@ pub fn sgt(op1: U256, op2: U256) -> U256 {
1920
let op2: I256 = op2.into();
2021

2122
if op1.gt(&op2) {
22-
U256::one()
23+
U256_ONE
2324
} else {
24-
U256::zero()
25+
U256_ZERO
2526
}
2627
}
2728

2829
#[inline]
2930
pub fn iszero(op1: U256) -> U256 {
30-
if op1 == U256::zero() {
31-
U256::one()
31+
if op1 == U256_ZERO {
32+
U256_ONE
3233
} else {
33-
U256::zero()
34+
U256_ZERO
3435
}
3536
}
3637

@@ -41,12 +42,12 @@ pub fn not(op1: U256) -> U256 {
4142

4243
#[inline]
4344
pub fn byte(op1: U256, op2: U256) -> U256 {
44-
let mut ret = U256::zero();
45-
if op1 < 32.into() {
45+
let mut ret = U256_ZERO;
46+
if op1 < U256_VALUE_32 {
4647
let o = op1.as_usize();
4748
for i in 0..8 {
4849
let t = 255 - (7 - i + 8 * o);
49-
let value = (op2 >> t) & U256::one();
50+
let value = (op2 >> t) & U256_ONE;
5051
ret = ret.overflowing_add(value << i).0;
5152
}
5253
}
@@ -55,17 +56,17 @@ pub fn byte(op1: U256, op2: U256) -> U256 {
5556

5657
#[inline]
5758
pub fn shl(shift: U256, value: U256) -> U256 {
58-
if value == U256::zero() || shift >= U256::from(256) {
59-
U256::zero()
59+
if value == U256_ZERO || shift >= U256_VALUE_256 {
60+
U256_ZERO
6061
} else {
6162
value << shift.as_usize()
6263
}
6364
}
6465

6566
#[inline]
6667
pub fn shr(shift: U256, value: U256) -> U256 {
67-
if value == U256::zero() || shift >= U256::from(256) {
68-
U256::zero()
68+
if value == U256_ZERO || shift >= U256_VALUE_256 {
69+
U256_ZERO
6970
} else {
7071
value >> shift.as_usize()
7172
}
@@ -75,22 +76,21 @@ pub fn shr(shift: U256, value: U256) -> U256 {
7576
pub fn sar(shift: U256, value: U256) -> U256 {
7677
let value = I256::from(value);
7778

78-
if value == I256::zero() || shift >= U256::from(256) {
79+
if value == I256::zero() || shift >= U256_VALUE_256 {
7980
let I256(sign, _) = value;
8081
match sign {
8182
// value is 0 or >=1, pushing 0
82-
Sign::Plus | Sign::Zero => U256::zero(),
83+
Sign::Plus | Sign::Zero => U256_ZERO,
8384
// value is <0, pushing -1
84-
Sign::Minus => I256(Sign::Minus, U256::one()).into(),
85+
Sign::Minus => I256(Sign::Minus, U256_ONE).into(),
8586
}
8687
} else {
87-
let shift: usize = shift.as_usize();
88-
88+
let shift = shift.as_usize();
8989
match value.0 {
9090
Sign::Plus | Sign::Zero => value.1 >> shift,
9191
Sign::Minus => {
92-
let shifted = ((value.1.overflowing_sub(U256::one()).0) >> shift)
93-
.overflowing_add(U256::one())
92+
let shifted = ((value.1.overflowing_sub(U256_ONE).0) >> shift)
93+
.overflowing_add(U256_ONE)
9494
.0;
9595
I256(Sign::Minus, shifted).into()
9696
}

evm/src/core/eval/macros.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,11 @@ macro_rules! op1_u256_fn {
7474

7575
macro_rules! op2_u256_bool_ref {
7676
( $machine:expr, $op:ident ) => {{
77+
use crate::utils::{U256_ONE, U256_ZERO};
78+
7779
pop_u256!($machine, op1, op2);
7880
let ret = op1.$op(&op2);
79-
push_u256!($machine, if ret { U256::one() } else { U256::zero() });
81+
push_u256!($machine, if ret { U256_ONE } else { U256_ZERO });
8082
trace_op!("{} {}, {}: {}", stringify!($op), op1, op2, ret);
8183

8284
Control::Continue(1)

0 commit comments

Comments
 (0)