diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index a45577322..2c1d7b023 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -249,6 +249,8 @@ impl<'a> Executive<'a> { // part of substate that may be reverted let mut unconfirmed_substate = Substate::new(substate.subtraces.is_some()); + + // transaction tracing stuff. None if there's no tracing. let mut trace_info = substate.subtraces.as_ref().map(|_| (TraceAction::from_call(¶ms), self.depth)); let mut trace_output = trace_info.as_ref().map(|_| vec![]); @@ -256,6 +258,7 @@ impl<'a> Executive<'a> { self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut())) }; + // if there's tracing, make up trace_info's result with trace_output and some arithmetic. if let Some((TraceAction::Call(ref mut c), _)) = trace_info { if let Some(output) = trace_output { c.result = res.as_ref().ok().map(|gas_left| (c.gas - *gas_left, output)); @@ -295,14 +298,17 @@ impl<'a> Executive<'a> { } let mut trace_info = substate.subtraces.as_ref().map(|_| (TraceAction::from_create(¶ms), self.depth)); + let mut trace_output = trace_info.as_ref().map(|_| vec![]); let created = params.address.clone(); let res = { - self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract) + self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract(trace_output.as_mut())) }; if let Some((TraceAction::Create(ref mut c), _)) = trace_info { - c.result = res.as_ref().ok().map(|gas_left| (c.gas - *gas_left, created, vec![])); + if let Some(output) = trace_output { + c.result = res.as_ref().ok().map(|gas_left| (c.gas - *gas_left, created, output)); + } } self.enact_result(&res, substate, unconfirmed_substate, trace_info); diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index b0ba67602..6e9605354 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -28,7 +28,7 @@ pub enum OutputPolicy<'a, 'b> { /// Used for message calls. Return(BytesRef<'a>, Option<&'b mut Bytes>), /// Init new contract as soon as `RETURN` is called. - InitContract, + InitContract(Option<&'b mut Bytes>), } /// Transaction properties that externalities need to know about. @@ -213,7 +213,7 @@ impl<'a> Ext for Externalities<'a> { } Ok(*gas) }, - OutputPolicy::InitContract => { + OutputPolicy::InitContract(ref mut copy) => { let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas); if return_cost > *gas { return match self.schedule.exceptional_failed_code_deposit { @@ -221,6 +221,9 @@ impl<'a> Ext for Externalities<'a> { false => Ok(*gas) } } + + handle_copy(copy); + let mut code = vec![]; code.reserve(data.len()); unsafe { @@ -333,7 +336,7 @@ mod tests { let mut setup = TestSetup::new(); let state = setup.state.reference_mut(); - let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract); + let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None)); assert_eq!(ext.env_info().number, 100); } @@ -342,7 +345,7 @@ mod tests { fn can_return_block_hash_no_env() { let mut setup = TestSetup::new(); let state = setup.state.reference_mut(); - let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract); + let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None)); let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap()); @@ -361,7 +364,7 @@ mod tests { env_info.last_hashes.push(test_hash.clone()); } let state = setup.state.reference_mut(); - let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract); + let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None)); let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap()); @@ -373,7 +376,7 @@ mod tests { fn can_call_fail_empty() { let mut setup = TestSetup::new(); let state = setup.state.reference_mut(); - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract); + let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None)); let mut output = vec![]; @@ -397,7 +400,7 @@ mod tests { let state = setup.state.reference_mut(); { - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract); + let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None)); ext.log(log_topics, &log_data); } @@ -412,7 +415,7 @@ mod tests { let state = setup.state.reference_mut(); { - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract); + let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None)); ext.suicide(&refund_account); }