2019-01-07 11:33:07 +01:00
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
2016-02-05 13:40:41 +01:00
2019-01-07 11:33:07 +01:00
// Parity Ethereum is free software: you can redistribute it and/or modify
2016-02-05 13:40:41 +01:00
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
2019-01-07 11:33:07 +01:00
// Parity Ethereum is distributed in the hope that it will be useful,
2016-02-05 13:40:41 +01:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
2019-01-07 11:33:07 +01:00
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
2016-02-05 13:40:41 +01:00
2016-07-11 09:42:41 +02:00
//! Rust VM implementation
2016-01-13 00:13:09 +01:00
2016-10-03 23:29:46 +02:00
#[ macro_use ]
mod informant ;
2016-07-05 15:15:44 +02:00
mod gasometer ;
mod stack ;
mod memory ;
2016-10-02 18:45:36 +02:00
mod shared_cache ;
2016-07-05 15:15:44 +02:00
2017-07-29 17:12:07 +02:00
use std ::marker ::PhantomData ;
use std ::{ cmp , mem } ;
2017-07-29 21:56:42 +02:00
use std ::sync ::Arc ;
2017-08-30 19:18:28 +02:00
use hash ::keccak ;
2018-08-13 22:06:15 +02:00
use bytes ::Bytes ;
2018-01-10 13:35:18 +01:00
use ethereum_types ::{ U256 , U512 , H256 , Address } ;
2017-08-01 12:37:57 +02:00
use vm ::{
2018-08-13 22:06:15 +02:00
self , ActionParams , ParamsType , ActionValue , CallType , MessageCallResult ,
2018-10-02 16:33:19 +02:00
ContractCreateResult , CreateContractAddress , ReturnData , GasLeft , Schedule ,
TrapKind , TrapError
2017-08-01 12:37:57 +02:00
} ;
use evm ::CostType ;
use instructions ::{ self , Instruction , InstructionInfo } ;
2016-07-05 15:15:44 +02:00
use self ::gasometer ::Gasometer ;
use self ::stack ::{ Stack , VecStack } ;
use self ::memory ::Memory ;
2016-10-02 18:45:36 +02:00
pub use self ::shared_cache ::SharedCache ;
2016-07-05 15:15:44 +02:00
2016-07-30 15:38:44 +02:00
use bit_set ::BitSet ;
2016-07-05 15:15:44 +02:00
2018-08-13 22:06:15 +02:00
const GASOMETER_PROOF : & str = " If gasometer is None, Err is immediately returned in step; this function is only called by step; qed " ;
2016-01-13 00:13:09 +01:00
type ProgramCounter = usize ;
2016-09-27 11:27:11 +02:00
const ONE : U256 = U256 ( [ 1 , 0 , 0 , 0 ] ) ;
const TWO : U256 = U256 ( [ 2 , 0 , 0 , 0 ] ) ;
const TWO_POW_5 : U256 = U256 ( [ 0x20 , 0 , 0 , 0 ] ) ;
const TWO_POW_8 : U256 = U256 ( [ 0x100 , 0 , 0 , 0 ] ) ;
const TWO_POW_16 : U256 = U256 ( [ 0x10000 , 0 , 0 , 0 ] ) ;
const TWO_POW_24 : U256 = U256 ( [ 0x1000000 , 0 , 0 , 0 ] ) ;
const TWO_POW_64 : U256 = U256 ( [ 0 , 0x1 , 0 , 0 ] ) ; // 0x1 00000000 00000000
const TWO_POW_96 : U256 = U256 ( [ 0 , 0x100000000 , 0 , 0 ] ) ; //0x1 00000000 00000000 00000000
const TWO_POW_224 : U256 = U256 ( [ 0 , 0 , 0 , 0x100000000 ] ) ; //0x1 00000000 00000000 00000000 00000000 00000000 00000000 00000000
const TWO_POW_248 : U256 = U256 ( [ 0 , 0 , 0 , 0x100000000000000 ] ) ; //0x1 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000000
2016-01-13 00:13:09 +01:00
/// Abstraction over raw vector of Bytes. Easier state management of PC.
2018-08-13 22:06:15 +02:00
struct CodeReader {
2016-01-13 00:13:09 +01:00
position : ProgramCounter ,
2018-08-13 22:06:15 +02:00
code : Arc < Bytes > ,
2016-01-13 00:13:09 +01:00
}
2016-01-16 17:08:57 +01:00
2018-08-13 22:06:15 +02:00
impl CodeReader {
2016-10-03 23:29:46 +02:00
/// Create new code reader - starting at position 0.
2018-08-13 22:06:15 +02:00
fn new ( code : Arc < Bytes > ) -> Self {
2016-10-03 23:29:46 +02:00
CodeReader {
2018-08-13 22:06:15 +02:00
code ,
2016-10-03 23:29:46 +02:00
position : 0 ,
}
}
2016-01-13 00:13:09 +01:00
/// Get `no_of_bytes` from code and convert to U256. Move PC
fn read ( & mut self , no_of_bytes : usize ) -> U256 {
2016-01-14 01:05:01 +01:00
let pos = self . position ;
2016-01-13 00:13:09 +01:00
self . position + = no_of_bytes ;
2016-01-15 22:46:29 +01:00
let max = cmp ::min ( pos + no_of_bytes , self . code . len ( ) ) ;
U256 ::from ( & self . code [ pos .. max ] )
2016-01-13 00:13:09 +01:00
}
2018-06-27 13:33:32 +02:00
fn len ( & self ) -> usize {
2016-01-13 01:53:33 +01:00
self . code . len ( )
}
2016-01-13 15:21:13 +01:00
}
2016-01-13 00:13:09 +01:00
2016-07-05 15:15:44 +02:00
enum InstructionResult < Gas > {
2016-01-16 20:11:12 +01:00
Ok ,
2016-07-05 15:15:44 +02:00
UnusedGas ( Gas ) ,
2016-01-13 15:21:13 +01:00
JumpToPosition ( U256 ) ,
2017-05-23 15:49:17 +02:00
StopExecutionNeedsReturn {
/// Gas left.
gas : Gas ,
/// Return data offset.
init_off : U256 ,
/// Return data size.
init_size : U256 ,
/// Apply or revert state changes.
apply : bool ,
} ,
2016-06-02 19:04:15 +02:00
StopExecution ,
2018-10-02 16:33:19 +02:00
Trap ( TrapKind ) ,
2016-01-13 00:13:09 +01:00
}
2018-08-13 22:06:15 +02:00
enum Never { }
/// ActionParams without code, so that it can be feed into CodeReader.
#[ derive(Debug) ]
struct InterpreterParams {
/// Address of currently executed code.
pub code_address : Address ,
/// Hash of currently executed code.
pub code_hash : Option < H256 > ,
/// Receive address. Usually equal to code_address,
/// except when called using CALLCODE.
pub address : Address ,
/// Sender of current part of the transaction.
pub sender : Address ,
/// Transaction initiator.
pub origin : Address ,
/// Gas paid up front for transaction execution
pub gas : U256 ,
/// Gas price.
pub gas_price : U256 ,
/// Transaction value.
pub value : ActionValue ,
/// Input data.
pub data : Option < Bytes > ,
/// Type of call
pub call_type : CallType ,
/// Param types encoding
pub params_type : ParamsType ,
}
impl From < ActionParams > for InterpreterParams {
fn from ( params : ActionParams ) -> Self {
InterpreterParams {
code_address : params . code_address ,
code_hash : params . code_hash ,
address : params . address ,
sender : params . sender ,
origin : params . origin ,
gas : params . gas ,
gas_price : params . gas_price ,
value : params . value ,
data : params . data ,
call_type : params . call_type ,
params_type : params . params_type ,
}
}
}
/// Stepping result returned by interpreter.
pub enum InterpreterResult {
/// The VM has already stopped.
Stopped ,
/// The VM has just finished execution in the current step.
Done ( vm ::Result < GasLeft > ) ,
/// The VM can continue to run.
Continue ,
2018-10-02 16:33:19 +02:00
Trap ( TrapKind ) ,
2018-08-13 22:06:15 +02:00
}
impl From < vm ::Error > for InterpreterResult {
fn from ( error : vm ::Error ) -> InterpreterResult {
InterpreterResult ::Done ( Err ( error ) )
}
}
2016-01-16 17:08:57 +01:00
/// Intepreter EVM implementation
2016-07-05 15:15:44 +02:00
pub struct Interpreter < Cost : CostType > {
2016-06-02 19:04:15 +02:00
mem : Vec < u8 > ,
2016-10-02 18:45:36 +02:00
cache : Arc < SharedCache > ,
2018-08-13 22:06:15 +02:00
params : InterpreterParams ,
reader : CodeReader ,
2017-06-06 17:47:12 +02:00
return_data : ReturnData ,
2018-08-13 22:06:15 +02:00
informant : informant ::EvmInformant ,
do_trace : bool ,
done : bool ,
valid_jump_destinations : Option < Arc < BitSet > > ,
gasometer : Option < Gasometer < Cost > > ,
stack : VecStack < U256 > ,
2018-10-02 16:33:19 +02:00
resume_output_range : Option < ( U256 , U256 ) > ,
resume_result : Option < InstructionResult < Cost > > ,
last_stack_ret_len : usize ,
2016-07-05 15:15:44 +02:00
_type : PhantomData < Cost > ,
2016-06-02 19:04:15 +02:00
}
2016-01-13 00:13:09 +01:00
2018-10-02 16:33:19 +02:00
impl < Cost : 'static + CostType > vm ::Exec for Interpreter < Cost > {
fn exec ( mut self : Box < Self > , ext : & mut vm ::Ext ) -> vm ::ExecTrapResult < GasLeft > {
2018-08-13 22:06:15 +02:00
loop {
let result = self . step ( ext ) ;
match result {
InterpreterResult ::Continue = > { } ,
2018-10-02 16:33:19 +02:00
InterpreterResult ::Done ( value ) = > return Ok ( value ) ,
InterpreterResult ::Trap ( trap ) = > match trap {
TrapKind ::Call ( params ) = > {
return Err ( TrapError ::Call ( params , self ) ) ;
} ,
TrapKind ::Create ( params , address ) = > {
return Err ( TrapError ::Create ( params , address , self ) ) ;
} ,
} ,
2018-08-13 22:06:15 +02:00
InterpreterResult ::Stopped = > panic! ( " Attempted to execute an already stopped VM. " )
}
}
}
}
2016-06-02 19:04:15 +02:00
2018-10-02 16:33:19 +02:00
impl < Cost : 'static + CostType > vm ::ResumeCall for Interpreter < Cost > {
fn resume_call ( mut self : Box < Self > , result : MessageCallResult ) -> Box < vm ::Exec > {
{
let this = & mut * self ;
let ( out_off , out_size ) = this . resume_output_range . take ( ) . expect ( " Box<ResumeCall> is obtained from a call opcode; resume_output_range is always set after those opcodes are executed; qed " ) ;
match result {
MessageCallResult ::Success ( gas_left , data ) = > {
let output = this . mem . writeable_slice ( out_off , out_size ) ;
let len = cmp ::min ( output . len ( ) , data . len ( ) ) ;
( & mut output [ .. len ] ) . copy_from_slice ( & data [ .. len ] ) ;
this . return_data = data ;
this . stack . push ( U256 ::one ( ) ) ;
this . resume_result = Some ( InstructionResult ::UnusedGas ( Cost ::from_u256 ( gas_left ) . expect ( " Gas left cannot be greater than current one " ) ) ) ;
} ,
MessageCallResult ::Reverted ( gas_left , data ) = > {
let output = this . mem . writeable_slice ( out_off , out_size ) ;
let len = cmp ::min ( output . len ( ) , data . len ( ) ) ;
( & mut output [ .. len ] ) . copy_from_slice ( & data [ .. len ] ) ;
this . return_data = data ;
this . stack . push ( U256 ::zero ( ) ) ;
this . resume_result = Some ( InstructionResult ::UnusedGas ( Cost ::from_u256 ( gas_left ) . expect ( " Gas left cannot be greater than current one " ) ) ) ;
} ,
MessageCallResult ::Failed = > {
this . stack . push ( U256 ::zero ( ) ) ;
this . resume_result = Some ( InstructionResult ::Ok ) ;
} ,
}
}
self
}
}
impl < Cost : 'static + CostType > vm ::ResumeCreate for Interpreter < Cost > {
fn resume_create ( mut self : Box < Self > , result : ContractCreateResult ) -> Box < vm ::Exec > {
match result {
ContractCreateResult ::Created ( address , gas_left ) = > {
self . stack . push ( address_to_u256 ( address ) ) ;
self . resume_result = Some ( InstructionResult ::UnusedGas ( Cost ::from_u256 ( gas_left ) . expect ( " Gas left cannot be greater. " ) ) ) ;
} ,
ContractCreateResult ::Reverted ( gas_left , return_data ) = > {
self . stack . push ( U256 ::zero ( ) ) ;
self . return_data = return_data ;
self . resume_result = Some ( InstructionResult ::UnusedGas ( Cost ::from_u256 ( gas_left ) . expect ( " Gas left cannot be greater. " ) ) ) ;
} ,
ContractCreateResult ::Failed = > {
self . stack . push ( U256 ::zero ( ) ) ;
self . resume_result = Some ( InstructionResult ::Ok ) ;
} ,
}
self
}
}
2018-08-13 22:06:15 +02:00
impl < Cost : CostType > Interpreter < Cost > {
/// Create a new `Interpreter` instance with shared cache.
pub fn new ( mut params : ActionParams , cache : Arc < SharedCache > , schedule : & Schedule , depth : usize ) -> Interpreter < Cost > {
let reader = CodeReader ::new ( params . code . take ( ) . expect ( " VM always called with code; qed " ) ) ;
let params = InterpreterParams ::from ( params ) ;
let informant = informant ::EvmInformant ::new ( depth ) ;
let valid_jump_destinations = None ;
let gasometer = Cost ::from_u256 ( params . gas ) . ok ( ) . map ( | gas | Gasometer ::< Cost > ::new ( gas ) ) ;
let stack = VecStack ::with_capacity ( schedule . stack_limit , U256 ::zero ( ) ) ;
2016-10-03 23:29:46 +02:00
2018-08-13 22:06:15 +02:00
Interpreter {
cache , params , reader , informant ,
valid_jump_destinations , gasometer , stack ,
done : false ,
do_trace : true ,
mem : Vec ::new ( ) ,
return_data : ReturnData ::empty ( ) ,
2018-10-02 16:33:19 +02:00
last_stack_ret_len : 0 ,
resume_output_range : None ,
resume_result : None ,
2018-08-13 22:06:15 +02:00
_type : PhantomData ,
}
}
2016-01-13 00:13:09 +01:00
2018-08-13 22:06:15 +02:00
/// Execute a single step on the VM.
#[ inline(always) ]
pub fn step ( & mut self , ext : & mut vm ::Ext ) -> InterpreterResult {
if self . done {
return InterpreterResult ::Stopped ;
}
2016-01-13 00:13:09 +01:00
2018-08-13 22:06:15 +02:00
let result = if self . gasometer . is_none ( ) {
InterpreterResult ::Done ( Err ( vm ::Error ::OutOfGas ) )
} else if self . reader . len ( ) = = 0 {
InterpreterResult ::Done ( Ok ( GasLeft ::Known ( self . gasometer . as_ref ( ) . expect ( " Gasometer None case is checked above; qed " ) . current_gas . as_u256 ( ) ) ) )
} else {
self . step_inner ( ext ) . err ( ) . expect ( " step_inner never returns Ok(()); qed " )
} ;
2016-01-14 11:00:29 +01:00
2018-08-13 22:06:15 +02:00
if let & InterpreterResult ::Done ( _ ) = & result {
self . done = true ;
self . informant . done ( ) ;
}
return result ;
}
2017-07-10 13:23:40 +02:00
2018-08-13 22:06:15 +02:00
/// Inner helper function for step.
#[ inline(always) ]
fn step_inner ( & mut self , ext : & mut vm ::Ext ) -> Result < Never , InterpreterResult > {
2018-10-02 16:33:19 +02:00
let result = match self . resume_result . take ( ) {
Some ( result ) = > result ,
None = > {
let opcode = self . reader . code [ self . reader . position ] ;
let instruction = Instruction ::from_u8 ( opcode ) ;
self . reader . position + = 1 ;
// TODO: make compile-time removable if too much of a performance hit.
self . do_trace = self . do_trace & & ext . trace_next_instruction (
self . reader . position - 1 , opcode , self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas . as_u256 ( ) ,
) ;
2018-06-27 13:33:32 +02:00
2018-10-02 16:33:19 +02:00
let instruction = match instruction {
Some ( i ) = > i ,
None = > return Err ( InterpreterResult ::Done ( Err ( vm ::Error ::BadInstruction {
instruction : opcode
} ) ) ) ,
} ;
2016-06-02 12:40:31 +02:00
2018-10-02 16:33:19 +02:00
let info = instruction . info ( ) ;
self . last_stack_ret_len = info . ret ;
self . verify_instruction ( ext , instruction , info ) ? ;
// Calculate gas cost
let requirements = self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . requirements ( ext , instruction , info , & self . stack , self . mem . size ( ) ) ? ;
if self . do_trace {
ext . trace_prepare_execute ( self . reader . position - 1 , opcode , requirements . gas_cost . as_u256 ( ) , Self ::mem_written ( instruction , & self . stack ) , Self ::store_written ( instruction , & self . stack ) ) ;
}
2016-06-02 12:40:31 +02:00
2018-10-02 16:33:19 +02:00
self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . verify_gas ( & requirements . gas_cost ) ? ;
self . mem . expand ( requirements . memory_required_size ) ;
self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_mem_gas = requirements . memory_total_gas ;
self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas = self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas - requirements . gas_cost ;
2016-01-15 23:32:16 +01:00
2018-10-02 16:33:19 +02:00
evm_debug! ( { self . informant . before_instruction ( self . reader . position , instruction , info , & self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas , & self . stack ) } ) ;
2016-01-15 23:32:16 +01:00
2018-10-02 16:33:19 +02:00
// Execute instruction
let current_gas = self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas ;
let result = self . exec_instruction (
current_gas , ext , instruction , requirements . provide_gas
) ? ;
2016-06-02 12:40:31 +02:00
2018-10-02 16:33:19 +02:00
evm_debug! ( { self . informant . after_instruction ( instruction ) } ) ;
result
} ,
} ;
2016-06-02 12:40:31 +02:00
2018-10-02 16:33:19 +02:00
if let InstructionResult ::Trap ( trap ) = result {
return Err ( InterpreterResult ::Trap ( trap ) ) ;
}
2016-10-03 23:29:46 +02:00
2018-08-13 22:06:15 +02:00
if let InstructionResult ::UnusedGas ( ref gas ) = result {
self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas = self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas + * gas ;
}
2016-10-15 14:39:15 +02:00
2018-08-13 22:06:15 +02:00
if self . do_trace {
ext . trace_executed (
self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas . as_u256 ( ) ,
2018-10-02 16:33:19 +02:00
self . stack . peek_top ( self . last_stack_ret_len ) ,
& self . mem ,
2018-08-13 22:06:15 +02:00
) ;
}
2016-01-14 11:00:29 +01:00
2018-08-13 22:06:15 +02:00
// Advance
match result {
InstructionResult ::JumpToPosition ( position ) = > {
if self . valid_jump_destinations . is_none ( ) {
2018-10-04 13:32:04 +02:00
self . valid_jump_destinations = Some ( self . cache . jump_destinations ( & self . params . code_hash , & self . reader . code ) ) ;
2018-08-13 22:06:15 +02:00
}
let jump_destinations = self . valid_jump_destinations . as_ref ( ) . expect ( " jump_destinations are initialized on first jump; qed " ) ;
let pos = self . verify_jump ( position , jump_destinations ) ? ;
self . reader . position = pos ;
} ,
InstructionResult ::StopExecutionNeedsReturn { gas , init_off , init_size , apply } = > {
let mem = mem ::replace ( & mut self . mem , Vec ::new ( ) ) ;
return Err ( InterpreterResult ::Done ( Ok ( GasLeft ::NeedsReturn {
gas_left : gas . as_u256 ( ) ,
data : mem . into_return_data ( init_off , init_size ) ,
apply_state : apply
} ) ) ) ;
} ,
InstructionResult ::StopExecution = > {
return Err ( InterpreterResult ::Done ( Ok ( GasLeft ::Known ( self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas . as_u256 ( ) ) ) ) ) ;
} ,
_ = > { } ,
2016-01-13 00:13:09 +01:00
}
2018-08-13 22:06:15 +02:00
if self . reader . position > = self . reader . len ( ) {
return Err ( InterpreterResult ::Done ( Ok ( GasLeft ::Known ( self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas . as_u256 ( ) ) ) ) ) ;
2016-10-02 18:45:36 +02:00
}
2018-08-13 22:06:15 +02:00
Err ( InterpreterResult ::Continue )
2016-10-02 18:45:36 +02:00
}
2016-07-05 15:15:44 +02:00
2018-08-13 22:06:15 +02:00
fn verify_instruction ( & self , ext : & vm ::Ext , instruction : Instruction , info : & InstructionInfo ) -> vm ::Result < ( ) > {
2016-01-14 01:56:37 +01:00
let schedule = ext . schedule ( ) ;
2016-01-13 15:21:13 +01:00
2017-04-19 14:30:00 +02:00
if ( instruction = = instructions ::DELEGATECALL & & ! schedule . have_delegate_call ) | |
2017-05-23 15:49:17 +02:00
( instruction = = instructions ::CREATE2 & & ! schedule . have_create2 ) | |
2017-06-19 11:41:46 +02:00
( instruction = = instructions ::STATICCALL & & ! schedule . have_static_call ) | |
2017-07-19 14:34:59 +02:00
( ( instruction = = instructions ::RETURNDATACOPY | | instruction = = instructions ::RETURNDATASIZE ) & & ! schedule . have_return_data ) | |
2018-05-05 10:23:50 +02:00
( instruction = = instructions ::REVERT & & ! schedule . have_revert ) | |
2018-07-31 07:27:57 +02:00
( ( instruction = = instructions ::SHL | | instruction = = instructions ::SHR | | instruction = = instructions ::SAR ) & & ! schedule . have_bitwise_shifting ) | |
( instruction = = instructions ::EXTCODEHASH & & ! schedule . have_extcodehash )
{
2017-08-01 12:37:57 +02:00
return Err ( vm ::Error ::BadInstruction {
2018-06-27 13:33:32 +02:00
instruction : instruction as u8
2016-01-14 02:36:48 +01:00
} ) ;
2016-01-14 01:56:37 +01:00
}
2016-01-13 15:21:13 +01:00
2018-08-13 22:06:15 +02:00
if ! self . stack . has ( info . args ) {
2017-08-01 12:37:57 +02:00
Err ( vm ::Error ::StackUnderflow {
2016-07-05 15:15:44 +02:00
instruction : info . name ,
wanted : info . args ,
2018-08-13 22:06:15 +02:00
on_stack : self . stack . size ( )
2016-07-05 15:15:44 +02:00
} )
2018-08-13 22:06:15 +02:00
} else if self . stack . size ( ) - info . args + info . ret > schedule . stack_limit {
2017-08-01 12:37:57 +02:00
Err ( vm ::Error ::OutOfStack {
2016-07-05 15:15:44 +02:00
instruction : info . name ,
wanted : info . ret - info . args ,
limit : schedule . stack_limit
} )
} else {
Ok ( ( ) )
2016-01-14 01:56:37 +01:00
}
2016-01-13 15:21:13 +01:00
}
2016-01-15 21:46:08 +01:00
2016-06-02 12:40:31 +02:00
fn mem_written (
instruction : Instruction ,
stack : & Stack < U256 >
) -> Option < ( usize , usize ) > {
2017-08-26 21:53:41 +02:00
let read = | pos | stack . peek ( pos ) . low_u64 ( ) as usize ;
let written = match instruction {
instructions ::MSTORE | instructions ::MLOAD = > Some ( ( read ( 0 ) , 32 ) ) ,
instructions ::MSTORE8 = > Some ( ( read ( 0 ) , 1 ) ) ,
instructions ::CALLDATACOPY | instructions ::CODECOPY | instructions ::RETURNDATACOPY = > Some ( ( read ( 0 ) , read ( 2 ) ) ) ,
instructions ::EXTCODECOPY = > Some ( ( read ( 1 ) , read ( 3 ) ) ) ,
instructions ::CALL | instructions ::CALLCODE = > Some ( ( read ( 5 ) , read ( 6 ) ) ) ,
instructions ::DELEGATECALL | instructions ::STATICCALL = > Some ( ( read ( 4 ) , read ( 5 ) ) ) ,
2016-06-02 12:40:31 +02:00
_ = > None ,
2017-08-26 21:53:41 +02:00
} ;
match written {
Some ( ( offset , size ) ) if ! memory ::is_valid_range ( offset , size ) = > None ,
written = > written ,
2016-06-02 12:40:31 +02:00
}
}
fn store_written (
instruction : Instruction ,
stack : & Stack < U256 >
) -> Option < ( U256 , U256 ) > {
match instruction {
instructions ::SSTORE = > Some ( ( stack . peek ( 0 ) . clone ( ) , stack . peek ( 1 ) . clone ( ) ) ) ,
_ = > None ,
}
}
2016-03-20 19:20:37 +01:00
fn exec_instruction (
2016-06-02 19:04:15 +02:00
& mut self ,
2016-07-05 15:15:44 +02:00
gas : Cost ,
2017-08-01 12:37:57 +02:00
ext : & mut vm ::Ext ,
2016-03-20 19:20:37 +01:00
instruction : Instruction ,
2016-10-15 14:39:15 +02:00
provided : Option < Cost >
2017-08-01 12:37:57 +02:00
) -> vm ::Result < InstructionResult < Cost > > {
2016-01-13 00:13:09 +01:00
match instruction {
2016-01-13 15:21:13 +01:00
instructions ::JUMP = > {
2018-08-13 22:06:15 +02:00
let jump = self . stack . pop_back ( ) ;
2016-01-13 15:21:13 +01:00
return Ok ( InstructionResult ::JumpToPosition (
jump
) ) ;
} ,
instructions ::JUMPI = > {
2018-08-13 22:06:15 +02:00
let jump = self . stack . pop_back ( ) ;
let condition = self . stack . pop_back ( ) ;
if ! condition . is_zero ( ) {
2016-01-13 15:21:13 +01:00
return Ok ( InstructionResult ::JumpToPosition (
jump
) ) ;
}
} ,
instructions ::JUMPDEST = > {
// ignore
} ,
2017-05-05 16:00:40 +02:00
instructions ::CREATE | instructions ::CREATE2 = > {
2018-08-13 22:06:15 +02:00
let endowment = self . stack . pop_back ( ) ;
2018-08-31 17:43:51 +02:00
let init_off = self . stack . pop_back ( ) ;
let init_size = self . stack . pop_back ( ) ;
2018-08-01 13:17:04 +02:00
let address_scheme = match instruction {
instructions ::CREATE = > CreateContractAddress ::FromSenderAndNonce ,
2018-08-13 22:06:15 +02:00
instructions ::CREATE2 = > CreateContractAddress ::FromSenderSaltAndCodeHash ( self . stack . pop_back ( ) . into ( ) ) ,
2018-08-01 13:17:04 +02:00
_ = > unreachable! ( " instruction can only be CREATE/CREATE2 checked above; qed " ) ,
} ;
2017-04-19 14:30:00 +02:00
2016-10-15 14:39:15 +02:00
let create_gas = provided . expect ( " `provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed " ) ;
2016-01-13 00:13:09 +01:00
2017-10-25 11:27:18 +02:00
if ext . is_static ( ) {
return Err ( vm ::Error ::MutableCallInStaticContext ) ;
}
2016-02-15 00:51:50 +01:00
2017-09-15 21:07:54 +02:00
// clear return data buffer before creating new call frame.
self . return_data = ReturnData ::empty ( ) ;
2018-08-13 22:06:15 +02:00
let can_create = ext . balance ( & self . params . address ) ? > = endowment & & ext . depth ( ) < ext . schedule ( ) . max_depth ;
2016-01-16 20:11:12 +01:00
if ! can_create {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::zero ( ) ) ;
2016-10-15 14:39:15 +02:00
return Ok ( InstructionResult ::UnusedGas ( create_gas ) ) ;
2016-01-13 00:13:09 +01:00
}
2016-01-16 20:11:12 +01:00
2017-10-25 11:27:18 +02:00
let contract_code = self . mem . read_slice ( init_off , init_size ) ;
2018-10-02 16:33:19 +02:00
let create_result = ext . create ( & create_gas . as_u256 ( ) , & endowment , contract_code , address_scheme , true ) ;
2016-01-16 20:11:12 +01:00
return match create_result {
2018-10-02 16:33:19 +02:00
Ok ( ContractCreateResult ::Created ( address , gas_left ) ) = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( address_to_u256 ( address ) ) ;
2016-10-15 14:39:15 +02:00
Ok ( InstructionResult ::UnusedGas ( Cost ::from_u256 ( gas_left ) . expect ( " Gas left cannot be greater. " ) ) )
2016-01-16 20:11:12 +01:00
} ,
2018-10-02 16:33:19 +02:00
Ok ( ContractCreateResult ::Reverted ( gas_left , return_data ) ) = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::zero ( ) ) ;
2017-09-15 21:07:54 +02:00
self . return_data = return_data ;
Ok ( InstructionResult ::UnusedGas ( Cost ::from_u256 ( gas_left ) . expect ( " Gas left cannot be greater. " ) ) )
} ,
2018-10-02 16:33:19 +02:00
Ok ( ContractCreateResult ::Failed ) = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::zero ( ) ) ;
2016-10-15 14:39:15 +02:00
Ok ( InstructionResult ::Ok )
2017-09-15 21:07:54 +02:00
} ,
2018-10-02 16:33:19 +02:00
Err ( trap ) = > {
Ok ( InstructionResult ::Trap ( trap ) )
} ,
2016-01-16 20:11:12 +01:00
} ;
2016-01-13 00:13:09 +01:00
} ,
2017-06-19 11:41:46 +02:00
instructions ::CALL | instructions ::CALLCODE | instructions ::DELEGATECALL | instructions ::STATICCALL = > {
2016-01-20 16:52:22 +01:00
assert! ( ext . schedule ( ) . call_value_transfer_gas > ext . schedule ( ) . call_stipend , " overflow possible " ) ;
2017-06-19 11:41:46 +02:00
2018-08-13 22:06:15 +02:00
self . stack . pop_back ( ) ;
2016-10-15 14:39:15 +02:00
let call_gas = provided . expect ( " `provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is one of `CALL`/`CALLCODE`/`DELEGATECALL`; qed " ) ;
2018-08-13 22:06:15 +02:00
let code_address = self . stack . pop_back ( ) ;
2016-01-20 16:52:22 +01:00
let code_address = u256_to_address ( & code_address ) ;
2017-09-15 21:07:54 +02:00
let value = if instruction = = instructions ::DELEGATECALL {
2016-02-23 11:40:23 +01:00
None
2017-09-15 21:07:54 +02:00
} else if instruction = = instructions ::STATICCALL {
Some ( U256 ::zero ( ) )
2016-02-23 11:40:23 +01:00
} else {
2018-08-13 22:06:15 +02:00
Some ( self . stack . pop_back ( ) )
2016-01-25 23:59:50 +01:00
} ;
2016-01-14 00:39:59 +01:00
2018-08-13 22:06:15 +02:00
let in_off = self . stack . pop_back ( ) ;
let in_size = self . stack . pop_back ( ) ;
let out_off = self . stack . pop_back ( ) ;
let out_size = self . stack . pop_back ( ) ;
2016-01-14 00:39:59 +01:00
2016-01-25 23:59:50 +01:00
// Add stipend (only CALL|CALLCODE when value > 0)
2019-02-11 23:20:51 +01:00
let call_gas = call_gas . overflow_add ( value . map_or_else ( | | Cost ::from ( 0 ) , | val | match val . is_zero ( ) {
2016-07-10 20:18:23 +02:00
false = > Cost ::from ( ext . schedule ( ) . call_stipend ) ,
2016-10-15 14:39:15 +02:00
true = > Cost ::from ( 0 ) ,
2019-02-11 23:20:51 +01:00
} ) ) . 0 ;
2016-01-16 20:11:12 +01:00
2016-01-25 23:59:50 +01:00
// Get sender & receive addresses, check if we have balance
2016-07-27 17:41:21 +02:00
let ( sender_address , receive_address , has_balance , call_type ) = match instruction {
2016-01-25 23:59:50 +01:00
instructions ::CALL = > {
2017-09-15 21:07:54 +02:00
if ext . is_static ( ) & & value . map_or ( false , | v | ! v . is_zero ( ) ) {
return Err ( vm ::Error ::MutableCallInStaticContext ) ;
}
2018-08-13 22:06:15 +02:00
let has_balance = ext . balance ( & self . params . address ) ? > = value . expect ( " value set for all but delegate call; qed " ) ;
( & self . params . address , & code_address , has_balance , CallType ::Call )
2016-01-25 23:59:50 +01:00
} ,
instructions ::CALLCODE = > {
2018-08-13 22:06:15 +02:00
let has_balance = ext . balance ( & self . params . address ) ? > = value . expect ( " value set for all but delegate call; qed " ) ;
( & self . params . address , & self . params . address , has_balance , CallType ::CallCode )
2016-01-25 23:59:50 +01:00
} ,
2018-08-13 22:06:15 +02:00
instructions ::DELEGATECALL = > ( & self . params . sender , & self . params . address , true , CallType ::DelegateCall ) ,
instructions ::STATICCALL = > ( & self . params . address , & code_address , true , CallType ::StaticCall ) ,
2018-06-27 13:33:32 +02:00
_ = > panic! ( format! ( " Unexpected instruction {:?} in CALL branch. " , instruction ) )
2016-01-23 10:41:13 +01:00
} ;
2017-09-15 21:07:54 +02:00
// clear return data buffer before creating new call frame.
self . return_data = ReturnData ::empty ( ) ;
2016-01-25 23:59:50 +01:00
let can_call = has_balance & & ext . depth ( ) < ext . schedule ( ) . max_depth ;
2016-01-16 20:11:12 +01:00
if ! can_call {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::zero ( ) ) ;
2016-01-16 20:11:12 +01:00
return Ok ( InstructionResult ::UnusedGas ( call_gas ) ) ;
}
let call_result = {
2018-08-13 23:27:13 +02:00
let input = self . mem . read_slice ( in_off , in_size ) ;
2018-10-02 16:33:19 +02:00
ext . call ( & call_gas . as_u256 ( ) , sender_address , receive_address , value , input , & code_address , call_type , true )
2016-01-16 20:11:12 +01:00
} ;
2018-10-02 16:33:19 +02:00
self . resume_output_range = Some ( ( out_off , out_size ) ) ;
2018-08-13 23:27:13 +02:00
2016-01-16 20:11:12 +01:00
return match call_result {
2018-10-02 16:33:19 +02:00
Ok ( MessageCallResult ::Success ( gas_left , data ) ) = > {
let output = self . mem . writeable_slice ( out_off , out_size ) ;
2018-08-13 23:27:13 +02:00
let len = cmp ::min ( output . len ( ) , data . len ( ) ) ;
( & mut output [ .. len ] ) . copy_from_slice ( & data [ .. len ] ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::one ( ) ) ;
2017-06-06 17:47:12 +02:00
self . return_data = data ;
2017-09-15 21:07:54 +02:00
Ok ( InstructionResult ::UnusedGas ( Cost ::from_u256 ( gas_left ) . expect ( " Gas left cannot be greater than current one " ) ) )
} ,
2018-10-02 16:33:19 +02:00
Ok ( MessageCallResult ::Reverted ( gas_left , data ) ) = > {
let output = self . mem . writeable_slice ( out_off , out_size ) ;
2018-08-13 23:27:13 +02:00
let len = cmp ::min ( output . len ( ) , data . len ( ) ) ;
( & mut output [ .. len ] ) . copy_from_slice ( & data [ .. len ] ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::zero ( ) ) ;
2017-09-15 21:07:54 +02:00
self . return_data = data ;
Ok ( InstructionResult ::UnusedGas ( Cost ::from_u256 ( gas_left ) . expect ( " Gas left cannot be greater than current one " ) ) )
2016-01-16 20:11:12 +01:00
} ,
2018-10-02 16:33:19 +02:00
Ok ( MessageCallResult ::Failed ) = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::zero ( ) ) ;
2016-01-16 20:11:12 +01:00
Ok ( InstructionResult ::Ok )
2017-09-15 21:07:54 +02:00
} ,
2018-10-02 16:33:19 +02:00
Err ( trap ) = > {
Ok ( InstructionResult ::Trap ( trap ) )
} ,
2016-01-14 00:39:59 +01:00
} ;
2016-02-15 00:51:50 +01:00
} ,
2016-01-13 00:13:09 +01:00
instructions ::RETURN = > {
2018-08-13 22:06:15 +02:00
let init_off = self . stack . pop_back ( ) ;
let init_size = self . stack . pop_back ( ) ;
2016-06-02 19:04:15 +02:00
2017-05-23 15:49:17 +02:00
return Ok ( InstructionResult ::StopExecutionNeedsReturn { gas : gas , init_off : init_off , init_size : init_size , apply : true } )
} ,
instructions ::REVERT = > {
2018-08-13 22:06:15 +02:00
let init_off = self . stack . pop_back ( ) ;
let init_size = self . stack . pop_back ( ) ;
2017-05-23 15:49:17 +02:00
return Ok ( InstructionResult ::StopExecutionNeedsReturn { gas : gas , init_off : init_off , init_size : init_size , apply : false } )
2016-01-13 00:13:09 +01:00
} ,
instructions ::STOP = > {
2016-01-13 15:21:13 +01:00
return Ok ( InstructionResult ::StopExecution ) ;
2016-01-13 00:13:09 +01:00
} ,
instructions ::SUICIDE = > {
2018-08-13 22:06:15 +02:00
let address = self . stack . pop_back ( ) ;
2017-02-26 13:10:50 +01:00
ext . suicide ( & u256_to_address ( & address ) ) ? ;
2016-01-13 15:21:13 +01:00
return Ok ( InstructionResult ::StopExecution ) ;
2016-01-13 00:13:09 +01:00
} ,
2018-06-27 13:33:32 +02:00
instructions ::LOG0 | instructions ::LOG1 | instructions ::LOG2 | instructions ::LOG3 | instructions ::LOG4 = > {
let no_of_topics = instruction . log_topics ( ) . expect ( " log_topics always return some for LOG* instructions; qed " ) ;
2016-01-13 00:13:09 +01:00
2018-08-13 22:06:15 +02:00
let offset = self . stack . pop_back ( ) ;
let size = self . stack . pop_back ( ) ;
let topics = self . stack . pop_n ( no_of_topics )
2016-01-13 00:13:09 +01:00
. iter ( )
. map ( H256 ::from )
. collect ( ) ;
2017-06-19 11:41:46 +02:00
ext . log ( topics , self . mem . read_slice ( offset , size ) ) ? ;
2016-01-13 00:13:09 +01:00
} ,
2018-06-27 13:33:32 +02:00
instructions ::PUSH1 | instructions ::PUSH2 | instructions ::PUSH3 | instructions ::PUSH4 |
instructions ::PUSH5 | instructions ::PUSH6 | instructions ::PUSH7 | instructions ::PUSH8 |
instructions ::PUSH9 | instructions ::PUSH10 | instructions ::PUSH11 | instructions ::PUSH12 |
instructions ::PUSH13 | instructions ::PUSH14 | instructions ::PUSH15 | instructions ::PUSH16 |
instructions ::PUSH17 | instructions ::PUSH18 | instructions ::PUSH19 | instructions ::PUSH20 |
instructions ::PUSH21 | instructions ::PUSH22 | instructions ::PUSH23 | instructions ::PUSH24 |
instructions ::PUSH25 | instructions ::PUSH26 | instructions ::PUSH27 | instructions ::PUSH28 |
instructions ::PUSH29 | instructions ::PUSH30 | instructions ::PUSH31 | instructions ::PUSH32 = > {
let bytes = instruction . push_bytes ( ) . expect ( " push_bytes always return some for PUSH* instructions " ) ;
2018-08-13 22:06:15 +02:00
let val = self . reader . read ( bytes ) ;
self . stack . push ( val ) ;
2016-01-13 00:13:09 +01:00
} ,
instructions ::MLOAD = > {
2018-08-13 22:06:15 +02:00
let word = self . mem . read ( self . stack . pop_back ( ) ) ;
self . stack . push ( U256 ::from ( word ) ) ;
2016-01-13 00:13:09 +01:00
} ,
instructions ::MSTORE = > {
2018-08-13 22:06:15 +02:00
let offset = self . stack . pop_back ( ) ;
let word = self . stack . pop_back ( ) ;
2016-06-02 19:04:15 +02:00
Memory ::write ( & mut self . mem , offset , word ) ;
2016-01-13 00:13:09 +01:00
} ,
instructions ::MSTORE8 = > {
2018-08-13 22:06:15 +02:00
let offset = self . stack . pop_back ( ) ;
let byte = self . stack . pop_back ( ) ;
2016-06-02 19:04:15 +02:00
self . mem . write_byte ( offset , byte ) ;
2016-01-13 00:13:09 +01:00
} ,
instructions ::MSIZE = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( self . mem . size ( ) ) ) ;
2016-01-13 00:13:09 +01:00
} ,
2016-01-13 01:53:33 +01:00
instructions ::SHA3 = > {
2018-08-13 22:06:15 +02:00
let offset = self . stack . pop_back ( ) ;
let size = self . stack . pop_back ( ) ;
2017-08-30 19:18:28 +02:00
let k = keccak ( self . mem . read_slice ( offset , size ) ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( & * k ) ) ;
2016-01-13 01:53:33 +01:00
} ,
2016-01-13 00:13:09 +01:00
instructions ::SLOAD = > {
2018-08-13 22:06:15 +02:00
let key = H256 ::from ( & self . stack . pop_back ( ) ) ;
2017-02-26 13:10:50 +01:00
let word = U256 ::from ( & * ext . storage_at ( & key ) ? ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( word ) ;
2016-01-13 00:13:09 +01:00
} ,
instructions ::SSTORE = > {
2018-08-13 22:06:15 +02:00
let address = H256 ::from ( & self . stack . pop_back ( ) ) ;
let val = self . stack . pop_back ( ) ;
2016-01-16 20:11:12 +01:00
2017-02-26 13:10:50 +01:00
let current_val = U256 ::from ( & * ext . storage_at ( & address ) ? ) ;
2016-01-16 20:11:12 +01:00
// Increase refund for clear
2018-09-07 12:51:08 +02:00
if ext . schedule ( ) . eip1283 {
let original_val = U256 ::from ( & * ext . initial_storage_at ( & address ) ? ) ;
gasometer ::handle_eip1283_sstore_clears_refund ( ext , & original_val , & current_val , & val ) ;
} else {
if ! current_val . is_zero ( ) & & val . is_zero ( ) {
2018-10-15 11:09:55 +02:00
let sstore_clears_schedule = ext . schedule ( ) . sstore_refund_gas ;
2018-09-07 12:51:08 +02:00
ext . add_sstore_refund ( sstore_clears_schedule ) ;
}
2016-01-16 20:11:12 +01:00
}
2017-02-26 13:10:50 +01:00
ext . set_storage ( address , H256 ::from ( & val ) ) ? ;
2016-01-13 00:13:09 +01:00
} ,
instructions ::PC = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( self . reader . position - 1 ) ) ;
2016-01-13 00:13:09 +01:00
} ,
instructions ::GAS = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( gas . as_u256 ( ) ) ;
2016-01-13 00:13:09 +01:00
} ,
2016-01-13 01:53:33 +01:00
instructions ::ADDRESS = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( address_to_u256 ( self . params . address . clone ( ) ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::ORIGIN = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( address_to_u256 ( self . params . origin . clone ( ) ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::BALANCE = > {
2018-08-13 22:06:15 +02:00
let address = u256_to_address ( & self . stack . pop_back ( ) ) ;
2017-02-26 13:10:50 +01:00
let balance = ext . balance ( & address ) ? ;
2018-08-13 22:06:15 +02:00
self . stack . push ( balance ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::CALLER = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( address_to_u256 ( self . params . sender . clone ( ) ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::CALLVALUE = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( match self . params . value {
2016-02-14 12:54:27 +01:00
ActionValue ::Transfer ( val ) | ActionValue ::Apparent ( val ) = > val
2016-01-20 17:27:33 +01:00
} ) ;
2016-01-13 01:53:33 +01:00
} ,
2016-01-13 23:51:10 +01:00
instructions ::CALLDATALOAD = > {
2018-08-13 22:06:15 +02:00
let big_id = self . stack . pop_back ( ) ;
2016-01-15 20:19:46 +01:00
let id = big_id . low_u64 ( ) as usize ;
2016-01-15 20:14:16 +01:00
let max = id . wrapping_add ( 32 ) ;
2018-08-13 22:06:15 +02:00
if let Some ( data ) = self . params . data . as_ref ( ) {
2016-02-05 02:15:26 +01:00
let bound = cmp ::min ( data . len ( ) , max ) ;
if id < bound & & big_id < U256 ::from ( data . len ( ) ) {
let mut v = [ 0 u8 ; 32 ] ;
v [ 0 .. bound - id ] . clone_from_slice ( & data [ id .. bound ] ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( & v [ .. ] ) )
2016-02-05 02:15:26 +01:00
} else {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::zero ( ) )
2016-02-05 02:15:26 +01:00
}
2016-01-15 20:14:16 +01:00
} else {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::zero ( ) )
2016-01-15 20:14:16 +01:00
}
2016-01-13 23:51:10 +01:00
} ,
2016-01-13 01:53:33 +01:00
instructions ::CALLDATASIZE = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( self . params . data . as_ref ( ) . map_or ( 0 , | l | l . len ( ) ) ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::CODESIZE = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( self . reader . len ( ) ) ) ;
2016-01-13 01:53:33 +01:00
} ,
2017-06-06 17:47:12 +02:00
instructions ::RETURNDATASIZE = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( self . return_data . len ( ) ) )
2017-06-06 17:47:12 +02:00
} ,
2016-01-13 01:53:33 +01:00
instructions ::EXTCODESIZE = > {
2018-08-13 22:06:15 +02:00
let address = u256_to_address ( & self . stack . pop_back ( ) ) ;
2018-07-31 07:27:57 +02:00
let len = ext . extcodesize ( & address ) ? . unwrap_or ( 0 ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( len ) ) ;
2016-01-13 01:53:33 +01:00
} ,
2018-07-31 07:27:57 +02:00
instructions ::EXTCODEHASH = > {
2018-08-13 22:06:15 +02:00
let address = u256_to_address ( & self . stack . pop_back ( ) ) ;
2018-07-31 07:27:57 +02:00
let hash = ext . extcodehash ( & address ) ? . unwrap_or_else ( H256 ::zero ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( hash ) ) ;
2018-07-31 07:27:57 +02:00
} ,
2016-01-13 22:30:41 +01:00
instructions ::CALLDATACOPY = > {
2018-08-13 22:06:15 +02:00
Self ::copy_data_to_memory ( & mut self . mem , & mut self . stack , & self . params . data . as_ref ( ) . map_or_else ( | | & [ ] as & [ u8 ] , | d | & * d as & [ u8 ] ) ) ;
2017-06-06 17:47:12 +02:00
} ,
instructions ::RETURNDATACOPY = > {
2017-09-15 21:07:54 +02:00
{
2018-08-13 22:06:15 +02:00
let source_offset = self . stack . peek ( 1 ) ;
let size = self . stack . peek ( 2 ) ;
2017-09-15 21:07:54 +02:00
let return_data_len = U256 ::from ( self . return_data . len ( ) ) ;
2017-10-12 11:45:03 +02:00
if source_offset . saturating_add ( * size ) > return_data_len {
2017-09-15 21:07:54 +02:00
return Err ( vm ::Error ::OutOfBounds ) ;
}
}
2018-08-13 22:06:15 +02:00
Self ::copy_data_to_memory ( & mut self . mem , & mut self . stack , & * self . return_data ) ;
2016-01-13 22:30:41 +01:00
} ,
instructions ::CODECOPY = > {
2018-08-13 22:06:15 +02:00
Self ::copy_data_to_memory ( & mut self . mem , & mut self . stack , & self . reader . code ) ;
2016-01-13 22:30:41 +01:00
} ,
instructions ::EXTCODECOPY = > {
2018-08-13 22:06:15 +02:00
let address = u256_to_address ( & self . stack . pop_back ( ) ) ;
2017-02-26 13:10:50 +01:00
let code = ext . extcode ( & address ) ? ;
2018-07-31 07:27:57 +02:00
Self ::copy_data_to_memory (
& mut self . mem ,
2018-08-13 22:06:15 +02:00
& mut self . stack ,
2018-07-31 07:27:57 +02:00
code . as_ref ( ) . map ( | c | & ( * c ) [ .. ] ) . unwrap_or ( & [ ] )
) ;
2016-01-13 22:30:41 +01:00
} ,
2016-01-13 01:53:33 +01:00
instructions ::GASPRICE = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( self . params . gas_price . clone ( ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::BLOCKHASH = > {
2018-08-13 22:06:15 +02:00
let block_number = self . stack . pop_back ( ) ;
2016-01-13 01:53:33 +01:00
let block_hash = ext . blockhash ( & block_number ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( & * block_hash ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::COINBASE = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( address_to_u256 ( ext . env_info ( ) . author . clone ( ) ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::TIMESTAMP = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( ext . env_info ( ) . timestamp ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::NUMBER = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( ext . env_info ( ) . number ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::DIFFICULTY = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( ext . env_info ( ) . difficulty . clone ( ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::GASLIMIT = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( ext . env_info ( ) . gas_limit . clone ( ) ) ;
2016-01-13 01:53:33 +01:00
} ,
2016-01-13 22:30:41 +01:00
2018-06-27 13:33:32 +02:00
// Stack instructions
2016-01-13 01:53:33 +01:00
2018-06-27 13:33:32 +02:00
instructions ::DUP1 | instructions ::DUP2 | instructions ::DUP3 | instructions ::DUP4 |
instructions ::DUP5 | instructions ::DUP6 | instructions ::DUP7 | instructions ::DUP8 |
instructions ::DUP9 | instructions ::DUP10 | instructions ::DUP11 | instructions ::DUP12 |
instructions ::DUP13 | instructions ::DUP14 | instructions ::DUP15 | instructions ::DUP16 = > {
let position = instruction . dup_position ( ) . expect ( " dup_position always return some for DUP* instructions " ) ;
2018-08-13 22:06:15 +02:00
let val = self . stack . peek ( position ) . clone ( ) ;
self . stack . push ( val ) ;
2016-01-13 00:13:09 +01:00
} ,
2018-06-27 13:33:32 +02:00
instructions ::SWAP1 | instructions ::SWAP2 | instructions ::SWAP3 | instructions ::SWAP4 |
instructions ::SWAP5 | instructions ::SWAP6 | instructions ::SWAP7 | instructions ::SWAP8 |
instructions ::SWAP9 | instructions ::SWAP10 | instructions ::SWAP11 | instructions ::SWAP12 |
instructions ::SWAP13 | instructions ::SWAP14 | instructions ::SWAP15 | instructions ::SWAP16 = > {
let position = instruction . swap_position ( ) . expect ( " swap_position always return some for SWAP* instructions " ) ;
2018-08-13 22:06:15 +02:00
self . stack . swap_with_top ( position )
2016-01-13 00:13:09 +01:00
} ,
2016-01-13 01:53:33 +01:00
instructions ::POP = > {
2018-08-13 22:06:15 +02:00
self . stack . pop_back ( ) ;
2016-01-13 01:53:33 +01:00
} ,
2016-01-13 00:13:09 +01:00
instructions ::ADD = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
self . stack . push ( a . overflowing_add ( b ) . 0 ) ;
2016-01-13 00:13:09 +01:00
} ,
2016-01-13 01:53:33 +01:00
instructions ::MUL = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
self . stack . push ( a . overflowing_mul ( b ) . 0 ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::SUB = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
self . stack . push ( a . overflowing_sub ( b ) . 0 ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::DIV = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
self . stack . push ( if ! b . is_zero ( ) {
2016-09-27 11:27:11 +02:00
match b {
ONE = > a ,
TWO = > a > > 1 ,
TWO_POW_5 = > a > > 5 ,
TWO_POW_8 = > a > > 8 ,
TWO_POW_16 = > a > > 16 ,
TWO_POW_24 = > a > > 24 ,
TWO_POW_64 = > a > > 64 ,
TWO_POW_96 = > a > > 96 ,
TWO_POW_224 = > a > > 224 ,
TWO_POW_248 = > a > > 248 ,
2018-09-04 20:13:51 +02:00
_ = > a / b ,
2016-09-27 11:27:11 +02:00
}
2016-01-17 11:54:29 +01:00
} else {
2016-02-15 00:51:50 +01:00
U256 ::zero ( )
2016-01-13 01:53:33 +01:00
} ) ;
} ,
instructions ::MOD = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
self . stack . push ( if ! b . is_zero ( ) {
2018-09-04 20:13:51 +02:00
a % b
2016-01-17 11:54:29 +01:00
} else {
U256 ::zero ( )
2016-01-13 01:53:33 +01:00
} ) ;
} ,
2016-01-15 03:12:39 +01:00
instructions ::SDIV = > {
2018-08-13 22:06:15 +02:00
let ( a , sign_a ) = get_and_reset_sign ( self . stack . pop_back ( ) ) ;
let ( b , sign_b ) = get_and_reset_sign ( self . stack . pop_back ( ) ) ;
2016-01-15 16:04:18 +01:00
2016-01-15 19:15:37 +01:00
// -2^255
2016-01-16 21:24:19 +01:00
let min = ( U256 ::one ( ) < < 255 ) - U256 ::one ( ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( if b . is_zero ( ) {
2016-01-15 16:04:18 +01:00
U256 ::zero ( )
2016-01-15 19:15:37 +01:00
} else if a = = min & & b = = ! U256 ::zero ( ) {
min
2016-01-15 16:04:18 +01:00
} else {
2018-09-04 20:13:51 +02:00
let c = a / b ;
2016-01-15 03:12:39 +01:00
set_sign ( c , sign_a ^ sign_b )
} ) ;
} ,
instructions ::SMOD = > {
2018-08-13 22:06:15 +02:00
let ua = self . stack . pop_back ( ) ;
let ub = self . stack . pop_back ( ) ;
2016-01-15 19:15:37 +01:00
let ( a , sign_a ) = get_and_reset_sign ( ua ) ;
2016-01-17 13:24:57 +01:00
let b = get_and_reset_sign ( ub ) . 0 ;
2016-01-15 03:12:39 +01:00
2018-08-13 22:06:15 +02:00
self . stack . push ( if ! b . is_zero ( ) {
2018-09-04 20:13:51 +02:00
let c = a % b ;
2016-01-15 19:15:37 +01:00
set_sign ( c , sign_a )
2016-01-15 03:12:39 +01:00
} else {
U256 ::zero ( )
} ) ;
} ,
instructions ::EXP = > {
2018-08-13 22:06:15 +02:00
let base = self . stack . pop_back ( ) ;
let expon = self . stack . pop_back ( ) ;
2016-01-17 13:24:57 +01:00
let res = base . overflowing_pow ( expon ) . 0 ;
2018-08-13 22:06:15 +02:00
self . stack . push ( res ) ;
2016-01-15 03:12:39 +01:00
} ,
2016-01-13 01:53:33 +01:00
instructions ::NOT = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
self . stack . push ( ! a ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::LT = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
self . stack . push ( Self ::bool_to_u256 ( a < b ) ) ;
2016-01-13 01:53:33 +01:00
} ,
2016-01-15 03:12:39 +01:00
instructions ::SLT = > {
2018-08-13 22:06:15 +02:00
let ( a , neg_a ) = get_and_reset_sign ( self . stack . pop_back ( ) ) ;
let ( b , neg_b ) = get_and_reset_sign ( self . stack . pop_back ( ) ) ;
2016-01-15 03:12:39 +01:00
2016-02-15 00:51:50 +01:00
let is_positive_lt = a < b & & ! ( neg_a | neg_b ) ;
let is_negative_lt = a > b & & ( neg_a & neg_b ) ;
let has_different_signs = neg_a & & ! neg_b ;
2016-01-15 03:12:39 +01:00
2018-08-13 22:06:15 +02:00
self . stack . push ( Self ::bool_to_u256 ( is_positive_lt | is_negative_lt | has_different_signs ) ) ;
2016-01-15 03:12:39 +01:00
} ,
2016-01-13 01:53:33 +01:00
instructions ::GT = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
self . stack . push ( Self ::bool_to_u256 ( a > b ) ) ;
2016-01-13 01:53:33 +01:00
} ,
2016-01-15 03:12:39 +01:00
instructions ::SGT = > {
2018-08-13 22:06:15 +02:00
let ( a , neg_a ) = get_and_reset_sign ( self . stack . pop_back ( ) ) ;
let ( b , neg_b ) = get_and_reset_sign ( self . stack . pop_back ( ) ) ;
2016-01-15 03:12:39 +01:00
2016-02-15 00:51:50 +01:00
let is_positive_gt = a > b & & ! ( neg_a | neg_b ) ;
let is_negative_gt = a < b & & ( neg_a & neg_b ) ;
let has_different_signs = ! neg_a & & neg_b ;
2016-01-15 03:12:39 +01:00
2018-08-13 22:06:15 +02:00
self . stack . push ( Self ::bool_to_u256 ( is_positive_gt | is_negative_gt | has_different_signs ) ) ;
2016-01-15 03:12:39 +01:00
} ,
2016-01-13 01:53:33 +01:00
instructions ::EQ = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
self . stack . push ( Self ::bool_to_u256 ( a = = b ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::ISZERO = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
self . stack . push ( Self ::bool_to_u256 ( a . is_zero ( ) ) ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::AND = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
self . stack . push ( a & b ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::OR = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
self . stack . push ( a | b ) ;
2016-01-13 01:53:33 +01:00
} ,
instructions ::XOR = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
self . stack . push ( a ^ b ) ;
2016-01-13 01:53:33 +01:00
} ,
2016-01-15 03:12:39 +01:00
instructions ::BYTE = > {
2018-08-13 22:06:15 +02:00
let word = self . stack . pop_back ( ) ;
let val = self . stack . pop_back ( ) ;
2016-01-16 20:11:12 +01:00
let byte = match word < U256 ::from ( 32 ) {
true = > ( val > > ( 8 * ( 31 - word . low_u64 ( ) as usize ) ) ) & U256 ::from ( 0xff ) ,
false = > U256 ::zero ( )
2016-01-15 03:12:39 +01:00
} ;
2018-08-13 22:06:15 +02:00
self . stack . push ( byte ) ;
2016-01-15 03:12:39 +01:00
} ,
instructions ::ADDMOD = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
let c = self . stack . pop_back ( ) ;
2016-01-15 03:12:39 +01:00
2018-08-13 22:06:15 +02:00
self . stack . push ( if ! c . is_zero ( ) {
2016-01-15 16:04:18 +01:00
// upcast to 512
let a5 = U512 ::from ( a ) ;
2016-01-17 13:24:57 +01:00
let res = a5 . overflowing_add ( U512 ::from ( b ) ) . 0 ;
2018-09-04 20:13:51 +02:00
let x = res % U512 ::from ( c ) ;
2016-01-15 16:04:18 +01:00
U256 ::from ( x )
2016-01-15 03:12:39 +01:00
} else {
U256 ::zero ( )
} ) ;
} ,
instructions ::MULMOD = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
let c = self . stack . pop_back ( ) ;
2016-01-15 03:12:39 +01:00
2018-08-13 22:06:15 +02:00
self . stack . push ( if ! c . is_zero ( ) {
2016-01-15 16:04:18 +01:00
let a5 = U512 ::from ( a ) ;
2016-01-17 13:24:57 +01:00
let res = a5 . overflowing_mul ( U512 ::from ( b ) ) . 0 ;
2018-09-04 20:13:51 +02:00
let x = res % U512 ::from ( c ) ;
2016-01-15 16:04:18 +01:00
U256 ::from ( x )
2016-01-15 03:12:39 +01:00
} else {
U256 ::zero ( )
} ) ;
} ,
2016-01-15 19:15:37 +01:00
instructions ::SIGNEXTEND = > {
2018-08-13 22:06:15 +02:00
let bit = self . stack . pop_back ( ) ;
2016-01-15 19:15:37 +01:00
if bit < U256 ::from ( 32 ) {
2018-08-13 22:06:15 +02:00
let number = self . stack . pop_back ( ) ;
2016-01-15 19:15:37 +01:00
let bit_position = ( bit . low_u64 ( ) * 8 + 7 ) as usize ;
let bit = number . bit ( bit_position ) ;
let mask = ( U256 ::one ( ) < < bit_position ) - U256 ::one ( ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( if bit {
2016-01-15 19:15:37 +01:00
number | ! mask
} else {
number & mask
} ) ;
}
} ,
2018-05-05 10:23:50 +02:00
instructions ::SHL = > {
const CONST_256 : U256 = U256 ( [ 256 , 0 , 0 , 0 ] ) ;
2018-08-13 22:06:15 +02:00
let shift = self . stack . pop_back ( ) ;
let value = self . stack . pop_back ( ) ;
2018-05-05 10:23:50 +02:00
let result = if shift > = CONST_256 {
U256 ::zero ( )
} else {
value < < ( shift . as_u32 ( ) as usize )
} ;
2018-08-13 22:06:15 +02:00
self . stack . push ( result ) ;
2018-05-05 10:23:50 +02:00
} ,
instructions ::SHR = > {
const CONST_256 : U256 = U256 ( [ 256 , 0 , 0 , 0 ] ) ;
2018-08-13 22:06:15 +02:00
let shift = self . stack . pop_back ( ) ;
let value = self . stack . pop_back ( ) ;
2018-05-05 10:23:50 +02:00
let result = if shift > = CONST_256 {
U256 ::zero ( )
} else {
value > > ( shift . as_u32 ( ) as usize )
} ;
2018-08-13 22:06:15 +02:00
self . stack . push ( result ) ;
2018-05-05 10:23:50 +02:00
} ,
instructions ::SAR = > {
// We cannot use get_and_reset_sign/set_sign here, because the rounding looks different.
const CONST_256 : U256 = U256 ( [ 256 , 0 , 0 , 0 ] ) ;
const CONST_HIBIT : U256 = U256 ( [ 0 , 0 , 0 , 0x8000000000000000 ] ) ;
2018-08-13 22:06:15 +02:00
let shift = self . stack . pop_back ( ) ;
let value = self . stack . pop_back ( ) ;
2018-05-05 10:23:50 +02:00
let sign = value & CONST_HIBIT ! = U256 ::zero ( ) ;
let result = if shift > = CONST_256 {
if sign {
U256 ::max_value ( )
} else {
U256 ::zero ( )
}
} else {
let shift = shift . as_u32 ( ) as usize ;
let mut shifted = value > > shift ;
if sign {
shifted = shifted | ( U256 ::max_value ( ) < < ( 256 - shift ) ) ;
}
shifted
} ;
2018-08-13 22:06:15 +02:00
self . stack . push ( result ) ;
2018-05-05 10:23:50 +02:00
} ,
2018-06-27 13:33:32 +02:00
} ;
Ok ( InstructionResult ::Ok )
}
fn copy_data_to_memory ( mem : & mut Vec < u8 > , stack : & mut Stack < U256 > , source : & [ u8 ] ) {
let dest_offset = stack . pop_back ( ) ;
let source_offset = stack . pop_back ( ) ;
let size = stack . pop_back ( ) ;
let source_size = U256 ::from ( source . len ( ) ) ;
let output_end = match source_offset > source_size | | size > source_size | | source_offset + size > source_size {
true = > {
let zero_slice = if source_offset > source_size {
mem . writeable_slice ( dest_offset , size )
} else {
mem . writeable_slice ( dest_offset + source_size - source_offset , source_offset + size - source_size )
} ;
for i in zero_slice . iter_mut ( ) {
* i = 0 ;
}
source . len ( )
} ,
false = > ( size . low_u64 ( ) + source_offset . low_u64 ( ) ) as usize
} ;
if source_offset < source_size {
let output_begin = source_offset . low_u64 ( ) as usize ;
mem . write_slice ( dest_offset , & source [ output_begin .. output_end ] ) ;
2016-01-13 00:13:09 +01:00
}
2016-01-14 01:56:37 +01:00
}
2016-01-13 00:13:09 +01:00
2018-06-27 13:33:32 +02:00
fn verify_jump ( & self , jump_u : U256 , valid_jump_destinations : & BitSet ) -> vm ::Result < usize > {
let jump = jump_u . low_u64 ( ) as usize ;
if valid_jump_destinations . contains ( jump ) & & U256 ::from ( jump ) = = jump_u {
Ok ( jump )
} else {
Err ( vm ::Error ::BadJumpDestination {
destination : jump
} )
}
}
2018-08-13 22:06:15 +02:00
fn bool_to_u256 ( val : bool ) -> U256 {
2018-06-27 13:33:32 +02:00
if val {
U256 ::one ( )
} else {
U256 ::zero ( )
}
}
2016-01-13 01:53:33 +01:00
}
2016-01-15 03:12:39 +01:00
fn get_and_reset_sign ( value : U256 ) -> ( U256 , bool ) {
2016-07-10 20:18:23 +02:00
let U256 ( arr ) = value ;
let sign = arr [ 3 ] . leading_zeros ( ) = = 0 ;
2016-01-15 19:15:37 +01:00
( set_sign ( value , sign ) , sign )
2016-01-15 03:12:39 +01:00
}
2016-01-16 17:08:57 +01:00
fn set_sign ( value : U256 , sign : bool ) -> U256 {
2016-01-15 19:15:37 +01:00
if sign {
2016-01-17 13:47:16 +01:00
( ! U256 ::zero ( ) ^ value ) . overflowing_add ( U256 ::one ( ) ) . 0
2016-01-15 19:15:37 +01:00
} else {
value
}
2016-01-15 03:12:39 +01:00
}
2016-01-16 17:08:57 +01:00
#[ inline ]
2016-01-13 01:53:33 +01:00
fn u256_to_address ( value : & U256 ) -> Address {
Address ::from ( H256 ::from ( value ) )
}
2016-01-16 17:08:57 +01:00
#[ inline ]
2016-01-13 01:53:33 +01:00
fn address_to_u256 ( value : Address ) -> U256 {
2016-09-01 12:23:31 +02:00
U256 ::from ( & * H256 ::from ( value ) )
2016-01-13 00:13:09 +01:00
}
2017-08-28 12:32:19 +02:00
#[ cfg(test) ]
mod tests {
use std ::sync ::Arc ;
use rustc_hex ::FromHex ;
use vmtype ::VMType ;
use factory ::Factory ;
2018-10-02 16:33:19 +02:00
use vm ::{ self , Exec , ActionParams , ActionValue } ;
2017-08-28 12:32:19 +02:00
use vm ::tests ::{ FakeExt , test_finalize } ;
2018-02-19 12:27:42 +01:00
2018-10-02 16:33:19 +02:00
fn interpreter ( params : ActionParams , ext : & vm ::Ext ) -> Box < Exec > {
2018-08-13 22:06:15 +02:00
Factory ::new ( VMType ::Interpreter , 1 ) . create ( params , ext . schedule ( ) , ext . depth ( ) )
2018-02-19 12:27:42 +01:00
}
2017-08-28 12:32:19 +02:00
#[ test ]
fn should_not_fail_on_tracing_mem ( ) {
let code = " 7feeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000620f120660406000601773945304eb96065b2a98b57a48a06ae28d285a71b56101f4f1600055 " . from_hex ( ) . unwrap ( ) ;
let mut params = ActionParams ::default ( ) ;
params . address = 5. into ( ) ;
params . gas = 300_000. into ( ) ;
params . gas_price = 1. into ( ) ;
params . value = ActionValue ::Transfer ( 100_000. into ( ) ) ;
params . code = Some ( Arc ::new ( code ) ) ;
let mut ext = FakeExt ::new ( ) ;
ext . balances . insert ( 5. into ( ) , 1_000_000_000. into ( ) ) ;
ext . tracing = true ;
let gas_left = {
2018-08-13 22:06:15 +02:00
let mut vm = interpreter ( params , & ext ) ;
2018-10-02 16:33:19 +02:00
test_finalize ( vm . exec ( & mut ext ) . ok ( ) . unwrap ( ) ) . unwrap ( )
2017-08-28 12:32:19 +02:00
} ;
assert_eq! ( ext . calls . len ( ) , 1 ) ;
assert_eq! ( gas_left , 248_212. into ( ) ) ;
}
2017-10-12 11:45:03 +02:00
#[ test ]
fn should_not_overflow_returndata ( ) {
let code = " 6001600160000360003e00 " . from_hex ( ) . unwrap ( ) ;
let mut params = ActionParams ::default ( ) ;
params . address = 5. into ( ) ;
params . gas = 300_000. into ( ) ;
params . gas_price = 1. into ( ) ;
params . code = Some ( Arc ::new ( code ) ) ;
let mut ext = FakeExt ::new_byzantium ( ) ;
ext . balances . insert ( 5. into ( ) , 1_000_000_000. into ( ) ) ;
ext . tracing = true ;
let err = {
2018-08-13 22:06:15 +02:00
let mut vm = interpreter ( params , & ext ) ;
2018-10-02 16:33:19 +02:00
test_finalize ( vm . exec ( & mut ext ) . ok ( ) . unwrap ( ) ) . err ( ) . unwrap ( )
2017-10-12 11:45:03 +02:00
} ;
assert_eq! ( err , ::vm ::Error ::OutOfBounds ) ;
}
2017-08-28 12:32:19 +02:00
}