2016-02-05 13:40:41 +01:00
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
2016-01-11 02:42:02 +01:00
//! Transaction Execution environment.
2016-01-11 16:33:08 +01:00
use common ::* ;
2016-01-07 19:05:44 +01:00
use state ::* ;
use engine ::* ;
2016-06-02 19:04:15 +02:00
use evm ::{ self , Ext , Factory , Finalize } ;
2016-01-15 14:22:46 +01:00
use externalities ::* ;
use substate ::* ;
2016-06-02 12:40:31 +02:00
use trace ::{ Trace , Tracer , NoopTracer , ExecutiveTracer , VMTrace , VMTracer , ExecutiveVMTracer , NoopVMTracer } ;
2016-01-26 10:15:55 +01:00
use crossbeam ;
2016-05-16 18:33:32 +02:00
pub use types ::executed ::{ Executed , ExecutionResult } ;
2016-01-26 10:15:55 +01:00
/// Max depth to avoid stack overflow (when it's reached we start a new thread with VM)
/// TODO [todr] We probably need some more sophisticated calculations here (limit on my machine 132)
2016-05-02 13:13:12 +02:00
/// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp`
2016-01-29 14:43:18 +01:00
const MAX_VM_DEPTH_FOR_THREAD : usize = 64 ;
2016-01-07 23:33:54 +01:00
2016-01-09 00:51:09 +01:00
/// Returns new address created from address and given nonce.
2016-01-08 00:16:15 +01:00
pub fn contract_address ( address : & Address , nonce : & U256 ) -> Address {
2016-01-07 23:33:54 +01:00
let mut stream = RlpStream ::new_list ( 2 ) ;
stream . append ( address ) ;
stream . append ( nonce ) ;
From ::from ( stream . out ( ) . sha3 ( ) )
}
2016-01-07 19:05:44 +01:00
2016-04-06 13:05:58 +02:00
/// Transaction execution options.
pub struct TransactOptions {
/// Enable call tracing.
pub tracing : bool ,
2016-06-02 12:40:31 +02:00
/// Enable VM tracing.
pub vm_tracing : bool ,
2016-04-06 13:05:58 +02:00
/// Check transaction nonce before execution.
pub check_nonce : bool ,
}
2016-01-11 19:25:37 +01:00
/// Transaction executor.
2016-01-07 19:05:44 +01:00
pub struct Executive < ' a > {
state : & ' a mut State ,
info : & ' a EnvInfo ,
engine : & ' a Engine ,
2016-05-19 00:44:49 +02:00
vm_factory : & ' a Factory ,
2016-03-18 23:49:12 +01:00
depth : usize ,
2016-01-07 19:05:44 +01:00
}
impl < ' a > Executive < ' a > {
2016-01-11 19:25:37 +01:00
/// Basic constructor.
2016-05-19 00:44:49 +02:00
pub fn new ( state : & ' a mut State , info : & ' a EnvInfo , engine : & ' a Engine , vm_factory : & ' a Factory ) -> Self {
2016-03-19 12:54:34 +01:00
Executive {
state : state ,
info : info ,
engine : engine ,
2016-05-19 00:44:49 +02:00
vm_factory : vm_factory ,
2016-03-19 12:54:34 +01:00
depth : 0 ,
}
2016-01-09 17:55:47 +01:00
}
2016-01-09 00:51:09 +01:00
2016-01-11 14:08:03 +01:00
/// Populates executive from parent properties. Increments executive depth.
2016-05-19 00:44:49 +02:00
pub fn from_parent ( state : & ' a mut State , info : & ' a EnvInfo , engine : & ' a Engine , vm_factory : & ' a Factory , parent_depth : usize ) -> Self {
2016-01-07 19:05:44 +01:00
Executive {
state : state ,
info : info ,
engine : engine ,
2016-05-19 00:44:49 +02:00
vm_factory : vm_factory ,
2016-03-19 12:54:34 +01:00
depth : parent_depth + 1 ,
2016-01-07 19:05:44 +01:00
}
}
2016-01-15 14:22:46 +01:00
/// Creates `Externalities` from `Executive`.
2016-06-03 11:36:30 +02:00
pub fn as_externalities < ' any , T , V > (
& ' any mut self ,
2016-06-02 12:40:31 +02:00
origin_info : OriginInfo ,
2016-06-03 11:36:30 +02:00
substate : & ' any mut Substate ,
output : OutputPolicy < ' any , ' any > ,
tracer : & ' any mut T ,
vm_tracer : & ' any mut V
) -> Externalities < ' any , T , V > where T : Tracer , V : VMTracer {
2016-06-02 12:40:31 +02:00
Externalities ::new ( self . state , self . info , self . engine , self . vm_factory , self . depth , origin_info , substate , output , tracer , vm_tracer )
2016-01-15 14:22:46 +01:00
}
2016-04-28 21:47:44 +02:00
/// This function should be used to execute transaction.
2016-05-14 14:28:44 +02:00
pub fn transact ( & ' a mut self , t : & SignedTransaction , options : TransactOptions ) -> Result < Executed , ExecutionError > {
2016-04-08 01:50:55 +02:00
let check = options . check_nonce ;
match options . tracing {
2016-06-02 12:40:31 +02:00
true = > match options . vm_tracing {
true = > self . transact_with_tracer ( t , check , ExecutiveTracer ::default ( ) , ExecutiveVMTracer ::default ( ) ) ,
false = > self . transact_with_tracer ( t , check , ExecutiveTracer ::default ( ) , NoopVMTracer ) ,
} ,
false = > match options . vm_tracing {
true = > self . transact_with_tracer ( t , check , NoopTracer , ExecutiveVMTracer ::default ( ) ) ,
false = > self . transact_with_tracer ( t , check , NoopTracer , NoopVMTracer ) ,
} ,
2016-04-08 01:50:55 +02:00
}
}
2016-04-28 21:47:44 +02:00
/// Execute transaction/call with tracing enabled
2016-06-02 12:40:31 +02:00
pub fn transact_with_tracer < T , V > (
& ' a mut self ,
t : & SignedTransaction ,
check_nonce : bool ,
mut tracer : T ,
mut vm_tracer : V
) -> Result < Executed , ExecutionError > where T : Tracer , V : VMTracer {
2016-05-14 14:28:44 +02:00
let sender = try ! ( t . sender ( ) . map_err ( | e | {
let message = format! ( " Transaction malformed: {:?} " , e ) ;
ExecutionError ::TransactionMalformed ( message )
} ) ) ;
2016-01-11 02:42:02 +01:00
let nonce = self . state . nonce ( & sender ) ;
2016-01-10 12:29:35 +01:00
2016-01-15 13:07:44 +01:00
let schedule = self . engine . schedule ( self . info ) ;
let base_gas_required = U256 ::from ( t . gas_required ( & schedule ) ) ;
if t . gas < base_gas_required {
return Err ( From ::from ( ExecutionError ::NotEnoughBaseGas { required : base_gas_required , got : t . gas } ) ) ;
}
let init_gas = t . gas - base_gas_required ;
2016-01-14 02:20:46 +01:00
2016-01-10 12:29:35 +01:00
// validate transaction nonce
2016-04-12 13:54:34 +02:00
if check_nonce & & t . nonce ! = nonce {
return Err ( From ::from ( ExecutionError ::InvalidNonce { expected : nonce , got : t . nonce } ) ) ;
2016-01-10 12:29:35 +01:00
}
2016-02-09 16:31:57 +01:00
2016-01-11 02:17:29 +01:00
// validate if transaction fits into given block
2016-01-11 02:42:02 +01:00
if self . info . gas_used + t . gas > self . info . gas_limit {
2016-02-09 16:31:57 +01:00
return Err ( From ::from ( ExecutionError ::BlockGasLimitReached {
gas_limit : self . info . gas_limit ,
gas_used : self . info . gas_used ,
gas : t . gas
2016-01-11 20:47:19 +01:00
} ) ) ;
2016-01-11 02:17:29 +01:00
}
2016-01-10 12:29:35 +01:00
// TODO: we might need bigints here, or at least check overflows.
2016-01-11 02:42:02 +01:00
let balance = self . state . balance ( & sender ) ;
2016-01-12 17:40:34 +01:00
let gas_cost = U512 ::from ( t . gas ) * U512 ::from ( t . gas_price ) ;
let total_cost = U512 ::from ( t . value ) + gas_cost ;
2016-01-10 12:29:35 +01:00
// avoid unaffordable transactions
2016-01-12 17:40:34 +01:00
if U512 ::from ( balance ) < total_cost {
2016-01-15 13:07:44 +01:00
return Err ( From ::from ( ExecutionError ::NotEnoughCash { required : total_cost , got : U512 ::from ( balance ) } ) ) ;
2016-01-10 12:29:35 +01:00
}
2016-01-07 21:29:36 +01:00
2016-01-11 02:17:29 +01:00
// NOTE: there can be no invalid transactions from this point.
2016-01-11 02:42:02 +01:00
self . state . inc_nonce ( & sender ) ;
2016-01-12 17:40:34 +01:00
self . state . sub_balance ( & sender , & U256 ::from ( gas_cost ) ) ;
2016-01-09 21:39:38 +01:00
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-11 15:55:54 +01:00
2016-03-19 14:29:09 +01:00
let ( gas_left , output ) = match t . action {
2016-01-17 15:56:09 +01:00
Action ::Create = > {
2016-01-15 15:00:28 +01:00
let new_address = contract_address ( & sender , & nonce ) ;
2016-01-11 16:33:08 +01:00
let params = ActionParams {
2016-01-15 15:00:28 +01:00
code_address : new_address . clone ( ) ,
address : new_address ,
2016-01-09 17:55:47 +01:00
sender : sender . clone ( ) ,
origin : sender . clone ( ) ,
2016-01-14 01:18:44 +01:00
gas : init_gas ,
2016-01-09 17:55:47 +01:00
gas_price : t . gas_price ,
2016-01-20 17:27:33 +01:00
value : ActionValue ::Transfer ( t . value ) ,
2016-01-15 15:00:28 +01:00
code : Some ( t . data . clone ( ) ) ,
data : None ,
2016-01-09 17:55:47 +01:00
} ;
2016-06-02 12:40:31 +02:00
( self . create ( params , & mut substate , & mut tracer , & mut vm_tracer ) , vec! [ ] )
2016-01-09 00:51:09 +01:00
} ,
2016-01-17 15:56:09 +01:00
Action ::Call ( ref address ) = > {
2016-01-11 16:33:08 +01:00
let params = ActionParams {
2016-01-15 15:00:28 +01:00
code_address : address . clone ( ) ,
2016-01-11 15:23:27 +01:00
address : address . clone ( ) ,
2016-01-09 17:55:47 +01:00
sender : sender . clone ( ) ,
origin : sender . clone ( ) ,
2016-01-14 01:18:44 +01:00
gas : init_gas ,
2016-01-09 17:55:47 +01:00
gas_price : t . gas_price ,
2016-01-20 17:27:33 +01:00
value : ActionValue ::Transfer ( t . value ) ,
2016-01-15 15:00:28 +01:00
code : self . state . code ( address ) ,
data : Some ( t . data . clone ( ) ) ,
2016-01-09 17:55:47 +01:00
} ;
2016-01-13 15:26:52 +01:00
// TODO: move output upstream
let mut out = vec! [ ] ;
2016-06-02 12:40:31 +02:00
( self . call ( params , & mut substate , BytesRef ::Flexible ( & mut out ) , & mut tracer , & mut vm_tracer ) , out )
2016-01-09 17:55:47 +01:00
}
2016-01-09 21:39:38 +01:00
} ;
// finalize here!
2016-06-02 12:40:31 +02:00
Ok ( try ! ( self . finalize ( t , substate , gas_left , output , tracer . traces ( ) . pop ( ) , vm_tracer . drain ( ) ) ) )
2016-01-07 19:05:44 +01:00
}
2016-06-02 12:40:31 +02:00
fn exec_vm < T , V > (
& mut self ,
params : ActionParams ,
unconfirmed_substate : & mut Substate ,
output_policy : OutputPolicy ,
tracer : & mut T ,
vm_tracer : & mut V
2016-06-02 19:04:15 +02:00
) -> evm ::Result < U256 > where T : Tracer , V : VMTracer {
2016-01-26 10:15:55 +01:00
// Ordinary execution - keep VM in same thread
if ( self . depth + 1 ) % MAX_VM_DEPTH_FOR_THREAD ! = 0 {
2016-05-19 00:44:49 +02:00
let vm_factory = self . vm_factory ;
2016-06-02 12:40:31 +02:00
let mut ext = self . as_externalities ( OriginInfo ::from ( & params ) , unconfirmed_substate , output_policy , tracer , vm_tracer ) ;
2016-03-20 19:20:37 +01:00
trace! ( target : " executive " , " ext.schedule.have_delegate_call: {} " , ext . schedule ( ) . have_delegate_call ) ;
2016-07-05 15:15:44 +02:00
return vm_factory . create ( params . gas ) . exec ( params , & mut ext ) . finalize ( ext ) ;
2016-01-26 10:15:55 +01:00
}
// Start in new thread to reset stack
// TODO [todr] No thread builder yet, so we need to reset once for a while
// https://github.com/aturon/crossbeam/issues/16
crossbeam ::scope ( | scope | {
2016-05-19 00:44:49 +02:00
let vm_factory = self . vm_factory ;
2016-06-02 12:40:31 +02:00
let mut ext = self . as_externalities ( OriginInfo ::from ( & params ) , unconfirmed_substate , output_policy , tracer , vm_tracer ) ;
2016-01-26 10:15:55 +01:00
scope . spawn ( move | | {
2016-07-05 15:15:44 +02:00
vm_factory . create ( params . gas ) . exec ( params , & mut ext ) . finalize ( ext )
2016-01-26 10:15:55 +01:00
} )
} ) . join ( )
}
2016-01-09 21:39:38 +01:00
/// Calls contract function with given contract params.
2016-01-11 02:17:29 +01:00
/// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides).
/// Modifies the substate and the output.
2016-01-11 17:01:42 +01:00
/// Returns either gas_left or `evm::Error`.
2016-06-02 12:40:31 +02:00
pub fn call < T , V > (
& mut self ,
params : ActionParams ,
substate : & mut Substate ,
mut output : BytesRef ,
tracer : & mut T ,
vm_tracer : & mut V
2016-06-02 19:04:15 +02:00
) -> evm ::Result < U256 > where T : Tracer , V : VMTracer {
2016-01-14 17:40:38 +01:00
// backup used in case of running out of gas
2016-02-03 19:34:51 +01:00
self . state . snapshot ( ) ;
2016-01-14 17:40:38 +01:00
2016-01-09 22:54:16 +01:00
// at first, transfer value to destination
2016-01-20 17:27:33 +01:00
if let ActionValue ::Transfer ( val ) = params . value {
self . state . transfer_balance ( & params . sender , & params . address , & val ) ;
2016-01-20 16:52:22 +01:00
}
2016-01-18 00:58:06 +01:00
trace! ( " Executive::call(params={:?}) self.env_info={:?} " , params , self . info ) ;
2016-01-09 22:54:16 +01:00
2016-04-30 17:41:24 +02:00
let delegate_call = params . code_address ! = params . address ;
2016-01-15 15:00:28 +01:00
if self . engine . is_builtin ( & params . code_address ) {
2016-01-11 02:17:29 +01:00
// if destination is builtin, try to execute it
2016-02-09 16:31:57 +01:00
2016-01-15 15:00:28 +01:00
let default = [ ] ;
2016-01-17 15:56:09 +01:00
let data = if let Some ( ref d ) = params . data { d as & [ u8 ] } else { & default as & [ u8 ] } ;
2016-01-15 15:14:41 +01:00
2016-04-30 17:41:24 +02:00
let trace_info = tracer . prepare_trace_call ( & params ) ;
2016-01-15 15:14:41 +01:00
let cost = self . engine . cost_of_builtin ( & params . code_address , data ) ;
2016-07-24 17:38:21 +02:00
if cost < = params . gas {
self . engine . execute_builtin ( & params . code_address , data , & mut output ) ;
self . state . clear_snapshot ( ) ;
// trace only top level calls to builtins to avoid DDoS attacks
if self . depth = = 0 {
let mut trace_output = tracer . prepare_trace_output ( ) ;
if let Some ( mut out ) = trace_output . as_mut ( ) {
* out = output . to_owned ( ) ;
2016-04-30 17:41:24 +02:00
}
2016-07-24 17:38:21 +02:00
tracer . trace_call (
trace_info ,
cost ,
trace_output ,
self . depth ,
vec! [ ] ,
delegate_call
) ;
}
Ok ( params . gas - cost )
} else {
2016-01-14 17:40:38 +01:00
// just drain the whole gas
2016-07-24 17:38:21 +02:00
self . state . revert_snapshot ( ) ;
2016-04-30 17:41:24 +02:00
2016-07-24 17:38:21 +02:00
tracer . trace_failed_call ( trace_info , self . depth , vec! [ ] , delegate_call ) ;
2016-04-30 17:41:24 +02:00
2016-07-24 17:38:21 +02:00
Err ( evm ::Error ::OutOfGas )
2016-01-09 22:54:16 +01:00
}
2016-03-21 11:24:03 +01:00
} else {
2016-04-08 01:50:55 +02:00
let trace_info = tracer . prepare_trace_call ( & params ) ;
let mut trace_output = tracer . prepare_trace_output ( ) ;
let mut subtracer = tracer . subtracer ( ) ;
2016-06-02 12:40:31 +02:00
2016-04-08 01:50:55 +02:00
let gas = params . gas ;
2016-03-18 23:49:12 +01:00
2016-03-21 11:24:03 +01:00
if params . code . is_some ( ) {
// part of substate that may be reverted
2016-04-08 01:50:55 +02:00
let mut unconfirmed_substate = Substate ::new ( ) ;
2016-01-15 18:56:28 +01:00
2016-06-02 12:40:31 +02:00
// TODO: make ActionParams pass by ref then avoid copy altogether.
2016-07-24 17:38:21 +02:00
let mut subvmtracer = vm_tracer . prepare_subtrace ( params . code . as_ref ( ) . expect ( " scope is conditional on params.code.is_some(); qed " ) ) ;
2016-06-02 12:40:31 +02:00
2016-03-21 11:24:03 +01:00
let res = {
2016-06-02 12:40:31 +02:00
self . exec_vm ( params , & mut unconfirmed_substate , OutputPolicy ::Return ( output , trace_output . as_mut ( ) ) , & mut subtracer , & mut subvmtracer )
2016-03-21 11:24:03 +01:00
} ;
2016-03-20 19:20:37 +01:00
2016-06-02 12:40:31 +02:00
vm_tracer . done_subtrace ( subvmtracer ) ;
2016-03-21 11:24:03 +01:00
trace! ( target : " executive " , " res={:?} " , res ) ;
2016-03-18 23:49:12 +01:00
2016-04-08 01:50:55 +02:00
let traces = subtracer . traces ( ) ;
match res {
Ok ( gas_left ) = > tracer . trace_call (
trace_info ,
gas - gas_left ,
trace_output ,
self . depth ,
traces ,
delegate_call
) ,
_ = > tracer . trace_failed_call ( trace_info , self . depth , traces , delegate_call ) ,
} ;
2016-03-18 23:49:12 +01:00
2016-03-21 11:24:03 +01:00
trace! ( target : " executive " , " substate={:?}; unconfirmed_substate={:?} \n " , substate , unconfirmed_substate ) ;
2016-04-08 01:50:55 +02:00
self . enact_result ( & res , substate , unconfirmed_substate ) ;
2016-03-21 11:24:03 +01:00
trace! ( target : " executive " , " enacted: substate={:?} \n " , substate ) ;
res
} else {
// otherwise it's just a basic transaction, only do tracing, if necessary.
self . state . clear_snapshot ( ) ;
2016-04-08 01:50:55 +02:00
2016-04-08 11:48:37 +02:00
tracer . trace_call ( trace_info , U256 ::zero ( ) , trace_output , self . depth , vec! [ ] , delegate_call ) ;
2016-03-21 11:56:11 +01:00
Ok ( params . gas )
2016-03-21 11:24:03 +01:00
}
2016-01-09 22:54:16 +01:00
}
2016-01-07 19:05:44 +01:00
}
2016-02-09 16:31:57 +01:00
2016-01-09 21:39:38 +01:00
/// Creates contract with given contract params.
2016-01-11 02:17:29 +01:00
/// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides).
/// Modifies the substate.
2016-06-02 12:40:31 +02:00
pub fn create < T , V > (
& mut self ,
params : ActionParams ,
substate : & mut Substate ,
tracer : & mut T ,
vm_tracer : & mut V
2016-06-02 19:04:15 +02:00
) -> evm ::Result < U256 > where T : Tracer , V : VMTracer {
2016-01-14 17:40:38 +01:00
// backup used in case of running out of gas
2016-02-03 19:34:51 +01:00
self . state . snapshot ( ) ;
2016-01-14 17:40:38 +01:00
2016-01-15 00:54:19 +01:00
// part of substate that may be reverted
2016-04-08 01:50:55 +02:00
let mut unconfirmed_substate = Substate ::new ( ) ;
2016-01-15 00:54:19 +01:00
2016-01-29 18:33:47 +01:00
// create contract and transfer value to it if necessary
let prev_bal = self . state . balance ( & params . address ) ;
2016-01-20 17:27:33 +01:00
if let ActionValue ::Transfer ( val ) = params . value {
2016-01-29 18:33:47 +01:00
self . state . sub_balance ( & params . sender , & val ) ;
self . state . new_contract ( & params . address , val + prev_bal ) ;
} else {
self . state . new_contract ( & params . address , prev_bal ) ;
2016-01-20 16:52:22 +01:00
}
2016-01-09 17:55:47 +01:00
2016-04-08 01:50:55 +02:00
let trace_info = tracer . prepare_trace_create ( & params ) ;
let mut trace_output = tracer . prepare_trace_output ( ) ;
let mut subtracer = tracer . subtracer ( ) ;
let gas = params . gas ;
2016-03-18 23:49:12 +01:00
let created = params . address . clone ( ) ;
2016-07-26 20:31:25 +02:00
let mut subvmtracer = vm_tracer . prepare_subtrace ( params . code . as_ref ( ) . expect ( " two ways into create (Externalities::create and Executive::transact_with_tracer); both place `Some(...)` `code` in `params`; qed " ) ) ;
2016-06-02 12:40:31 +02:00
2016-01-14 17:40:38 +01:00
let res = {
2016-06-02 12:40:31 +02:00
self . exec_vm ( params , & mut unconfirmed_substate , OutputPolicy ::InitContract ( trace_output . as_mut ( ) ) , & mut subtracer , & mut subvmtracer )
2016-01-14 17:40:38 +01:00
} ;
2016-03-18 23:49:12 +01:00
2016-06-02 12:40:31 +02:00
vm_tracer . done_subtrace ( subvmtracer ) ;
2016-04-08 01:50:55 +02:00
match res {
Ok ( gas_left ) = > tracer . trace_create (
trace_info ,
gas - gas_left ,
trace_output ,
created ,
self . depth ,
subtracer . traces ( )
) ,
_ = > tracer . trace_failed_create ( trace_info , self . depth , subtracer . traces ( ) )
} ;
2016-03-18 23:49:12 +01:00
2016-04-08 01:50:55 +02:00
self . enact_result ( & res , substate , unconfirmed_substate ) ;
2016-01-14 19:52:40 +01:00
res
2016-01-07 19:05:44 +01:00
}
2016-01-09 21:39:38 +01:00
2016-01-09 22:54:16 +01:00
/// Finalizes the transaction (does refunds and suicides).
2016-06-02 12:40:31 +02:00
fn finalize (
& mut self ,
t : & SignedTransaction ,
substate : Substate ,
2016-06-02 19:04:15 +02:00
result : evm ::Result < U256 > ,
2016-06-02 12:40:31 +02:00
output : Bytes ,
trace : Option < Trace > ,
vm_trace : Option < VMTrace >
) -> ExecutionResult {
2016-01-15 00:36:58 +01:00
let schedule = self . engine . schedule ( self . info ) ;
// refunds from SSTORE nonzero -> zero
2016-01-16 20:11:12 +01:00
let sstore_refunds = U256 ::from ( schedule . sstore_refund_gas ) * substate . sstore_clears_count ;
2016-01-15 00:36:58 +01:00
// refunds from contract suicides
let suicide_refunds = U256 ::from ( schedule . suicide_refund_gas ) * U256 ::from ( substate . suicides . len ( ) ) ;
2016-01-15 18:56:28 +01:00
let refunds_bound = sstore_refunds + suicide_refunds ;
2016-01-15 00:36:58 +01:00
// real ammount to refund
2016-05-31 16:59:01 +02:00
let gas_left_prerefund = match result { Ok ( x ) = > x , _ = > 0. into ( ) } ;
2016-01-15 18:56:28 +01:00
let refunded = cmp ::min ( refunds_bound , ( t . gas - gas_left_prerefund ) / U256 ::from ( 2 ) ) ;
let gas_left = gas_left_prerefund + refunded ;
let gas_used = t . gas - gas_left ;
let refund_value = gas_left * t . gas_price ;
let fees_value = gas_used * t . gas_price ;
2016-01-16 01:48:38 +01:00
trace! ( " exec::finalize: t.gas={}, sstore_refunds={}, suicide_refunds={}, refunds_bound={}, gas_left_prerefund={}, refunded={}, gas_left={}, gas_used={}, refund_value={}, fees_value={} \n " ,
t . gas , sstore_refunds , suicide_refunds , refunds_bound , gas_left_prerefund , refunded , gas_left , gas_used , refund_value , fees_value ) ;
2016-01-15 18:56:28 +01:00
2016-01-16 01:48:38 +01:00
trace! ( " exec::finalize: Refunding refund_value={}, sender={} \n " , refund_value , t . sender ( ) . unwrap ( ) ) ;
2016-01-15 00:36:58 +01:00
self . state . add_balance ( & t . sender ( ) . unwrap ( ) , & refund_value ) ;
2016-01-16 01:48:38 +01:00
trace! ( " exec::finalize: Compensating author: fees_value={}, author={} \n " , fees_value , & self . info . author ) ;
2016-01-15 18:56:28 +01:00
self . state . add_balance ( & self . info . author , & fees_value ) ;
2016-01-15 00:36:58 +01:00
// perform suicides
2016-01-17 15:56:09 +01:00
for address in & substate . suicides {
2016-01-15 00:36:58 +01:00
self . state . kill_account ( address ) ;
}
2016-02-09 16:31:57 +01:00
match result {
2016-01-11 17:01:42 +01:00
Err ( evm ::Error ::Internal ) = > Err ( ExecutionError ::Internal ) ,
2016-01-17 15:56:09 +01:00
Err ( _ ) = > {
2016-01-11 17:37:22 +01:00
Ok ( Executed {
gas : t . gas ,
gas_used : t . gas ,
refunded : U256 ::zero ( ) ,
cumulative_gas_used : self . info . gas_used + t . gas ,
logs : vec ! [ ] ,
2016-03-18 23:49:12 +01:00
contracts_created : vec ! [ ] ,
2016-03-19 14:29:09 +01:00
output : output ,
2016-03-20 12:04:31 +01:00
trace : trace ,
2016-06-02 12:40:31 +02:00
vm_trace : vm_trace ,
2016-06-02 12:39:25 +02:00
state_diff : None ,
2016-01-11 17:37:22 +01:00
} )
2016-01-11 15:55:54 +01:00
} ,
2016-01-15 18:56:28 +01:00
_ = > {
2016-01-11 16:05:21 +01:00
Ok ( Executed {
gas : t . gas ,
gas_used : gas_used ,
2016-01-15 18:56:28 +01:00
refunded : refunded ,
2016-01-11 16:05:21 +01:00
cumulative_gas_used : self . info . gas_used + gas_used ,
2016-01-11 17:37:22 +01:00
logs : substate . logs ,
2016-01-15 18:56:28 +01:00
contracts_created : substate . contracts_created ,
2016-03-19 14:29:09 +01:00
output : output ,
2016-03-20 12:04:31 +01:00
trace : trace ,
2016-06-02 12:40:31 +02:00
vm_trace : vm_trace ,
2016-06-02 12:39:25 +02:00
state_diff : None ,
2016-01-11 16:05:21 +01:00
} )
2016-01-14 17:40:38 +01:00
} ,
2016-01-09 23:24:01 +01:00
}
2016-01-09 21:39:38 +01:00
}
2016-01-14 17:40:38 +01:00
2016-06-02 19:04:15 +02:00
fn enact_result ( & mut self , result : & evm ::Result < U256 > , substate : & mut Substate , un_substate : Substate ) {
2016-01-17 15:56:09 +01:00
match * result {
Err ( evm ::Error ::OutOfGas )
2016-02-09 16:31:57 +01:00
| Err ( evm ::Error ::BadJumpDestination { .. } )
| Err ( evm ::Error ::BadInstruction { .. } )
2016-01-17 15:56:09 +01:00
| Err ( evm ::Error ::StackUnderflow { .. } )
| Err ( evm ::Error ::OutOfStack { .. } ) = > {
2016-04-08 01:50:55 +02:00
self . state . revert_snapshot ( ) ;
2016-01-15 00:04:40 +01:00
} ,
2016-02-03 19:34:51 +01:00
Ok ( _ ) | Err ( evm ::Error ::Internal ) = > {
self . state . clear_snapshot ( ) ;
2016-04-08 01:50:55 +02:00
substate . accrue ( un_substate ) ;
2016-02-03 19:34:51 +01:00
}
2016-01-14 17:40:38 +01:00
}
}
2016-01-09 17:55:47 +01:00
}
2016-01-07 23:33:54 +01:00
#[ cfg(test) ]
2016-02-08 22:54:33 +01:00
#[ allow(dead_code) ]
2016-01-07 23:33:54 +01:00
mod tests {
2016-01-11 17:49:49 +01:00
use super ::* ;
use common ::* ;
2016-02-09 16:31:57 +01:00
use evm ::{ Factory , VMType } ;
2016-01-15 14:22:46 +01:00
use substate ::* ;
2016-01-31 10:52:07 +01:00
use tests ::helpers ::* ;
2016-04-30 17:41:24 +02:00
use trace ::trace ;
use trace ::{ Trace , Tracer , NoopTracer , ExecutiveTracer } ;
2016-06-02 12:40:31 +02:00
use trace ::{ VMTrace , VMOperation , VMExecutedOperation , MemoryDiff , StorageDiff , VMTracer , NoopVMTracer , ExecutiveVMTracer } ;
2016-01-09 01:33:50 +01:00
2016-01-07 23:33:54 +01:00
#[ test ]
fn test_contract_address ( ) {
let address = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
2016-01-09 02:12:17 +01:00
let expected_address = Address ::from_str ( " 3f09c73a5ed19289fb9bdc72f1742566df146f56 " ) . unwrap ( ) ;
assert_eq! ( expected_address , contract_address ( & address , & U256 ::from ( 88 ) ) ) ;
2016-01-07 23:33:54 +01:00
}
2016-01-09 01:33:50 +01:00
2016-01-09 13:51:59 +01:00
// TODO: replace params with transactions!
2016-01-14 16:17:44 +01:00
evm_test! { test_sender_balance : test_sender_balance_jit , test_sender_balance_int }
fn test_sender_balance ( factory : Factory ) {
2016-01-09 02:12:17 +01:00
let sender = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
let address = contract_address ( & sender , & U256 ::zero ( ) ) ;
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-09 02:12:17 +01:00
params . address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
2016-01-12 13:39:12 +01:00
params . gas = U256 ::from ( 100_000 ) ;
2016-01-15 15:00:28 +01:00
params . code = Some ( " 3331600055 " . from_hex ( ) . unwrap ( ) ) ;
2016-01-20 17:31:37 +01:00
params . value = ActionValue ::Transfer ( U256 ::from ( 0x7 ) ) ;
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
2016-01-09 02:12:17 +01:00
state . add_balance ( & sender , & U256 ::from ( 0x100 u64 ) ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-09 02:12:17 +01:00
2016-01-12 13:39:12 +01:00
let gas_left = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( )
2016-01-12 13:39:12 +01:00
} ;
2016-01-09 02:12:17 +01:00
2016-01-12 13:39:12 +01:00
assert_eq! ( gas_left , U256 ::from ( 79_975 ) ) ;
2016-01-09 13:51:59 +01:00
assert_eq! ( state . storage_at ( & address , & H256 ::new ( ) ) , H256 ::from ( & U256 ::from ( 0xf9 u64 ) ) ) ;
2016-01-09 02:12:17 +01:00
assert_eq! ( state . balance ( & sender ) , U256 ::from ( 0xf9 ) ) ;
assert_eq! ( state . balance ( & address ) , U256 ::from ( 0x7 ) ) ;
2016-01-12 16:05:54 +01:00
// 0 cause contract hasn't returned
assert_eq! ( substate . contracts_created . len ( ) , 0 ) ;
2016-01-11 17:37:22 +01:00
// TODO: just test state root.
2016-01-09 01:33:50 +01:00
}
2016-01-09 13:51:59 +01:00
2016-03-19 21:02:44 +01:00
evm_test! { test_create_contract_out_of_depth : test_create_contract_out_of_depth_jit , test_create_contract_out_of_depth_int }
fn test_create_contract_out_of_depth ( factory : Factory ) {
2016-01-12 16:05:54 +01:00
// code:
//
2016-01-12 13:39:12 +01:00
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
// 60 00 - push 0
// 52
// 60 1d - push 29
// 60 03 - push 3
// 60 17 - push 17
// f0 - create
// 60 00 - push 0
// 55 sstore
2016-01-12 16:05:54 +01:00
//
// other code:
//
// 60 10 - push 16
// 80 - duplicate first stack item
// 60 0c - push 12
// 60 00 - push 0
// 39 - copy current code to memory
// 60 00 - push 0
// f3 - return
2016-01-12 13:39:12 +01:00
let code = " 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055 " . from_hex ( ) . unwrap ( ) ;
2016-01-09 13:51:59 +01:00
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
let address = contract_address ( & sender , & U256 ::zero ( ) ) ;
2016-01-12 13:39:12 +01:00
// TODO: add tests for 'callcreate'
//let next_address = contract_address(&address, &U256::zero());
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-09 13:51:59 +01:00
params . address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
2016-01-12 13:39:12 +01:00
params . gas = U256 ::from ( 100_000 ) ;
2016-01-15 15:00:28 +01:00
params . code = Some ( code . clone ( ) ) ;
2016-01-20 17:31:37 +01:00
params . value = ActionValue ::Transfer ( U256 ::from ( 100 ) ) ;
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
2016-01-12 13:39:12 +01:00
state . add_balance ( & sender , & U256 ::from ( 100 ) ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-09 13:51:59 +01:00
2016-01-12 13:39:12 +01:00
let gas_left = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( )
2016-01-12 13:39:12 +01:00
} ;
2016-02-09 16:31:57 +01:00
2016-01-13 13:16:53 +01:00
assert_eq! ( gas_left , U256 ::from ( 62_976 ) ) ;
// ended with max depth
assert_eq! ( substate . contracts_created . len ( ) , 0 ) ;
}
2016-03-19 22:12:52 +01:00
evm_test! { test_call_to_create : test_call_to_create_jit , test_call_to_create_int }
fn test_call_to_create ( factory : Factory ) {
2016-03-19 21:02:44 +01:00
// code:
//
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
// 60 00 - push 0
// 52
// 60 1d - push 29
// 60 03 - push 3
2016-06-02 12:40:31 +02:00
// 60 17 - push 23
2016-03-19 21:02:44 +01:00
// f0 - create
// 60 00 - push 0
// 55 sstore
//
// other code:
//
// 60 10 - push 16
// 80 - duplicate first stack item
// 60 0c - push 12
// 60 00 - push 0
// 39 - copy current code to memory
// 60 00 - push 0
// f3 - return
let code = " 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055 " . from_hex ( ) . unwrap ( ) ;
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
let address = contract_address ( & sender , & U256 ::zero ( ) ) ;
// TODO: add tests for 'callcreate'
//let next_address = contract_address(&address, &U256::zero());
let mut params = ActionParams ::default ( ) ;
params . address = address . clone ( ) ;
2016-03-21 11:24:03 +01:00
params . code_address = address . clone ( ) ;
2016-03-19 21:02:44 +01:00
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
params . gas = U256 ::from ( 100_000 ) ;
params . code = Some ( code . clone ( ) ) ;
params . value = ActionValue ::Transfer ( U256 ::from ( 100 ) ) ;
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
state . add_balance ( & sender , & U256 ::from ( 100 ) ) ;
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 5 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
let mut tracer = ExecutiveTracer ::default ( ) ;
2016-06-02 12:40:31 +02:00
let mut vm_tracer = ExecutiveVMTracer ::default ( ) ;
2016-03-19 21:02:44 +01:00
let gas_left = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-03-19 21:02:44 +01:00
let output = BytesRef ::Fixed ( & mut [ 0 u8 ; 0 ] ) ;
2016-06-02 12:40:31 +02:00
ex . call ( params , & mut substate , output , & mut tracer , & mut vm_tracer ) . unwrap ( )
2016-03-19 21:02:44 +01:00
} ;
2016-06-02 12:40:31 +02:00
assert_eq! ( gas_left , U256 ::from ( 44_752 ) ) ;
2016-04-08 01:50:55 +02:00
let expected_trace = vec! [ Trace {
2016-03-19 21:02:44 +01:00
depth : 0 ,
2016-04-30 17:41:24 +02:00
action : trace ::Action ::Call ( trace ::Call {
2016-05-31 16:59:01 +02:00
from : " cd1722f3947def4cf144679da39c4c32bdc35681 " . into ( ) ,
to : " b010143a42d5980c7e5ef0e4a4416dc098a4fed3 " . into ( ) ,
value : 100. into ( ) ,
gas : 100000. into ( ) ,
2016-03-19 21:02:44 +01:00
input : vec ! [ ] ,
2016-04-08 01:50:55 +02:00
} ) ,
2016-04-30 17:41:24 +02:00
result : trace ::Res ::Call ( trace ::CallResult {
2016-04-08 01:50:55 +02:00
gas_used : U256 ::from ( 55_248 ) ,
output : vec ! [ ] ,
2016-03-19 21:02:44 +01:00
} ) ,
subs : vec ! [ Trace {
depth : 1 ,
2016-04-30 17:41:24 +02:00
action : trace ::Action ::Create ( trace ::Create {
2016-05-31 16:59:01 +02:00
from : " b010143a42d5980c7e5ef0e4a4416dc098a4fed3 " . into ( ) ,
value : 23. into ( ) ,
gas : 67979. into ( ) ,
2016-04-08 01:50:55 +02:00
init : vec ! [ 96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 , 85 ]
} ) ,
2016-04-30 17:41:24 +02:00
result : trace ::Res ::Create ( trace ::CreateResult {
2016-04-08 01:50:55 +02:00
gas_used : U256 ::from ( 3224 ) ,
address : Address ::from_str ( " c6d80f262ae5e0f164e5fde365044d7ada2bfa34 " ) . unwrap ( ) ,
code : vec ! [ 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 ]
2016-03-19 21:02:44 +01:00
} ) ,
subs : vec ! [ ]
} ]
2016-04-08 01:50:55 +02:00
} ] ;
assert_eq! ( tracer . traces ( ) , expected_trace ) ;
2016-06-02 12:40:31 +02:00
let expected_vm_trace = VMTrace {
parent_step : 0 ,
code : vec ! [ 124 , 96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 , 85 , 96 , 0 , 82 , 96 , 29 , 96 , 3 , 96 , 23 , 240 , 96 , 0 , 85 ] ,
operations : vec ! [
2016-06-02 19:04:15 +02:00
VMOperation { pc : 0 , instruction : 124 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99997. into ( ) , stack_push : vec_into ! [ U256 ::from_dec_str ( " 2589892687202724018173567190521546555304938078595079151649957320078677 " ) . unwrap ( ) ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 30 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99994. into ( ) , stack_push : vec_into ! [ 0 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 32 , instruction : 82 , gas_cost : 6. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99988. into ( ) , stack_push : vec_into ! [ ] , mem_diff : Some ( MemoryDiff { offset : 0 , data : vec ! [ 0 , 0 , 0 , 96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 , 85 ] } ) , store_diff : None } ) } ,
VMOperation { pc : 33 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99985. into ( ) , stack_push : vec_into ! [ 29 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 35 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99982. into ( ) , stack_push : vec_into ! [ 3 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 37 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99979. into ( ) , stack_push : vec_into ! [ 23 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 39 , instruction : 240 , gas_cost : 32000. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67979. into ( ) , stack_push : vec_into ! [ U256 ::from_dec_str ( " 1135198453258042933984631383966629874710669425204 " ) . unwrap ( ) ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 40 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 64752. into ( ) , stack_push : vec_into ! [ 0 ] , mem_diff : None , store_diff : None } ) } ,
2016-06-02 12:40:31 +02:00
VMOperation { pc : 42 , instruction : 85 , gas_cost : 20000. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 44752. into ( ) , stack_push : vec_into ! [ ] , mem_diff : None , store_diff : Some ( StorageDiff { location : 0. into ( ) , value : U256 ::from_dec_str ( " 1135198453258042933984631383966629874710669425204 " ) . unwrap ( ) } ) } ) }
] ,
subs : vec ! [
VMTrace {
parent_step : 7 ,
code : vec ! [ 96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 , 85 ] ,
operations : vec ! [
2016-06-02 19:04:15 +02:00
VMOperation { pc : 0 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67976. into ( ) , stack_push : vec_into ! [ 16 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 2 , instruction : 128 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67973. into ( ) , stack_push : vec_into ! [ 16 , 16 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 3 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67970. into ( ) , stack_push : vec_into ! [ 12 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 5 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67967. into ( ) , stack_push : vec_into ! [ 0 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 7 , instruction : 57 , gas_cost : 9. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67958. into ( ) , stack_push : vec_into ! [ ] , mem_diff : Some ( MemoryDiff { offset : 0 , data : vec ! [ 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 ] } ) , store_diff : None } ) } ,
VMOperation { pc : 8 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67955. into ( ) , stack_push : vec_into ! [ 0 ] , mem_diff : None , store_diff : None } ) } ,
2016-06-02 12:40:31 +02:00
VMOperation { pc : 10 , instruction : 243 , gas_cost : 0. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67955. into ( ) , stack_push : vec_into ! [ ] , mem_diff : None , store_diff : None } ) }
] ,
subs : vec ! [ ]
}
]
} ;
assert_eq! ( vm_tracer . drain ( ) . unwrap ( ) , expected_vm_trace ) ;
2016-03-19 21:02:44 +01:00
}
2016-03-19 22:12:52 +01:00
evm_test! { test_create_contract : test_create_contract_jit , test_create_contract_int }
fn test_create_contract ( factory : Factory ) {
// code:
//
// 60 10 - push 16
// 80 - duplicate first stack item
// 60 0c - push 12
// 60 00 - push 0
// 39 - copy current code to memory
// 60 00 - push 0
// f3 - return
let code = " 601080600c6000396000f3006000355415600957005b60203560003555 " . from_hex ( ) . unwrap ( ) ;
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
let address = contract_address ( & sender , & U256 ::zero ( ) ) ;
// TODO: add tests for 'callcreate'
//let next_address = contract_address(&address, &U256::zero());
let mut params = ActionParams ::default ( ) ;
params . address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
params . gas = U256 ::from ( 100_000 ) ;
params . code = Some ( code . clone ( ) ) ;
2016-05-31 16:59:01 +02:00
params . value = ActionValue ::Transfer ( 100. into ( ) ) ;
2016-03-19 22:12:52 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
state . add_balance ( & sender , & U256 ::from ( 100 ) ) ;
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 5 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
let mut tracer = ExecutiveTracer ::default ( ) ;
2016-06-02 12:40:31 +02:00
let mut vm_tracer = ExecutiveVMTracer ::default ( ) ;
2016-03-19 22:12:52 +01:00
let gas_left = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params . clone ( ) , & mut substate , & mut tracer , & mut vm_tracer ) . unwrap ( )
2016-03-19 22:12:52 +01:00
} ;
2016-06-02 12:40:31 +02:00
assert_eq! ( gas_left , U256 ::from ( 96_776 ) ) ;
2016-04-08 01:50:55 +02:00
let expected_trace = vec! [ Trace {
2016-03-19 22:12:52 +01:00
depth : 0 ,
2016-04-30 17:41:24 +02:00
action : trace ::Action ::Create ( trace ::Create {
2016-03-19 22:12:52 +01:00
from : params . sender ,
2016-05-31 16:59:01 +02:00
value : 100. into ( ) ,
2016-03-19 22:12:52 +01:00
gas : params . gas ,
init : vec ! [ 96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 , 85 ] ,
2016-04-08 01:50:55 +02:00
} ) ,
2016-04-30 17:41:24 +02:00
result : trace ::Res ::Create ( trace ::CreateResult {
2016-04-08 01:50:55 +02:00
gas_used : U256 ::from ( 3224 ) ,
address : params . address ,
code : vec ! [ 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 ]
2016-03-19 22:12:52 +01:00
} ) ,
subs : vec ! [ ]
2016-04-08 01:50:55 +02:00
} ] ;
assert_eq! ( tracer . traces ( ) , expected_trace ) ;
2016-06-02 19:04:15 +02:00
2016-06-02 12:40:31 +02:00
let expected_vm_trace = VMTrace {
parent_step : 0 ,
code : vec ! [ 96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 , 85 ] ,
operations : vec ! [
VMOperation { pc : 0 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99997. into ( ) , stack_push : vec_into ! [ 16 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 2 , instruction : 128 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99994. into ( ) , stack_push : vec_into ! [ 16 , 16 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 3 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99991. into ( ) , stack_push : vec_into ! [ 12 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 5 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99988. into ( ) , stack_push : vec_into ! [ 0 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 7 , instruction : 57 , gas_cost : 9. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99979. into ( ) , stack_push : vec_into ! [ ] , mem_diff : Some ( MemoryDiff { offset : 0 , data : vec ! [ 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 ] } ) , store_diff : None } ) } ,
VMOperation { pc : 8 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99976. into ( ) , stack_push : vec_into ! [ 0 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 10 , instruction : 243 , gas_cost : 0. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99976. into ( ) , stack_push : vec_into ! [ ] , mem_diff : None , store_diff : None } ) }
] ,
subs : vec ! [ ]
} ;
assert_eq! ( vm_tracer . drain ( ) . unwrap ( ) , expected_vm_trace ) ;
2016-03-19 22:12:52 +01:00
}
2016-03-21 11:24:03 +01:00
2016-01-14 16:17:44 +01:00
evm_test! { test_create_contract_value_too_high : test_create_contract_value_too_high_jit , test_create_contract_value_too_high_int }
fn test_create_contract_value_too_high ( factory : Factory ) {
2016-01-13 13:16:53 +01:00
// code:
//
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
// 60 00 - push 0
// 52
// 60 1d - push 29
// 60 03 - push 3
// 60 e6 - push 230
// f0 - create a contract trying to send 230.
// 60 00 - push 0
// 55 sstore
//
// other code:
//
// 60 10 - push 16
// 80 - duplicate first stack item
// 60 0c - push 12
// 60 00 - push 0
// 39 - copy current code to memory
// 60 00 - push 0
// f3 - return
let code = " 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d600360e6f0600055 " . from_hex ( ) . unwrap ( ) ;
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
let address = contract_address ( & sender , & U256 ::zero ( ) ) ;
// TODO: add tests for 'callcreate'
//let next_address = contract_address(&address, &U256::zero());
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-13 13:16:53 +01:00
params . address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
params . gas = U256 ::from ( 100_000 ) ;
2016-01-15 15:00:28 +01:00
params . code = Some ( code . clone ( ) ) ;
2016-01-20 17:31:37 +01:00
params . value = ActionValue ::Transfer ( U256 ::from ( 100 ) ) ;
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
2016-01-13 13:16:53 +01:00
state . add_balance ( & sender , & U256 ::from ( 100 ) ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-13 13:16:53 +01:00
let gas_left = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( )
2016-01-13 13:16:53 +01:00
} ;
2016-02-09 16:31:57 +01:00
2016-01-13 13:16:53 +01:00
assert_eq! ( gas_left , U256 ::from ( 62_976 ) ) ;
2016-01-12 16:05:54 +01:00
assert_eq! ( substate . contracts_created . len ( ) , 0 ) ;
}
2016-01-14 16:17:44 +01:00
evm_test! { test_create_contract_without_max_depth : test_create_contract_without_max_depth_jit , test_create_contract_without_max_depth_int }
fn test_create_contract_without_max_depth ( factory : Factory ) {
2016-01-12 16:05:54 +01:00
// code:
//
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
// 60 00 - push 0
// 52
// 60 1d - push 29
// 60 03 - push 3
// 60 17 - push 17
// f0 - create
// 60 00 - push 0
// 55 sstore
//
// other code:
//
// 60 10 - push 16
// 80 - duplicate first stack item
// 60 0c - push 12
// 60 00 - push 0
// 39 - copy current code to memory
// 60 00 - push 0
// f3 - return
2016-01-14 12:33:49 +01:00
let code = " 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0 " . from_hex ( ) . unwrap ( ) ;
2016-01-12 16:05:54 +01:00
2016-01-09 13:51:59 +01:00
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
let address = contract_address ( & sender , & U256 ::zero ( ) ) ;
let next_address = contract_address ( & address , & U256 ::zero ( ) ) ;
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-09 13:51:59 +01:00
params . address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
2016-01-12 16:05:54 +01:00
params . gas = U256 ::from ( 100_000 ) ;
2016-01-15 15:00:28 +01:00
params . code = Some ( code . clone ( ) ) ;
2016-01-20 17:31:37 +01:00
params . value = ActionValue ::Transfer ( U256 ::from ( 100 ) ) ;
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
2016-01-12 16:05:54 +01:00
state . add_balance ( & sender , & U256 ::from ( 100 ) ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 1024 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-09 13:51:59 +01:00
{
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( ) ;
2016-01-09 13:51:59 +01:00
}
2016-02-09 16:31:57 +01:00
2016-01-12 16:05:54 +01:00
assert_eq! ( substate . contracts_created . len ( ) , 1 ) ;
assert_eq! ( substate . contracts_created [ 0 ] , next_address ) ;
2016-01-12 13:39:12 +01:00
}
2016-01-16 04:59:53 +01:00
// test is incorrect, mk
2016-02-08 22:54:33 +01:00
// TODO: fix (preferred) or remove
2016-01-16 04:59:53 +01:00
evm_test_ignore! { test_aba_calls : test_aba_calls_jit , test_aba_calls_int }
2016-01-14 16:17:44 +01:00
fn test_aba_calls ( factory : Factory ) {
2016-01-12 13:39:12 +01:00
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 18 - push 18
// 73 945304eb96065b2a98b57a48a06ae28d285a71b5 - push this address
// 61 03e8 - push 1000
// f1 - message call
// 58 - get PC
// 55 - sstore
let code_a = " 6000600060006000601873945304eb96065b2a98b57a48a06ae28d285a71b56103e8f15855 " . from_hex ( ) . unwrap ( ) ;
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 17 - push 17
// 73 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 - push this address
// 61 0x01f4 - push 500
// f1 - message call
// 60 01 - push 1
// 01 - add
// 58 - get PC
// 55 - sstore
let code_b = " 60006000600060006017730f572e5295c57f15886f9b263e2f6d2d6c7b5ec66101f4f16001015855 " . from_hex ( ) . unwrap ( ) ;
let address_a = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
let address_b = Address ::from_str ( " 945304eb96065b2a98b57a48a06ae28d285a71b5 " ) . unwrap ( ) ;
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-12 13:39:12 +01:00
params . address = address_a . clone ( ) ;
params . sender = sender . clone ( ) ;
params . gas = U256 ::from ( 100_000 ) ;
2016-01-15 15:00:28 +01:00
params . code = Some ( code_a . clone ( ) ) ;
2016-01-20 17:31:37 +01:00
params . value = ActionValue ::Transfer ( U256 ::from ( 100_000 ) ) ;
2016-01-12 13:39:12 +01:00
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
2016-01-12 13:39:12 +01:00
state . init_code ( & address_a , code_a . clone ( ) ) ;
state . init_code ( & address_b , code_b . clone ( ) ) ;
state . add_balance ( & sender , & U256 ::from ( 100_000 ) ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-12 13:39:12 +01:00
let gas_left = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
ex . call ( params , & mut substate , BytesRef ::Fixed ( & mut [ ] ) , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( )
2016-01-12 13:39:12 +01:00
} ;
assert_eq! ( gas_left , U256 ::from ( 73_237 ) ) ;
assert_eq! ( state . storage_at ( & address_a , & H256 ::from ( & U256 ::from ( 0x23 ) ) ) , H256 ::from ( & U256 ::from ( 1 ) ) ) ;
2016-01-10 16:21:01 +01:00
}
2016-01-16 04:59:53 +01:00
// test is incorrect, mk
2016-02-08 22:54:33 +01:00
// TODO: fix (preferred) or remove
2016-01-16 04:59:53 +01:00
evm_test_ignore! { test_recursive_bomb1 : test_recursive_bomb1_jit , test_recursive_bomb1_int }
2016-01-14 16:17:44 +01:00
fn test_recursive_bomb1 ( factory : Factory ) {
2016-01-10 16:21:01 +01:00
// 60 01 - push 1
// 60 00 - push 0
2016-02-09 16:31:57 +01:00
// 54 - sload
2016-01-10 16:21:01 +01:00
// 01 - add
// 60 00 - push 0
// 55 - sstore
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 30 - load address
// 60 e0 - push e0
// 5a - get gas
// 03 - sub
// f1 - message call (self in this case)
// 60 01 - push 1
2016-01-12 13:39:12 +01:00
// 55 - sstore
2016-01-10 16:21:01 +01:00
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2016-01-11 14:08:03 +01:00
let code = " 600160005401600055600060006000600060003060e05a03f1600155 " . from_hex ( ) . unwrap ( ) ;
2016-01-10 16:21:01 +01:00
let address = contract_address ( & sender , & U256 ::zero ( ) ) ;
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-10 16:21:01 +01:00
params . address = address . clone ( ) ;
2016-01-12 13:39:12 +01:00
params . gas = U256 ::from ( 100_000 ) ;
2016-01-15 15:00:28 +01:00
params . code = Some ( code . clone ( ) ) ;
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
2016-01-10 16:21:01 +01:00
state . init_code ( & address , code . clone ( ) ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-10 16:21:01 +01:00
2016-01-12 13:39:12 +01:00
let gas_left = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
ex . call ( params , & mut substate , BytesRef ::Fixed ( & mut [ ] ) , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( )
2016-01-12 13:39:12 +01:00
} ;
2016-01-10 16:21:01 +01:00
2016-01-12 13:39:12 +01:00
assert_eq! ( gas_left , U256 ::from ( 59_870 ) ) ;
assert_eq! ( state . storage_at ( & address , & H256 ::from ( & U256 ::zero ( ) ) ) , H256 ::from ( & U256 ::from ( 1 ) ) ) ;
assert_eq! ( state . storage_at ( & address , & H256 ::from ( & U256 ::one ( ) ) ) , H256 ::from ( & U256 ::from ( 1 ) ) ) ;
2016-01-09 13:51:59 +01:00
}
2016-01-12 18:31:47 +01:00
2016-01-16 04:59:53 +01:00
// test is incorrect, mk
2016-02-08 22:54:33 +01:00
// TODO: fix (preferred) or remove
2016-01-16 04:59:53 +01:00
evm_test_ignore! { test_transact_simple : test_transact_simple_jit , test_transact_simple_int }
2016-01-14 16:17:44 +01:00
fn test_transact_simple ( factory : Factory ) {
2016-01-12 19:11:05 +01:00
let keypair = KeyPair ::create ( ) . unwrap ( ) ;
2016-02-04 23:48:29 +01:00
let t = Transaction {
action : Action ::Create ,
value : U256 ::from ( 17 ) ,
data : " 3331600055 " . from_hex ( ) . unwrap ( ) ,
gas : U256 ::from ( 100_000 ) ,
gas_price : U256 ::zero ( ) ,
nonce : U256 ::zero ( )
2016-07-26 20:31:25 +02:00
} . sign ( keypair . secret ( ) ) ;
2016-01-12 18:31:47 +01:00
let sender = t . sender ( ) . unwrap ( ) ;
2016-01-12 19:43:26 +01:00
let contract = contract_address ( & sender , & U256 ::zero ( ) ) ;
2016-01-12 18:31:47 +01:00
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
state . add_balance ( & sender , & U256 ::from ( 18 ) ) ;
2016-02-02 23:06:34 +01:00
let mut info = EnvInfo ::default ( ) ;
2016-01-12 18:31:47 +01:00
info . gas_limit = U256 ::from ( 100_000 ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-01-12 18:31:47 +01:00
let executed = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
let opts = TransactOptions { check_nonce : true , tracing : false , vm_tracing : false } ;
2016-04-06 13:05:58 +02:00
ex . transact ( & t , opts ) . unwrap ( )
2016-01-12 18:31:47 +01:00
} ;
assert_eq! ( executed . gas , U256 ::from ( 100_000 ) ) ;
2016-01-14 16:40:50 +01:00
assert_eq! ( executed . gas_used , U256 ::from ( 41_301 ) ) ;
assert_eq! ( executed . refunded , U256 ::from ( 58_699 ) ) ;
assert_eq! ( executed . cumulative_gas_used , U256 ::from ( 41_301 ) ) ;
2016-01-12 18:31:47 +01:00
assert_eq! ( executed . logs . len ( ) , 0 ) ;
assert_eq! ( executed . contracts_created . len ( ) , 0 ) ;
2016-01-12 19:43:26 +01:00
assert_eq! ( state . balance ( & sender ) , U256 ::from ( 1 ) ) ;
assert_eq! ( state . balance ( & contract ) , U256 ::from ( 17 ) ) ;
assert_eq! ( state . nonce ( & sender ) , U256 ::from ( 1 ) ) ;
assert_eq! ( state . storage_at ( & contract , & H256 ::new ( ) ) , H256 ::from ( & U256 ::from ( 1 ) ) ) ;
2016-01-12 18:31:47 +01:00
}
2016-01-14 16:17:44 +01:00
evm_test! { test_transact_invalid_sender : test_transact_invalid_sender_jit , test_transact_invalid_sender_int }
fn test_transact_invalid_sender ( factory : Factory ) {
2016-02-04 23:48:29 +01:00
let t = Transaction {
action : Action ::Create ,
value : U256 ::from ( 17 ) ,
data : " 3331600055 " . from_hex ( ) . unwrap ( ) ,
gas : U256 ::from ( 100_000 ) ,
gas_price : U256 ::zero ( ) ,
nonce : U256 ::zero ( )
2016-03-26 13:30:02 +01:00
} . invalid_sign ( ) ;
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
2016-02-02 23:06:34 +01:00
let mut info = EnvInfo ::default ( ) ;
2016-01-12 19:43:26 +01:00
info . gas_limit = U256 ::from ( 100_000 ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-01-12 18:31:47 +01:00
let res = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
let opts = TransactOptions { check_nonce : true , tracing : false , vm_tracing : false } ;
2016-04-06 13:05:58 +02:00
ex . transact ( & t , opts )
2016-01-12 18:31:47 +01:00
} ;
2016-02-09 16:31:57 +01:00
2016-01-12 18:31:47 +01:00
match res {
2016-05-14 14:28:44 +02:00
Err ( ExecutionError ::TransactionMalformed ( _ ) ) = > ( ) ,
_ = > assert! ( false , " Expected an invalid transaction error. " )
2016-01-12 18:31:47 +01:00
}
}
2016-01-14 16:17:44 +01:00
evm_test! { test_transact_invalid_nonce : test_transact_invalid_nonce_jit , test_transact_invalid_nonce_int }
fn test_transact_invalid_nonce ( factory : Factory ) {
2016-01-12 19:11:05 +01:00
let keypair = KeyPair ::create ( ) . unwrap ( ) ;
2016-02-04 23:48:29 +01:00
let t = Transaction {
action : Action ::Create ,
value : U256 ::from ( 17 ) ,
data : " 3331600055 " . from_hex ( ) . unwrap ( ) ,
gas : U256 ::from ( 100_000 ) ,
gas_price : U256 ::zero ( ) ,
nonce : U256 ::one ( )
2016-07-26 20:31:25 +02:00
} . sign ( keypair . secret ( ) ) ;
2016-01-12 19:43:26 +01:00
let sender = t . sender ( ) . unwrap ( ) ;
2016-02-04 23:48:29 +01:00
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
state . add_balance ( & sender , & U256 ::from ( 17 ) ) ;
2016-02-02 23:06:34 +01:00
let mut info = EnvInfo ::default ( ) ;
2016-01-12 19:43:26 +01:00
info . gas_limit = U256 ::from ( 100_000 ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-01-12 19:43:26 +01:00
let res = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
let opts = TransactOptions { check_nonce : true , tracing : false , vm_tracing : false } ;
2016-04-06 13:05:58 +02:00
ex . transact ( & t , opts )
2016-01-12 19:43:26 +01:00
} ;
2016-02-09 16:31:57 +01:00
2016-01-12 19:43:26 +01:00
match res {
2016-05-14 14:28:44 +02:00
Err ( ExecutionError ::InvalidNonce { expected , got } )
2016-02-09 16:31:57 +01:00
if expected = = U256 ::zero ( ) & & got = = U256 ::one ( ) = > ( ) ,
2016-01-12 19:43:26 +01:00
_ = > assert! ( false , " Expected invalid nonce error. " )
}
}
2016-01-14 16:17:44 +01:00
evm_test! { test_transact_gas_limit_reached : test_transact_gas_limit_reached_jit , test_transact_gas_limit_reached_int }
fn test_transact_gas_limit_reached ( factory : Factory ) {
2016-01-12 19:43:26 +01:00
let keypair = KeyPair ::create ( ) . unwrap ( ) ;
2016-02-04 23:48:29 +01:00
let t = Transaction {
action : Action ::Create ,
value : U256 ::from ( 17 ) ,
data : " 3331600055 " . from_hex ( ) . unwrap ( ) ,
gas : U256 ::from ( 80_001 ) ,
gas_price : U256 ::zero ( ) ,
nonce : U256 ::zero ( )
2016-07-26 20:31:25 +02:00
} . sign ( keypair . secret ( ) ) ;
2016-01-12 19:43:26 +01:00
let sender = t . sender ( ) . unwrap ( ) ;
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
state . add_balance ( & sender , & U256 ::from ( 17 ) ) ;
2016-02-02 23:06:34 +01:00
let mut info = EnvInfo ::default ( ) ;
2016-01-12 19:43:26 +01:00
info . gas_used = U256 ::from ( 20_000 ) ;
info . gas_limit = U256 ::from ( 100_000 ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-01-12 19:43:26 +01:00
let res = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
let opts = TransactOptions { check_nonce : true , tracing : false , vm_tracing : false } ;
2016-04-06 13:05:58 +02:00
ex . transact ( & t , opts )
2016-01-12 19:43:26 +01:00
} ;
match res {
2016-05-14 14:28:44 +02:00
Err ( ExecutionError ::BlockGasLimitReached { gas_limit , gas_used , gas } )
2016-02-09 16:31:57 +01:00
if gas_limit = = U256 ::from ( 100_000 ) & & gas_used = = U256 ::from ( 20_000 ) & & gas = = U256 ::from ( 80_001 ) = > ( ) ,
2016-01-12 19:43:26 +01:00
_ = > assert! ( false , " Expected block gas limit error. " )
}
}
2016-01-14 16:17:44 +01:00
evm_test! { test_not_enough_cash : test_not_enough_cash_jit , test_not_enough_cash_int }
fn test_not_enough_cash ( factory : Factory ) {
2016-02-04 23:48:29 +01:00
2016-01-12 19:43:26 +01:00
let keypair = KeyPair ::create ( ) . unwrap ( ) ;
2016-02-04 23:48:29 +01:00
let t = Transaction {
action : Action ::Create ,
value : U256 ::from ( 18 ) ,
data : " 3331600055 " . from_hex ( ) . unwrap ( ) ,
gas : U256 ::from ( 100_000 ) ,
gas_price : U256 ::one ( ) ,
nonce : U256 ::zero ( )
2016-07-26 20:31:25 +02:00
} . sign ( keypair . secret ( ) ) ;
2016-01-12 19:43:26 +01:00
let sender = t . sender ( ) . unwrap ( ) ;
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
state . add_balance ( & sender , & U256 ::from ( 100_017 ) ) ;
2016-02-02 23:06:34 +01:00
let mut info = EnvInfo ::default ( ) ;
2016-01-12 19:43:26 +01:00
info . gas_limit = U256 ::from ( 100_000 ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-01-12 18:31:47 +01:00
let res = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
let opts = TransactOptions { check_nonce : true , tracing : false , vm_tracing : false } ;
2016-04-06 13:05:58 +02:00
ex . transact ( & t , opts )
2016-01-12 18:31:47 +01:00
} ;
2016-02-09 16:31:57 +01:00
2016-01-12 18:31:47 +01:00
match res {
2016-05-14 14:28:44 +02:00
Err ( ExecutionError ::NotEnoughCash { required , got } )
2016-02-09 16:31:57 +01:00
if required = = U512 ::from ( 100_018 ) & & got = = U512 ::from ( 100_017 ) = > ( ) ,
2016-01-13 13:16:53 +01:00
_ = > assert! ( false , " Expected not enough cash error. {:?} " , res )
2016-01-10 16:21:01 +01:00
}
2016-01-09 13:51:59 +01:00
}
2016-01-15 23:32:16 +01:00
evm_test! { test_sha3 : test_sha3_jit , test_sha3_int }
fn test_sha3 ( factory : Factory ) {
let code = " 6064640fffffffff20600055 " . from_hex ( ) . unwrap ( ) ;
let sender = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
let address = contract_address ( & sender , & U256 ::zero ( ) ) ;
// TODO: add tests for 'callcreate'
//let next_address = contract_address(&address, &U256::zero());
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-15 23:32:16 +01:00
params . address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
params . gas = U256 ::from ( 0x0186a0 ) ;
2016-01-16 02:25:08 +01:00
params . code = Some ( code . clone ( ) ) ;
2016-01-20 17:31:37 +01:00
params . value = ActionValue ::Transfer ( U256 ::from_str ( " 0de0b6b3a7640000 " ) . unwrap ( ) ) ;
2016-01-31 10:52:07 +01:00
let mut state_result = get_temp_state ( ) ;
let mut state = state_result . reference_mut ( ) ;
2016-01-15 23:32:16 +01:00
state . add_balance ( & sender , & U256 ::from_str ( " 152d02c7e14af6800000 " ) . unwrap ( ) ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-15 23:32:16 +01:00
let result = {
2016-05-19 00:44:49 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine , & factory ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
2016-01-15 23:32:16 +01:00
} ;
match result {
Err ( _ ) = > {
} ,
_ = > {
panic! ( " Expected OutOfGas " ) ;
}
}
}
2016-01-07 23:33:54 +01:00
}