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 memory ;
2016-10-02 18:45:36 +02:00
mod shared_cache ;
2016-07-05 15:15:44 +02:00
mod stack ;
2018-08-13 22:06:15 +02:00
use bytes ::Bytes ;
2019-05-10 13:48:52 +02:00
use ethereum_types ::{ Address , H256 , U256 } ;
2017-08-30 19:18:28 +02:00
use hash ::keccak ;
2019-05-10 13:48:52 +02:00
use num_bigint ::BigUint ;
2017-07-29 17:12:07 +02:00
use std ::{ cmp , marker ::PhantomData , mem , sync ::Arc } ;
2017-08-01 12:37:57 +02:00
use vm ::{
2018-08-13 22:06:15 +02:00
self , ActionParams , ActionValue , CallType , ContractCreateResult , CreateContractAddress ,
2018-10-02 16:33:19 +02:00
GasLeft , MessageCallResult , ParamsType , ReturnData , Schedule , TrapError , TrapKind ,
2017-08-01 12:37:57 +02:00
} ;
use evm ::CostType ;
use instructions ::{ self , Instruction , InstructionInfo } ;
2016-10-02 18:45:36 +02:00
pub use self ::shared_cache ::SharedCache ;
2016-07-05 15:15:44 +02:00
use self ::{
gasometer ::Gasometer ,
memory ::Memory ,
stack ::{ Stack , VecStack } ,
2020-08-05 06:08:03 +02:00
} ;
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
2020-08-07 19:41:07 +02:00
/// Maximum subroutine stack size as specified in
/// https://eips.ethereum.org/EIPS/eip-2315.
pub const MAX_SUB_STACK_SIZE : usize = 1023 ;
2019-05-10 13:48:52 +02:00
fn to_biguint ( x : U256 ) -> BigUint {
let mut bytes = [ 0 u8 ; 32 ] ;
x . to_little_endian ( & mut bytes ) ;
BigUint ::from_bytes_le ( & bytes )
}
fn from_biguint ( x : BigUint ) -> U256 {
let bytes = x . to_bytes_le ( ) ;
U256 ::from_little_endian ( & bytes )
}
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 { code , position : 0 }
}
2020-08-05 06:08:03 +02:00
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
}
2020-08-05 06:08:03 +02: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 ) ,
2020-08-07 19:41:07 +02:00
JumpToSubroutine ( U256 ) ,
ReturnFromSubroutine ( usize ) ,
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
/// 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
}
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 > > ,
2020-08-07 19:41:07 +02:00
valid_subroutine_destinations : Option < Arc < BitSet > > ,
2018-08-13 22:06:15 +02:00
gasometer : Option < Gasometer < Cost > > ,
stack : VecStack < U256 > ,
2020-08-07 19:41:07 +02:00
return_stack : Vec < usize > ,
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 > {
2020-07-29 10:36:15 +02:00
fn exec ( mut self : Box < Self > , ext : & mut dyn 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 > {
2020-07-29 10:36:15 +02:00
fn resume_call ( mut self : Box < Self > , result : MessageCallResult ) -> Box < dyn vm ::Exec > {
2018-10-02 16:33:19 +02:00
{
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 " ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
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 ] ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
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 ] ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
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 ) ;
}
}
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
self
}
}
impl < Cost : 'static + CostType > vm ::ResumeCreate for Interpreter < Cost > {
2020-07-29 10:36:15 +02:00
fn resume_create ( mut self : Box < Self > , result : ContractCreateResult ) -> Box < dyn vm ::Exec > {
2018-10-02 16:33:19 +02:00
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 ) ;
}
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
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 ;
2020-08-07 19:41:07 +02:00
let valid_subroutine_destinations = None ;
2018-08-13 22:06:15 +02:00
let gasometer = Cost ::from_u256 ( params . gas )
. ok ( )
. map ( | gas | Gasometer ::< Cost > ::new ( gas ) ) ;
let stack = VecStack ::with_capacity ( schedule . stack_limit , U256 ::zero ( ) ) ;
2020-08-07 19:41:07 +02:00
let return_stack = Vec ::with_capacity ( MAX_SUB_STACK_SIZE ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
Interpreter {
cache ,
params ,
reader ,
informant ,
valid_jump_destinations ,
2020-08-07 19:41:07 +02:00
valid_subroutine_destinations ,
2018-08-13 22:06:15 +02:00
gasometer ,
stack ,
2020-08-07 19:41:07 +02:00
return_stack ,
2018-08-13 22:06:15 +02:00
done : false ,
2019-09-12 18:43:53 +02:00
// Overridden in `step_inner` based on
// the result of `ext.trace_next_instruction`.
2018-08-13 22:06:15 +02:00
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 ,
}
2020-08-05 06:08:03 +02:00
}
2018-08-13 22:06:15 +02:00
/// Execute a single step on the VM.
#[ inline(always) ]
2020-07-29 10:36:15 +02:00
pub fn step ( & mut self , ext : & mut dyn vm ::Ext ) -> InterpreterResult {
2018-08-13 22:06:15 +02:00
if self . done {
return InterpreterResult ::Stopped ;
}
2020-08-05 06:08:03 +02: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 {
2019-09-13 15:46:03 +02:00
let current_gas = self
. gasometer
. as_ref ( )
. expect ( " Gasometer None case is checked above; qed " )
. current_gas
. as_u256 ( ) ;
InterpreterResult ::Done ( Ok ( GasLeft ::Known ( current_gas ) ) )
2018-08-13 22:06:15 +02:00
} else {
2019-09-12 18:43:53 +02:00
self . step_inner ( ext )
2018-08-13 22:06:15 +02:00
} ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
if let & InterpreterResult ::Done ( _ ) = & result {
self . done = true ;
self . informant . done ( ) ;
}
2019-09-13 15:46:03 +02:00
result
2018-08-13 22:06:15 +02:00
}
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
/// Inner helper function for step.
#[ inline(always) ]
2019-09-12 18:43:53 +02:00
fn step_inner ( & mut self , ext : & mut dyn vm ::Ext ) -> 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 ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
// 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 ( ) ,
) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let instruction = match instruction {
Some ( i ) = > i ,
2019-09-12 18:43:53 +02:00
None = > {
return InterpreterResult ::Done ( Err ( vm ::Error ::BadInstruction {
2018-10-02 16:33:19 +02:00
instruction : opcode ,
2019-09-12 18:43:53 +02:00
} ) )
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let info = instruction . info ( ) ;
self . last_stack_ret_len = info . ret ;
2019-09-12 18:43:53 +02:00
if let Err ( e ) = self . verify_instruction ( ext , instruction , info ) {
return InterpreterResult ::Done ( Err ( e ) ) ;
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
// Calculate gas cost
2019-09-12 18:43:53 +02:00
let requirements = match self
. gasometer
. as_mut ( )
. expect ( GASOMETER_PROOF )
. requirements ( ext , instruction , info , & self . stack , self . mem . size ( ) )
{
Ok ( t ) = > t ,
Err ( e ) = > return InterpreterResult ::Done ( Err ( e ) ) ,
} ;
2018-10-02 16:33:19 +02:00
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 ) ,
) ;
}
2019-09-12 18:43:53 +02:00
if let Err ( e ) = self
. gasometer
. as_mut ( )
2018-10-02 16:33:19 +02:00
. expect ( GASOMETER_PROOF )
. verify_gas ( & requirements . gas_cost )
2020-08-05 06:08:03 +02:00
{
2018-10-02 16:33:19 +02:00
if self . do_trace {
ext . trace_failed ( ) ;
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
return InterpreterResult ::Done ( Err ( e ) ) ;
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
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 ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
evm_debug! ( {
self . informant . before_instruction (
self . reader . position ,
instruction ,
2019-09-12 18:43:53 +02:00
info ,
2018-08-13 22:06:15 +02:00
& self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas ,
& self . stack ,
2020-08-05 06:08:03 +02:00
)
} ) ;
2018-10-02 16:33:19 +02:00
// Execute instruction
2018-08-13 22:06:15 +02:00
let current_gas = self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas ;
let result = match self . exec_instruction (
2018-10-02 16:33:19 +02:00
current_gas ,
2020-08-05 06:08:03 +02:00
ext ,
2018-10-02 16:33:19 +02:00
instruction ,
2019-09-12 18:43:53 +02:00
requirements . provide_gas ,
2020-08-05 06:08:03 +02:00
) {
2019-09-12 18:43:53 +02:00
Err ( x ) = > {
2018-08-13 22:06:15 +02:00
if self . do_trace {
ext . trace_failed ( ) ;
2020-08-05 06:08:03 +02:00
}
2018-08-13 22:06:15 +02:00
return InterpreterResult ::Done ( Err ( x ) ) ;
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
Ok ( x ) = > x ,
2020-08-05 06:08:03 +02:00
} ;
2018-10-02 16:33:19 +02:00
evm_debug! ( { self . informant . after_instruction ( instruction ) } ) ;
2018-08-13 22:06:15 +02:00
result
2020-08-05 06:08:03 +02:00
}
} ;
2018-08-13 22:06:15 +02:00
if let InstructionResult ::Trap ( trap ) = result {
2019-09-12 18:43:53 +02:00
return InterpreterResult ::Trap ( trap ) ;
}
2020-08-05 06:08:03 +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 =
2019-09-12 18:43:53 +02:00
self . gasometer . as_mut ( ) . expect ( GASOMETER_PROOF ) . current_gas + * gas ;
2020-08-05 06:08:03 +02:00
}
2019-09-12 18:43:53 +02:00
if self . do_trace {
2018-08-13 22:06:15 +02:00
ext . trace_executed (
2019-09-12 18:43:53 +02:00
self . gasometer
. as_mut ( )
. expect ( GASOMETER_PROOF )
. current_gas
. as_u256 ( ) ,
self . stack . peek_top ( self . last_stack_ret_len ) ,
2018-10-02 16:33:19 +02:00
& self . mem ,
2019-09-12 18:43:53 +02:00
) ;
2020-08-05 06:08:03 +02:00
}
2018-08-13 22:06:15 +02:00
// Advance
2019-09-12 18:43:53 +02:00
match result {
InstructionResult ::JumpToPosition ( position ) = > {
if self . valid_jump_destinations . is_none ( ) {
2018-08-13 22:06:15 +02:00
self . valid_jump_destinations = Some (
self . cache
2020-08-07 19:41:07 +02:00
. jump_and_sub_destinations ( & self . params . code_hash , & self . reader . code )
. 0 ,
2020-08-05 06:08:03 +02:00
) ;
}
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 = match self . verify_jump ( position , jump_destinations ) {
2019-09-12 18:43:53 +02:00
Ok ( x ) = > x ,
Err ( e ) = > return InterpreterResult ::Done ( Err ( e ) ) ,
2016-10-02 18:45:36 +02:00
} ;
2018-08-13 22:06:15 +02:00
self . reader . position = pos ;
2020-08-05 06:08:03 +02:00
}
2020-08-07 19:41:07 +02:00
InstructionResult ::JumpToSubroutine ( position ) = > {
if self . valid_subroutine_destinations . is_none ( ) {
self . valid_subroutine_destinations = Some (
self . cache
. jump_and_sub_destinations ( & self . params . code_hash , & self . reader . code )
. 1 ,
) ;
}
let subroutine_destinations = self
. valid_subroutine_destinations
. as_ref ( )
. expect ( " subroutine_destinations are initialized on first jump; qed " ) ;
let pos = match self . verify_jump ( position , subroutine_destinations ) {
Ok ( x ) = > x ,
Err ( e ) = > return InterpreterResult ::Done ( Err ( e ) ) ,
} ;
self . return_stack . push ( self . reader . position ) ;
self . reader . position = pos + 1 ;
}
InstructionResult ::ReturnFromSubroutine ( pos ) = > {
self . reader . position = pos ;
}
2018-08-13 22:06:15 +02:00
InstructionResult ::StopExecutionNeedsReturn {
gas ,
init_off ,
init_size ,
2020-08-05 06:08:03 +02:00
apply ,
2018-08-13 22:06:15 +02:00
} = > {
2016-01-14 01:56:37 +01:00
let mem = mem ::replace ( & mut self . mem , Vec ::new ( ) ) ;
2017-07-19 14:34:59 +02:00
return InterpreterResult ::Done ( Ok ( GasLeft ::NeedsReturn {
2018-08-13 22:06:15 +02:00
gas_left : gas . as_u256 ( ) ,
2017-07-19 14:34:59 +02:00
data : mem . into_return_data ( init_off , init_size ) ,
apply_state : apply ,
2020-08-05 06:08:03 +02:00
} ) ) ;
}
2019-09-13 15:46:03 +02:00
InstructionResult ::StopExecution = > {
2017-08-01 12:37:57 +02:00
return InterpreterResult ::Done ( Ok ( GasLeft ::Known (
2018-08-13 22:06:15 +02:00
self . gasometer
. as_mut ( )
2017-08-01 12:37:57 +02:00
. expect ( GASOMETER_PROOF )
. current_gas
2016-07-05 15:15:44 +02:00
. as_u256 ( ) ,
2020-08-05 06:08:03 +02:00
) ) ) ;
2016-07-05 15:15:44 +02:00
}
2018-08-13 22:06:15 +02:00
_ = > { }
}
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
if self . reader . position > = self . reader . len ( ) {
return InterpreterResult ::Done ( Ok ( GasLeft ::Known (
2018-10-02 16:33:19 +02:00
self . gasometer
2018-08-13 22:06:15 +02:00
. as_mut ( )
2019-09-12 18:43:53 +02:00
. expect ( GASOMETER_PROOF )
2018-08-13 22:06:15 +02:00
. current_gas
. as_u256 ( ) ,
2020-08-05 06:08:03 +02:00
) ) ) ;
}
2018-08-13 22:06:15 +02:00
InterpreterResult ::Continue
2020-08-05 06:08:03 +02:00
}
2016-07-05 15:15:44 +02:00
fn verify_instruction (
& self ,
2020-07-29 10:36:15 +02:00
ext : & dyn vm ::Ext ,
2016-06-02 12:40:31 +02:00
instruction : Instruction ,
info : & InstructionInfo ,
) -> vm ::Result < ( ) > {
2017-08-26 21:53:41 +02:00
let schedule = ext . schedule ( ) ;
2020-08-05 06:08:03 +02:00
2020-08-07 19:41:07 +02:00
use instructions ::* ;
if ( instruction = = DELEGATECALL & & ! schedule . have_delegate_call )
| | ( instruction = = CREATE2 & & ! schedule . have_create2 )
| | ( instruction = = STATICCALL & & ! schedule . have_static_call )
| | ( ( instruction = = RETURNDATACOPY | | instruction = = RETURNDATASIZE )
2017-08-26 21:53:41 +02:00
& & ! schedule . have_return_data )
2020-08-07 19:41:07 +02:00
| | ( instruction = = REVERT & & ! schedule . have_revert )
| | ( ( instruction = = SHL | | instruction = = SHR | | instruction = = SAR )
2018-07-31 07:27:57 +02:00
& & ! schedule . have_bitwise_shifting )
2020-08-07 19:41:07 +02:00
| | ( instruction = = EXTCODEHASH & & ! schedule . have_extcodehash )
| | ( instruction = = CHAINID & & ! schedule . have_chain_id )
| | ( instruction = = SELFBALANCE & & ! schedule . have_selfbalance )
| | ( ( instruction = = BEGINSUB | | instruction = = JUMPSUB | | instruction = = RETURNSUB )
& & ! schedule . have_subs )
2017-08-26 21:53:41 +02:00
{
return Err ( vm ::Error ::BadInstruction {
2016-06-02 12:40:31 +02:00
instruction : instruction as u8 ,
2020-08-05 06:08:03 +02: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 ,
2016-06-02 12:40:31 +02:00
on_stack : self . stack . size ( ) ,
2020-08-05 06:08:03 +02:00
} )
2016-06-02 12:40:31 +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 ,
2020-08-05 06:08:03 +02:00
} )
} else {
Ok ( ( ) )
}
}
2020-07-29 10:36:15 +02:00
fn mem_written ( instruction : Instruction , stack : & dyn Stack < U256 > ) -> Option < ( usize , usize ) > {
2017-08-26 21:53:41 +02:00
let read = | pos | stack . peek ( pos ) . low_u64 ( ) as usize ;
2016-06-02 12:40:31 +02:00
let written = match instruction {
instructions ::MSTORE | instructions ::MLOAD = > Some ( ( read ( 0 ) , 32 ) ) ,
instructions ::MSTORE8 = > Some ( ( read ( 0 ) , 1 ) ) ,
instructions ::CALLDATACOPY | instructions ::CODECOPY | instructions ::RETURNDATACOPY = > {
2017-08-26 21:53:41 +02:00
Some ( ( read ( 0 ) , read ( 2 ) ) )
2016-06-02 12:40:31 +02:00
}
2016-03-20 19:20:37 +01:00
instructions ::EXTCODECOPY = > Some ( ( read ( 1 ) , read ( 3 ) ) ) ,
instructions ::CALL | instructions ::CALLCODE = > Some ( ( read ( 5 ) , read ( 6 ) ) ) ,
2016-01-13 15:21:13 +01:00
instructions ::DELEGATECALL | instructions ::STATICCALL = > Some ( ( read ( 4 ) , read ( 5 ) ) ) ,
_ = > None ,
2018-08-13 22:06:15 +02:00
} ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
match written {
Some ( ( offset , size ) ) if ! memory ::is_valid_range ( offset , size ) = > None ,
2017-08-26 21:53:41 +02:00
written = > written ,
2020-08-05 06:08:03 +02:00
}
}
2020-07-29 10:36:15 +02:00
fn store_written ( instruction : Instruction , stack : & dyn Stack < U256 > ) -> Option < ( U256 , U256 ) > {
2016-01-13 15:21:13 +01:00
match instruction {
instructions ::SSTORE = > Some ( ( stack . peek ( 0 ) . clone ( ) , stack . peek ( 1 ) . clone ( ) ) ) ,
2017-05-05 16:00:40 +02:00
_ = > None ,
2020-08-05 06:08:03 +02:00
}
}
2017-05-05 16:00:40 +02:00
fn exec_instruction (
2016-06-02 19:04:15 +02:00
& mut self ,
2017-05-05 16:00:40 +02:00
gas : Cost ,
2020-07-29 10:36:15 +02:00
ext : & mut dyn vm ::Ext ,
2017-05-05 16:00:40 +02:00
instruction : Instruction ,
2016-10-15 14:39:15 +02:00
provided : Option < Cost > ,
2017-05-05 16:00:40 +02:00
) -> vm ::Result < InstructionResult < Cost > > {
2018-08-31 17:43:51 +02:00
match instruction {
2016-01-13 15:21:13 +01:00
instructions ::JUMP = > {
2018-08-31 17:43:51 +02:00
let jump = self . stack . pop_back ( ) ;
return Ok ( InstructionResult ::JumpToPosition ( jump ) ) ;
2020-08-05 06:08:03 +02:00
}
2018-08-31 17:43:51 +02:00
instructions ::JUMPI = > {
2018-08-13 22:06:15 +02:00
let jump = self . stack . pop_back ( ) ;
2018-08-31 17:43:51 +02:00
let condition = self . stack . pop_back ( ) ;
2018-08-01 13:17:04 +02:00
if ! condition . is_zero ( ) {
return Ok ( InstructionResult ::JumpToPosition ( jump ) ) ;
2020-08-05 06:08:03 +02:00
}
}
2018-08-01 13:17:04 +02:00
instructions ::JUMPDEST = > {
// ignore
2020-08-05 06:08:03 +02:00
}
2020-08-07 19:41:07 +02:00
instructions ::BEGINSUB = > {
return Err ( vm ::Error ::InvalidSubEntry ) ;
}
instructions ::JUMPSUB = > {
if self . return_stack . len ( ) > = MAX_SUB_STACK_SIZE {
return Err ( vm ::Error ::OutOfSubStack {
wanted : 1 ,
limit : MAX_SUB_STACK_SIZE ,
} ) ;
}
let sub_destination = self . stack . pop_back ( ) ;
return Ok ( InstructionResult ::JumpToSubroutine ( sub_destination ) ) ;
}
instructions ::RETURNSUB = > {
if let Some ( pos ) = self . return_stack . pop ( ) {
return Ok ( InstructionResult ::ReturnFromSubroutine ( pos ) ) ;
} else {
return Err ( vm ::Error ::SubStackUnderflow {
wanted : 1 ,
on_stack : 0 ,
} ) ;
}
}
2018-08-13 22:06:15 +02:00
instructions ::CREATE | instructions ::CREATE2 = > {
let endowment = self . stack . pop_back ( ) ;
2018-08-01 13:17:04 +02:00
let init_off = self . stack . pop_back ( ) ;
2016-10-15 14:39:15 +02:00
let init_size = self . stack . pop_back ( ) ;
let address_scheme = match instruction {
instructions ::CREATE = > CreateContractAddress ::FromSenderAndNonce ,
instructions ::CREATE2 = > CreateContractAddress ::FromSenderSaltAndCodeHash (
2018-08-13 22:06:15 +02:00
self . stack . pop_back ( ) . into ( ) ,
2020-08-05 06:08:03 +02:00
) ,
2016-10-15 14:39:15 +02:00
_ = > unreachable! ( " instruction can only be CREATE/CREATE2 checked above; qed " ) ,
2016-01-13 00:13:09 +01:00
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +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 " ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
if ext . is_static ( ) {
2016-10-15 14:39:15 +02:00
return Err ( vm ::Error ::MutableCallInStaticContext ) ;
2016-01-16 20:11:12 +01:00
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
// clear return data buffer before creating new call frame.
2017-09-15 21:07:54 +02:00
self . return_data = ReturnData ::empty ( ) ;
2020-08-05 06:08:03 +02:00
2017-09-15 21:07:54 +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 {
2017-09-15 21:07:54 +02:00
self . stack . push ( U256 ::zero ( ) ) ;
return Ok ( InstructionResult ::UnusedGas ( create_gas ) ) ;
2020-08-05 06:08:03 +02:00
}
2017-09-15 21:07:54 +02:00
let contract_code = self . mem . read_slice ( init_off , init_size ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
let create_result = ext . create (
2017-09-15 21:07:54 +02:00
& create_gas . as_u256 ( ) ,
& endowment ,
2017-10-25 11:27:18 +02:00
contract_code ,
2018-08-01 13:17:04 +02:00
address_scheme ,
2020-08-05 06:08:03 +02:00
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 (
2017-09-15 21:07:54 +02:00
Cost ::from_u256 ( gas_left ) . expect ( " Gas left cannot be greater. " ) ,
2020-08-05 06:08:03 +02:00
) )
2017-09-15 21:07:54 +02:00
}
2018-10-02 16:33:19 +02:00
Ok ( ContractCreateResult ::Reverted ( gas_left , return_data ) ) = > {
self . stack . push ( U256 ::zero ( ) ) ;
2017-09-15 21:07:54 +02:00
self . return_data = return_data ;
2018-10-02 16:33:19 +02:00
Ok ( InstructionResult ::UnusedGas (
2016-10-15 14:39:15 +02:00
Cost ::from_u256 ( gas_left ) . expect ( " Gas left cannot be greater. " ) ,
2020-08-05 06:08:03 +02:00
) )
}
2016-10-15 14:39:15 +02:00
Ok ( ContractCreateResult ::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 )
2020-08-05 06:08:03 +02:00
}
2018-08-13 22:06:15 +02:00
Err ( trap ) = > Ok ( InstructionResult ::Trap ( trap ) ) ,
2016-01-20 16:52:22 +01:00
} ;
2020-08-05 06:08:03 +02:00
}
2017-09-15 21:07:54 +02:00
instructions ::CALL
| instructions ::CALLCODE
| instructions ::DELEGATECALL
| instructions ::STATICCALL = > {
2019-02-11 23:20:51 +01:00
assert! (
2016-07-10 20:18:23 +02:00
ext . schedule ( ) . call_value_transfer_gas > ext . schedule ( ) . call_stipend ,
2016-07-27 17:41:21 +02:00
" overflow possible "
2020-08-05 06:08:03 +02:00
) ;
2017-09-15 21:07:54 +02:00
self . stack . pop_back ( ) ;
2018-08-13 22:06: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 " ) ;
let code_address = self . stack . pop_back ( ) ;
let code_address = u256_to_address ( & code_address ) ;
2020-08-05 06:08:03 +02:00
2016-01-25 23:59:50 +01:00
let value = if instruction = = instructions ::DELEGATECALL {
2020-08-05 06:08:03 +02:00
None
2018-08-13 22:06:15 +02:00
} else if instruction = = instructions ::STATICCALL {
2017-09-15 21:07:54 +02:00
Some ( U256 ::zero ( ) )
2020-08-05 06:08:03 +02:00
} else {
2018-08-13 22:06:15 +02:00
Some ( self . stack . pop_back ( ) )
2020-08-05 06:08:03 +02: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 ( ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
// Add stipend (only CALL|CALLCODE when value > 0)
let call_gas = call_gas
. overflow_add ( value . map_or_else (
2019-02-11 23:20:51 +01:00
| | Cost ::from ( 0 ) ,
2018-08-13 22:06:15 +02:00
| val | match val . is_zero ( ) {
false = > Cost ::from ( ext . schedule ( ) . call_stipend ) ,
2016-10-15 14:39:15 +02:00
true = > Cost ::from ( 0 ) ,
2020-08-05 06:08:03 +02:00
} ,
) )
. 0 ;
2018-08-13 22:06:15 +02:00
// Get sender & receive addresses, check if we have balance
2018-10-02 16:33:19 +02:00
let ( sender_address , receive_address , has_balance , call_type ) = match instruction {
instructions ::CALL = > {
if ext . is_static ( ) & & value . map_or ( false , | v | ! v . is_zero ( ) ) {
2017-09-15 21:07:54 +02:00
return Err ( vm ::Error ::MutableCallInStaticContext ) ;
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
let has_balance = ext . balance ( & self . params . address ) ?
> = value . expect ( " value set for all but delegate call; qed " ) ;
2020-08-05 06:08:03 +02:00
(
2018-10-02 16:33:19 +02:00
& self . params . address ,
& code_address ,
2018-08-13 22:06:15 +02:00
has_balance ,
2018-10-02 16:33:19 +02:00
CallType ::Call ,
2020-08-05 06:08:03 +02:00
)
2016-01-16 20:11:12 +01:00
}
2017-06-19 11:41:46 +02:00
instructions ::CALLCODE = > {
2018-10-02 16:33:19 +02:00
let has_balance = ext . balance ( & self . params . address ) ?
2016-01-16 20:11:12 +01:00
> = value . expect ( " value set for all but delegate call; qed " ) ;
2020-08-05 06:08:03 +02:00
(
2016-01-16 20:11:12 +01:00
& self . params . address ,
2018-10-02 16:33:19 +02:00
& self . params . address ,
has_balance ,
2018-08-13 22:06:15 +02:00
CallType ::CallCode ,
2018-10-02 16:33:19 +02:00
)
2020-08-05 06:08:03 +02:00
}
2018-08-13 22:06:15 +02:00
instructions ::DELEGATECALL = > (
& self . params . sender ,
2018-10-02 16:33:19 +02:00
& self . params . address ,
2020-08-05 06:08:03 +02:00
true ,
2018-10-02 16:33:19 +02:00
CallType ::DelegateCall ,
2020-08-05 06:08:03 +02:00
) ,
2018-10-02 16:33:19 +02:00
instructions ::STATICCALL = > (
2017-06-06 17:47:12 +02:00
& self . params . address ,
2017-09-15 21:07:54 +02:00
& code_address ,
true ,
CallType ::StaticCall ,
2020-08-05 06:08:03 +02:00
) ,
2017-09-15 21:07:54 +02:00
_ = > panic! ( format! (
" Unexpected instruction {:?} in CALL branch. " ,
instruction
2018-10-02 16:33:19 +02:00
) ) ,
2020-08-05 06:08:03 +02:00
} ;
2018-10-02 16:33:19 +02:00
// clear return data buffer before creating new call frame.
self . return_data = ReturnData ::empty ( ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 23:27:13 +02: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 ( ) ) ;
2017-09-15 21:07:54 +02:00
return Ok ( InstructionResult ::UnusedGas ( call_gas ) ) ;
2016-01-16 20:11:12 +01:00
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let call_result = {
2018-08-13 22:06:15 +02:00
let input = self . mem . read_slice ( in_off , in_size ) ;
2017-05-23 15:49:17 +02:00
ext . call (
& call_gas . as_u256 ( ) ,
2016-07-27 17:41:21 +02:00
sender_address ,
2017-05-23 15:49:17 +02:00
receive_address ,
2020-08-05 06:08:03 +02:00
value ,
2017-05-23 15:49:17 +02:00
input ,
2018-08-13 22:06:15 +02:00
& code_address ,
2017-05-23 15:49:17 +02:00
call_type ,
true ,
2020-08-05 06:08:03 +02:00
)
} ;
2017-05-23 15:49:17 +02:00
self . resume_output_range = Some ( ( out_off , out_size ) ) ;
2020-08-05 06:08:03 +02:00
2017-05-23 15:49:17 +02:00
return match call_result {
Ok ( MessageCallResult ::Success ( gas_left , data ) ) = > {
2018-08-13 22:06:15 +02:00
let output = self . mem . writeable_slice ( out_off , out_size ) ;
let len = cmp ::min ( output . len ( ) , data . len ( ) ) ;
( & mut output [ .. len ] ) . copy_from_slice ( & data [ .. len ] ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::one ( ) ) ;
2017-05-23 15:49:17 +02:00
self . return_data = data ;
Ok ( InstructionResult ::UnusedGas (
Cost ::from_u256 ( gas_left )
2018-06-27 13:33:32 +02:00
. expect ( " Gas left cannot be greater than current one " ) ,
2020-08-05 06:08:03 +02:00
) )
}
2018-08-13 22:06:15 +02:00
Ok ( MessageCallResult ::Reverted ( gas_left , data ) ) = > {
2017-06-19 11:41:46 +02:00
let output = self . mem . writeable_slice ( out_off , out_size ) ;
let len = cmp ::min ( output . len ( ) , data . len ( ) ) ;
( & mut output [ .. len ] ) . copy_from_slice ( & data [ .. len ] ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::zero ( ) ) ;
2017-06-19 11:41:46 +02:00
self . return_data = data ;
2018-06-27 13:33:32 +02:00
Ok ( InstructionResult ::UnusedGas (
Cost ::from_u256 ( gas_left )
. expect ( " Gas left cannot be greater than current one " ) ,
2020-08-05 06:08:03 +02:00
) )
}
2018-06-27 13:33:32 +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 )
2020-08-05 06:08:03 +02:00
}
2016-01-13 00:13:09 +01:00
Err ( trap ) = > Ok ( InstructionResult ::Trap ( trap ) ) ,
2020-08-05 06:08:03 +02: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 ( ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
return Ok ( InstructionResult ::StopExecutionNeedsReturn {
2016-06-02 19:04:15 +02:00
gas : gas ,
init_off : init_off ,
2017-05-23 15:49:17 +02:00
init_size : init_size ,
2016-06-02 19:04:15 +02:00
apply : true ,
} ) ;
2016-01-13 00:13:09 +01:00
}
instructions ::REVERT = > {
2018-08-13 22:06:15 +02:00
let init_off = self . stack . pop_back ( ) ;
let init_size = self . stack . pop_back ( ) ;
2020-08-05 06:08:03 +02:00
2016-01-13 00:13:09 +01:00
return Ok ( InstructionResult ::StopExecutionNeedsReturn {
gas : gas ,
2017-05-23 15:49:17 +02:00
init_off : init_off ,
2016-01-13 00:13:09 +01:00
init_size : init_size ,
2018-08-13 22:06:15 +02:00
apply : false ,
} ) ;
2016-01-13 00:13:09 +01:00
}
2016-01-13 01:53:33 +01:00
instructions ::STOP = > {
2016-01-13 15:21:13 +01:00
return Ok ( InstructionResult ::StopExecution ) ;
2020-08-05 06:08:03 +02:00
}
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 ) ;
2020-08-05 06:08:03 +02:00
}
2018-06-27 13:33:32 +02:00
instructions ::LOG0
| instructions ::LOG1
| instructions ::LOG2
2016-01-13 01:53:33 +01:00
| instructions ::LOG3
2018-06-27 13:33:32 +02:00
| instructions ::LOG4 = > {
let no_of_topics = instruction
. log_topics ( )
. expect ( " log_topics always return some for LOG* instructions; qed " ) ;
2020-08-05 06:08:03 +02:00
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 topics = self
2018-08-13 22:06:15 +02:00
. stack
. pop_n ( no_of_topics )
2020-08-05 06:08:03 +02:00
. iter ( )
2018-08-13 22:06:15 +02:00
. map ( H256 ::from )
. collect ( ) ;
ext . log ( topics , self . mem . read_slice ( offset , size ) ) ? ;
2016-01-13 01:53:33 +01:00
}
2016-01-13 00:13:09 +01:00
instructions ::PUSH1
2018-08-13 22:06:15 +02:00
| instructions ::PUSH2
2016-01-13 00:13:09 +01:00
| instructions ::PUSH3
| instructions ::PUSH4
2018-06-27 13:33:32 +02:00
| 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
2018-08-13 22:06:15 +02:00
| instructions ::PUSH25
2018-06-27 13:33:32 +02:00
| instructions ::PUSH26
| instructions ::PUSH27
| instructions ::PUSH28
| instructions ::PUSH29
| instructions ::PUSH30
| instructions ::PUSH31
2016-01-13 00:13:09 +01:00
| instructions ::PUSH32 = > {
2018-08-13 22:06:15 +02:00
let bytes = instruction
. push_bytes ( )
2016-01-13 01:53:33 +01:00
. 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 01:53:33 +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 01:53:33 +01:00
}
instructions ::MSTORE = > {
let offset = self . stack . pop_back ( ) ;
2018-08-13 22:06:15 +02:00
let word = self . stack . pop_back ( ) ;
Memory ::write ( & mut self . mem , offset , word ) ;
2016-01-13 01:53:33 +01:00
}
2016-01-13 23:51:10 +01:00
instructions ::MSTORE8 = > {
let offset = self . stack . pop_back ( ) ;
2018-08-13 22:06:15 +02:00
let byte = self . stack . pop_back ( ) ;
self . mem . write_byte ( offset , byte ) ;
2020-08-05 06:08:03 +02:00
}
2018-08-13 22:06:15 +02:00
instructions ::MSIZE = > {
self . stack . push ( U256 ::from ( self . mem . size ( ) ) ) ;
2016-02-05 02:15:26 +01:00
}
instructions ::SHA3 = > {
let offset = self . stack . pop_back ( ) ;
2018-08-13 22:06:15 +02:00
let size = self . stack . pop_back ( ) ;
let k = keccak ( self . mem . read_slice ( offset , size ) ) ;
self . stack . push ( U256 ::from ( & * k ) ) ;
2020-08-05 06:08:03 +02:00
}
2019-09-13 15:46:03 +02:00
instructions ::SLOAD = > {
2018-08-13 22:06:15 +02:00
let key = H256 ::from ( & self . stack . pop_back ( ) ) ;
let word = U256 ::from ( & * ext . storage_at ( & key ) ? ) ;
self . stack . push ( word ) ;
2016-01-13 01:53:33 +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 ( ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02: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 ) ? ) ;
2018-08-13 22:06:15 +02:00
gasometer ::handle_eip1283_sstore_clears_refund (
2016-01-13 01:53:33 +01:00
ext ,
2018-09-07 12:51:08 +02:00
& original_val ,
& current_val ,
2020-08-05 06:08:03 +02:00
& val ,
) ;
2016-01-13 01:53:33 +01:00
} else {
2017-06-06 17:47:12 +02:00
if ! current_val . is_zero ( ) & & val . is_zero ( ) {
let sstore_clears_schedule = ext . schedule ( ) . sstore_refund_gas ;
2018-09-07 12:51:08 +02:00
ext . add_sstore_refund ( sstore_clears_schedule ) ;
2020-08-05 06:08:03 +02:00
}
}
2017-02-26 13:10:50 +01:00
ext . set_storage ( address , H256 ::from ( & val ) ) ? ;
2020-08-05 06:08:03 +02:00
}
2017-06-06 17:47:12 +02:00
instructions ::PC = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::from ( self . reader . position - 1 ) ) ;
2017-06-06 17:47:12 +02:00
}
2016-01-13 01:53:33 +01:00
instructions ::GAS = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( gas . as_u256 ( ) ) ;
2016-01-13 01:53:33 +01:00
}
2018-07-31 07:27:57 +02:00
instructions ::ADDRESS = > {
2018-08-13 22:06:15 +02:00
self . stack
. push ( address_to_u256 ( self . params . address . clone ( ) ) ) ;
2018-07-31 07:27:57 +02:00
}
2016-01-13 22:30:41 +01:00
instructions ::ORIGIN = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( address_to_u256 ( self . params . origin . clone ( ) ) ) ;
2017-06-06 17:47:12 +02: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 ) ;
2020-08-05 06:08:03 +02:00
}
2018-07-31 07:27:57 +02:00
instructions ::CALLER = > {
self . stack . push ( address_to_u256 ( self . params . sender . clone ( ) ) ) ;
2020-08-05 06:08:03 +02:00
}
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 {
2018-07-31 07:27:57 +02:00
ActionValue ::Transfer ( val ) | ActionValue ::Apparent ( val ) = > val ,
} ) ;
2016-01-13 22:30:41 +01:00
}
2016-01-13 01:53:33 +01:00
instructions ::CALLDATALOAD = > {
2018-08-13 22:06:15 +02:00
let big_id = self . stack . pop_back ( ) ;
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 ( ) {
let bound = cmp ::min ( data . len ( ) , max ) ;
2016-01-13 01:53:33 +01:00
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-01-13 01:53:33 +01:00
} else {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::zero ( ) )
2016-01-13 01:53:33 +01:00
}
} else {
2018-08-13 22:06:15 +02:00
self . stack . push ( U256 ::zero ( ) )
2020-08-05 06:08:03 +02:00
}
}
2018-08-13 22:06:15 +02:00
instructions ::CALLDATASIZE = > {
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
}
2018-08-13 22:06:15 +02:00
instructions ::RETURNDATASIZE = > self . stack . push ( U256 ::from ( self . return_data . len ( ) ) ) ,
2016-01-13 22:30:41 +01:00
instructions ::EXTCODESIZE = > {
2018-08-13 22:06:15 +02:00
let address = u256_to_address ( & self . stack . pop_back ( ) ) ;
let len = ext . extcodesize ( & address ) ? . unwrap_or ( 0 ) ;
self . stack . push ( U256 ::from ( len ) ) ;
2016-01-13 01:53:33 +01:00
}
2019-09-12 18:43:53 +02:00
instructions ::EXTCODEHASH = > {
let address = u256_to_address ( & self . stack . pop_back ( ) ) ;
2019-09-13 15:46:03 +02:00
let hash = ext . extcodehash ( & address ) ? . unwrap_or_else ( H256 ::zero ) ;
self . stack . push ( U256 ::from ( hash ) ) ;
2020-08-05 06:08:03 +02:00
}
2019-09-13 15:46:03 +02:00
instructions ::CALLDATACOPY = > {
2018-08-13 22:06:15 +02:00
Self ::copy_data_to_memory (
2018-07-31 07:27:57 +02:00
& mut self . mem ,
2019-09-13 15:46:03 +02:00
& mut self . stack ,
& self
. params
2020-08-05 06:08:03 +02:00
. data
2019-09-13 15:46:03 +02:00
. as_ref ( )
2018-08-13 22:06:15 +02:00
. map_or_else ( | | & [ ] as & [ u8 ] , | d | & * d as & [ u8 ] ) ,
2020-08-05 06:08:03 +02:00
) ;
2019-09-13 15:46:03 +02:00
}
2018-06-27 13:33:32 +02:00
instructions ::RETURNDATACOPY = > {
2020-08-05 06:08:03 +02:00
{
2018-06-27 13:33:32 +02:00
let source_offset = self . stack . peek ( 1 ) ;
2018-08-13 22:06:15 +02:00
let size = self . stack . peek ( 2 ) ;
let return_data_len = U256 ::from ( self . return_data . len ( ) ) ;
if source_offset . saturating_add ( * size ) > return_data_len {
return Err ( vm ::Error ::OutOfBounds ) ;
2020-08-05 06:08:03 +02:00
}
}
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 00:13:09 +01:00
}
2018-06-27 13:33:32 +02: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 00:13:09 +01:00
}
2016-01-13 01:53:33 +01:00
instructions ::EXTCODECOPY = > {
2018-08-13 22:06:15 +02:00
let address = u256_to_address ( & self . stack . pop_back ( ) ) ;
2016-01-13 00:13:09 +01:00
let code = ext . extcode ( & address ) ? ;
2018-08-13 22:06:15 +02:00
Self ::copy_data_to_memory (
2018-07-31 07:27:57 +02:00
& 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 ( & [ ] ) ,
2020-08-05 06:08:03 +02:00
) ;
}
2016-01-13 00:13:09 +01:00
instructions ::GASPRICE = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( self . params . gas_price . clone ( ) ) ;
2020-08-05 06:08:03 +02:00
}
2018-08-13 22:06:15 +02:00
instructions ::BLOCKHASH = > {
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 ) ) ;
2020-08-05 06:08:03 +02:00
}
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 ( ) ) ) ;
2020-08-05 06:08:03 +02:00
}
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 ) ) ;
2020-08-05 06:08:03 +02:00
}
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 00:13:09 +01:00
}
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 ( ) ) ;
2020-08-05 06:08:03 +02:00
}
2016-01-13 01:53:33 +01:00
instructions ::CHAINID = > self . stack . push ( ext . chain_id ( ) . into ( ) ) ,
instructions ::SELFBALANCE = > {
2018-08-13 22:06:15 +02:00
self . stack . push ( ext . balance ( & self . params . address ) ? ) ;
2016-01-13 01:53:33 +01:00
}
2020-08-05 06:08:03 +02:00
2018-06-27 13:33:32 +02:00
// Stack instructions
instructions ::DUP1
| instructions ::DUP2
| instructions ::DUP3
| instructions ::DUP4
2016-01-13 01:53:33 +01:00
| instructions ::DUP5
2018-08-13 22:06:15 +02:00
| instructions ::DUP6
2018-06-27 13:33:32 +02:00
| instructions ::DUP7
| instructions ::DUP8
2018-08-13 22:06:15 +02:00
| instructions ::DUP9
| instructions ::DUP10
2016-09-27 11:27:11 +02:00
| instructions ::DUP11
2018-06-27 13:33:32 +02:00
| instructions ::DUP12
| instructions ::DUP13
2016-09-27 11:27:11 +02:00
| instructions ::DUP14
2016-02-15 00:51:50 +01:00
| instructions ::DUP15
2016-01-13 01:53:33 +01:00
| instructions ::DUP16 = > {
2018-06-27 13:33:32 +02:00
let position = instruction
. dup_position ( )
2018-08-13 22:06:15 +02:00
. expect ( " dup_position always return some for DUP* instructions " ) ;
let val = self . stack . peek ( position ) . clone ( ) ;
self . stack . push ( val ) ;
2016-01-17 11:54:29 +01:00
}
2018-06-27 13:33:32 +02:00
instructions ::SWAP1
| instructions ::SWAP2
| instructions ::SWAP3
| instructions ::SWAP4
| instructions ::SWAP5
2016-01-17 11:54:29 +01:00
| instructions ::SWAP6
2018-06-27 13:33:32 +02:00
| instructions ::SWAP7
| instructions ::SWAP8
| instructions ::SWAP9
| instructions ::SWAP10
| instructions ::SWAP11
| instructions ::SWAP12
| instructions ::SWAP13
| instructions ::SWAP14
| instructions ::SWAP15
2016-01-15 03:12:39 +01:00
| instructions ::SWAP16 = > {
2018-08-13 22:06:15 +02:00
let position = instruction
. swap_position ( )
. expect ( " swap_position always return some for SWAP* instructions " ) ;
self . stack . swap_with_top ( position )
2020-08-05 06:08:03 +02:00
}
2018-08-13 22:06:15 +02:00
instructions ::POP = > {
self . stack . pop_back ( ) ;
2020-08-05 06:08:03 +02:00
}
2016-01-16 21:24:19 +01:00
instructions ::ADD = > {
let a = self . stack . pop_back ( ) ;
2018-08-13 22:06:15 +02:00
let b = self . stack . pop_back ( ) ;
self . stack . push ( a . overflowing_add ( b ) . 0 ) ;
2016-01-15 19:15:37 +01:00
}
instructions ::MUL = > {
2018-09-04 20:13:51 +02:00
let a = self . stack . pop_back ( ) ;
2016-01-15 03:12:39 +01:00
let b = self . stack . pop_back ( ) ;
self . stack . push ( a . overflowing_mul ( b ) . 0 ) ;
}
instructions ::SUB = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
let b = self . stack . pop_back ( ) ;
2016-01-15 19:15:37 +01:00
self . stack . push ( a . overflowing_sub ( b ) . 0 ) ;
2020-08-05 06:08:03 +02:00
}
2016-01-13 01:53:33 +01:00
instructions ::DIV = > {
2016-01-15 19:15:37 +01:00
let a = self . stack . pop_back ( ) ;
2016-01-17 13:24:57 +01:00
let b = self . stack . pop_back ( ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( if ! b . is_zero ( ) {
2016-01-15 03:12:39 +01:00
match b {
ONE = > a ,
2018-08-13 22:06:15 +02:00
TWO = > a > > 1 ,
TWO_POW_5 = > a > > 5 ,
2016-01-17 13:24:57 +01:00
TWO_POW_8 = > a > > 8 ,
TWO_POW_16 = > a > > 16 ,
2016-09-27 11:27:11 +02:00
TWO_POW_24 = > a > > 24 ,
2016-01-15 03:12:39 +01:00
TWO_POW_64 = > a > > 64 ,
2016-01-13 01:53:33 +01:00
TWO_POW_96 = > a > > 96 ,
2018-08-13 22:06:15 +02:00
TWO_POW_224 = > a > > 224 ,
2016-01-13 01:53:33 +01:00
TWO_POW_248 = > a > > 248 ,
2018-09-04 20:13:51 +02:00
_ = > a / b ,
2016-01-13 01:53:33 +01:00
}
2020-08-05 06:08:03 +02:00
} else {
2018-05-05 10:23:50 +02:00
U256 ::zero ( )
2020-08-05 06:08:03 +02:00
} ) ;
}
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 ( ) { a % b } 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 ( ) ) ;
2020-08-05 06:08:03 +02:00
2016-01-15 19:15:37 +01:00
// -2^255
2016-02-15 00:51:50 +01:00
let min = ( U256 ::one ( ) < < 255 ) - U256 ::one ( ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( if b . is_zero ( ) {
2018-05-05 10:23:50 +02:00
U256 ::zero ( )
2018-08-13 22:06:15 +02:00
} else if a = = min & & b = = ! U256 ::zero ( ) {
2020-08-05 06:08:03 +02:00
min
} else {
2018-08-13 22:06:15 +02:00
let c = a / b ;
set_sign ( c , sign_a ^ sign_b )
} ) ;
2016-01-15 03:12:39 +01:00
}
2016-01-13 01:53:33 +01:00
instructions ::SMOD = > {
2018-08-13 22:06:15 +02:00
let ua = self . stack . pop_back ( ) ;
let ub = self . stack . pop_back ( ) ;
let ( a , sign_a ) = get_and_reset_sign ( ua ) ;
let b = get_and_reset_sign ( ub ) . 0 ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
self . stack . push ( if ! b . is_zero ( ) {
let c = a % b ;
set_sign ( c , sign_a )
} else {
U256 ::zero ( )
} ) ;
2016-01-15 03:12:39 +01:00
}
2016-01-13 01:53:33 +01:00
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 ) ;
2020-08-05 06:08:03 +02:00
}
2016-01-15 03:12:39 +01:00
instructions ::NOT = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
self . stack . push ( ! a ) ;
2020-08-05 06:08:03 +02:00
}
2016-01-15 03:12:39 +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
}
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 ( ) ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
let is_positive_lt = a < b & & ! ( neg_a | neg_b ) ;
let is_negative_lt = a > b & & ( neg_a & neg_b ) ;
2016-02-15 00:51:50 +01:00
let has_different_signs = neg_a & & ! neg_b ;
2020-08-05 06:08:03 +02: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 ,
2020-08-05 06:08:03 +02: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 ( ) ) ;
2020-08-05 06:08:03 +02: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 ;
2020-08-05 06:08:03 +02: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 ,
2020-08-05 06:08:03 +02:00
) ) ;
}
2016-01-13 22:30:41 +01:00
instructions ::EQ = > {
2018-08-13 22:06:15 +02:00
let a = self . stack . pop_back ( ) ;
2016-01-16 20:11:12 +01:00
let b = self . stack . pop_back ( ) ;
self . stack . push ( Self ::bool_to_u256 ( a = = b ) ) ;
2016-01-15 03:12:39 +01:00
}
2016-01-13 01:53:33 +01:00
instructions ::ISZERO = > {
2016-01-15 03:12:39 +01:00
let a = self . stack . pop_back ( ) ;
2018-08-13 22:06:15 +02:00
self . stack . push ( Self ::bool_to_u256 ( a . is_zero ( ) ) ) ;
2016-01-15 03:12:39 +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-15 03:12:39 +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 ) ;
2020-08-05 06:08:03 +02:00
}
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-15 03:12:39 +01:00
}
2016-01-15 19:15:37 +01:00
instructions ::BYTE = > {
let word = self . stack . pop_back ( ) ;
2018-08-13 22:06:15 +02:00
let val = self . stack . pop_back ( ) ;
2016-01-15 19:15:37 +01:00
let byte = match word < U256 ::from ( 32 ) {
2016-01-16 20:11:12 +01:00
true = > ( val > > ( 8 * ( 31 - word . low_u64 ( ) as usize ) ) ) & U256 ::from ( 0xff ) ,
false = > U256 ::zero ( ) ,
2020-08-05 06:08:03 +02:00
} ;
2018-08-13 22:06:15 +02:00
self . stack . push ( byte ) ;
2020-08-05 06:08:03 +02:00
}
2016-01-15 19:15:37 +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 ( ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
self . stack . push ( if ! c . is_zero ( ) {
2019-05-10 13:48:52 +02:00
let a_num = to_biguint ( a ) ;
2018-08-13 22:06:15 +02:00
let b_num = to_biguint ( b ) ;
2019-05-10 13:48:52 +02:00
let c_num = to_biguint ( c ) ;
let res = a_num + b_num ;
2016-01-15 19:15:37 +01:00
let x = res % c_num ;
2019-05-10 13:48:52 +02:00
from_biguint ( x )
2016-01-15 19:15:37 +01:00
} else {
U256 ::zero ( )
} ) ;
}
2018-05-05 10:23:50 +02:00
instructions ::MULMOD = > {
let a = self . stack . pop_back ( ) ;
2018-08-13 22:06:15 +02:00
let b = self . stack . pop_back ( ) ;
2018-05-05 10:23:50 +02:00
let c = self . stack . pop_back ( ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
self . stack . push ( if ! c . is_zero ( ) {
2019-05-10 13:48:52 +02:00
let a_num = to_biguint ( a ) ;
let b_num = to_biguint ( b ) ;
2018-05-05 10:23:50 +02:00
let c_num = to_biguint ( c ) ;
2019-05-10 13:48:52 +02:00
let res = a_num * b_num ;
let x = res % c_num ;
from_biguint ( x )
2020-08-05 06:08:03 +02:00
} else {
2018-05-05 10:23:50 +02:00
U256 ::zero ( )
2020-08-05 06:08:03 +02:00
} ) ;
}
2018-05-05 10:23:50 +02:00
instructions ::SIGNEXTEND = > {
2018-08-13 22:06:15 +02:00
let bit = self . stack . pop_back ( ) ;
if bit < U256 ::from ( 32 ) {
let number = self . stack . pop_back ( ) ;
2018-05-05 10:23:50 +02:00
let bit_position = ( bit . low_u64 ( ) * 8 + 7 ) as usize ;
2020-08-05 06:08:03 +02:00
2016-01-15 19:15:37 +01:00
let bit = number . bit ( bit_position ) ;
2018-05-05 10:23:50 +02:00
let mask = ( U256 ::one ( ) < < bit_position ) - U256 ::one ( ) ;
2018-08-13 22:06:15 +02:00
self . stack
. push ( if bit { number | ! mask } else { number & mask } ) ;
2018-05-05 10:23:50 +02:00
}
2020-08-05 06:08:03 +02:00
}
2018-05-05 10:23:50 +02:00
instructions ::SHL = > {
const CONST_256 : U256 = U256 ( [ 256 , 0 , 0 , 0 ] ) ;
2020-08-05 06:08:03 +02:00
2018-08-13 22:06:15 +02:00
let shift = self . stack . pop_back ( ) ;
let value = self . stack . pop_back ( ) ;
2020-08-05 06:08:03 +02:00
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 ] ) ;
2020-08-05 06:08:03 +02:00
2018-05-05 10:23:50 +02:00
let shift = self . stack . pop_back ( ) ;
2018-08-13 22:06:15 +02:00
let value = self . stack . pop_back ( ) ;
2020-08-05 06:08:03 +02:00
2018-05-05 10:23:50 +02:00
let result = if shift > = CONST_256 {
U256 ::zero ( )
2020-08-05 06:08:03 +02:00
} else {
2016-01-16 20:11:12 +01:00
value > > ( shift . as_u32 ( ) as usize )
2020-08-05 06:08:03 +02:00
} ;
2018-08-13 22:06:15 +02:00
self . stack . push ( result ) ;
2020-08-05 06:08:03 +02:00
}
2016-01-13 01:53:33 +01:00
instructions ::SAR = > {
2018-05-05 10:23:50 +02:00
// We cannot use get_and_reset_sign/set_sign here, because the rounding looks different.
2020-08-05 06:08:03 +02:00
2018-05-05 10:23:50 +02:00
const CONST_256 : U256 = U256 ( [ 256 , 0 , 0 , 0 ] ) ;
2018-08-13 22:06:15 +02:00
const CONST_HIBIT : U256 = U256 ( [ 0 , 0 , 0 , 0x8000000000000000 ] ) ;
2020-08-05 06:08:03 +02:00
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 ( ) ;
2020-08-05 06:08:03 +02:00
2018-05-05 10:23:50 +02:00
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 )
}
2020-08-05 06:08:03 +02:00
2020-07-29 10:36:15 +02:00
fn copy_data_to_memory ( mem : & mut Vec < u8 > , stack : & mut dyn Stack < U256 > , source : & [ u8 ] ) {
2018-06-27 13:33:32 +02:00
let dest_offset = stack . pop_back ( ) ;
let source_offset = stack . pop_back ( ) ;
let size = stack . pop_back ( ) ;
let source_size = U256 ::from ( source . len ( ) ) ;
2020-08-05 06:08:03 +02:00
2018-06-27 13:33:32 +02:00
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 ,
} ;
2020-08-05 06:08:03 +02:00
2018-06-27 13:33:32 +02:00
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-14 01:56:37 +01:00
}
2020-08-05 06:08:03 +02: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 ;
2020-08-05 06:08:03 +02:00
2018-06-27 13:33:32 +02:00
if valid_jump_destinations . contains ( jump ) & & U256 ::from ( jump ) = = jump_u {
Ok ( jump )
} else {
2020-08-07 19:41:07 +02:00
// Note: if jump > usize, BadJumpDestination value is trimmed
2018-06-27 13:33:32 +02:00
Err ( vm ::Error ::BadJumpDestination { destination : jump } )
}
2020-08-05 06:08:03 +02:00
}
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 factory ::Factory ;
use rustc_hex ::FromHex ;
use std ::sync ::Arc ;
2018-10-02 16:33:19 +02:00
use vm ::{
self ,
2017-08-28 12:32:19 +02:00
tests ::{ test_finalize , FakeExt } ,
2018-10-02 16:33:19 +02:00
ActionParams , ActionValue , Exec ,
} ;
2017-08-28 12:32:19 +02:00
use vmtype ::VMType ;
2020-08-05 06:08:03 +02:00
2020-07-29 10:36:15 +02:00
fn interpreter ( params : ActionParams , ext : & dyn vm ::Ext ) -> Box < dyn 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
}
2020-08-05 06:08:03 +02:00
2017-08-28 12:32:19 +02:00
#[ test ]
fn should_not_fail_on_tracing_mem ( ) {
let code = " 7feeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff006000527faaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffaa6020526000620f120660406000601773945304eb96065b2a98b57a48a06ae28d285a71b56101f4f1600055 " . from_hex ( ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2017-08-28 12:32:19 +02:00
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 ;
2020-08-05 06:08:03 +02:00
2017-08-28 12:32:19 +02:00
let gas_left = {
2020-07-29 11:00:04 +02:00
let 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
} ;
2020-08-05 06:08:03 +02:00
2017-08-28 12:32:19 +02:00
assert_eq! ( ext . calls . len ( ) , 1 ) ;
assert_eq! ( gas_left , 248_212. into ( ) ) ;
}
2020-08-05 06:08:03 +02:00
2017-10-12 11:45:03 +02:00
#[ test ]
fn should_not_overflow_returndata ( ) {
let code = " 6001600160000360003e00 " . from_hex ( ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2017-10-12 11:45:03 +02:00
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 ;
2020-08-05 06:08:03 +02:00
2017-10-12 11:45:03 +02:00
let err = {
2020-07-29 11:00:04 +02:00
let 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
} ;
2020-08-05 06:08:03 +02:00
2017-10-12 11:45:03 +02:00
assert_eq! ( err , ::vm ::Error ::OutOfBounds ) ;
}
2017-08-28 12:32:19 +02:00
}