@@ -3,20 +3,20 @@ use crate::{
3
3
primitives:: { Spec , B256 , KECCAK_EMPTY , U256 } ,
4
4
Host , InstructionResult , Interpreter ,
5
5
} ;
6
+ use core:: ptr;
6
7
7
8
pub fn keccak256 < H : Host + ?Sized > ( interpreter : & mut Interpreter , _host : & mut H ) {
8
- pop ! ( interpreter, from , len ) ;
9
- let len = as_usize_or_fail ! ( interpreter, len ) ;
9
+ pop_top ! ( interpreter, offset , len_ptr ) ;
10
+ let len = as_usize_or_fail ! ( interpreter, len_ptr ) ;
10
11
gas_or_fail ! ( interpreter, gas:: keccak256_cost( len as u64 ) ) ;
11
12
let hash = if len == 0 {
12
13
KECCAK_EMPTY
13
14
} else {
14
- let from = as_usize_or_fail ! ( interpreter, from ) ;
15
+ let from = as_usize_or_fail ! ( interpreter, offset ) ;
15
16
resize_memory ! ( interpreter, from, len) ;
16
17
crate :: primitives:: keccak256 ( interpreter. shared_memory . slice ( from, len) )
17
18
} ;
18
-
19
- push_b256 ! ( interpreter, hash) ;
19
+ * len_ptr = hash. into ( ) ;
20
20
}
21
21
22
22
pub fn address < H : Host + ?Sized > ( interpreter : & mut Interpreter , _host : & mut H ) {
@@ -56,18 +56,25 @@ pub fn codecopy<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H)
56
56
57
57
pub fn calldataload < H : Host + ?Sized > ( interpreter : & mut Interpreter , _host : & mut H ) {
58
58
gas ! ( interpreter, gas:: VERYLOW ) ;
59
- pop ! ( interpreter, index) ;
60
- let index = as_usize_saturated ! ( index) ;
61
- let load = if index < interpreter. contract . input . len ( ) {
62
- let have_bytes = 32 . min ( interpreter. contract . input . len ( ) - index) ;
63
- let mut bytes = [ 0u8 ; 32 ] ;
64
- bytes[ ..have_bytes] . copy_from_slice ( & interpreter. contract . input [ index..index + have_bytes] ) ;
65
- B256 :: new ( bytes)
66
- } else {
67
- B256 :: ZERO
68
- } ;
69
-
70
- push_b256 ! ( interpreter, load) ;
59
+ pop_top ! ( interpreter, offset_ptr) ;
60
+ let mut word = B256 :: ZERO ;
61
+ let offset = as_usize_saturated ! ( offset_ptr) ;
62
+ if offset < interpreter. contract . input . len ( ) {
63
+ let count = 32 . min ( interpreter. contract . input . len ( ) - offset) ;
64
+ // SAFETY: count is bounded by the calldata length.
65
+ // This is `word[..count].copy_from_slice(input[offset..offset + count])`, written using
66
+ // raw pointers as apparently the compiler cannot optimize the slice version, and using
67
+ // `get_unchecked` twice is uglier.
68
+ debug_assert ! ( count <= 32 && offset + count <= interpreter. contract. input. len( ) ) ;
69
+ unsafe {
70
+ ptr:: copy_nonoverlapping (
71
+ interpreter. contract . input . as_ptr ( ) . add ( offset) ,
72
+ word. as_mut_ptr ( ) ,
73
+ count,
74
+ )
75
+ } ;
76
+ }
77
+ * offset_ptr = word. into ( ) ;
71
78
}
72
79
73
80
pub fn calldatasize < H : Host + ?Sized > ( interpreter : & mut Interpreter , _host : & mut H ) {
0 commit comments