Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

eth_call returns output of contract creations #6420

Merged
merged 5 commits into from
Sep 5, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,9 @@ impl Client {
T: trace::Tracer,
V: trace::VMTracer,
{
let options = options.dont_check_nonce();
let options = options
.dont_check_nonce()
.save_output_from_contract();
let original_state = if state_diff { Some(state.clone()) } else { None };

let mut ret = Executive::new(state, env_info, engine).transact_virtual(transaction, options)?;
Expand Down
36 changes: 26 additions & 10 deletions ethcore/src/executive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ pub struct TransactOptions<T, V> {
pub vm_tracer: V,
/// Check transaction nonce before execution.
pub check_nonce: bool,
/// Records the output from init contract calls.
pub output_from_init_contract: bool,
}

impl<T, V> TransactOptions<T, V> {
Expand All @@ -83,6 +85,7 @@ impl<T, V> TransactOptions<T, V> {
tracer,
vm_tracer,
check_nonce: true,
output_from_init_contract: false,
}
}

Expand All @@ -91,6 +94,12 @@ impl<T, V> TransactOptions<T, V> {
self.check_nonce = false;
self
}

/// Saves the output from contract creation.
pub fn save_output_from_contract(mut self) -> Self {
self.output_from_init_contract = true;
self
}
}

impl TransactOptions<trace::ExecutiveTracer, trace::ExecutiveVMTracer> {
Expand All @@ -100,6 +109,7 @@ impl TransactOptions<trace::ExecutiveTracer, trace::ExecutiveVMTracer> {
tracer: trace::ExecutiveTracer::default(),
vm_tracer: trace::ExecutiveVMTracer::toplevel(),
check_nonce: true,
output_from_init_contract: false,
}
}
}
Expand All @@ -111,6 +121,7 @@ impl TransactOptions<trace::ExecutiveTracer, trace::NoopVMTracer> {
tracer: trace::ExecutiveTracer::default(),
vm_tracer: trace::NoopVMTracer,
check_nonce: true,
output_from_init_contract: false,
}
}
}
Expand All @@ -122,6 +133,7 @@ impl TransactOptions<trace::NoopTracer, trace::ExecutiveVMTracer> {
tracer: trace::NoopTracer,
vm_tracer: trace::ExecutiveVMTracer::toplevel(),
check_nonce: true,
output_from_init_contract: false,
}
}
}
Expand All @@ -133,6 +145,7 @@ impl TransactOptions<trace::NoopTracer, trace::NoopVMTracer> {
tracer: trace::NoopTracer,
vm_tracer: trace::NoopVMTracer,
check_nonce: true,
output_from_init_contract: false,
}
}
}
Expand Down Expand Up @@ -201,7 +214,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
pub fn transact<T, V>(&'a mut self, t: &SignedTransaction, options: TransactOptions<T, V>)
-> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer,
{
self.transact_with_tracer(t, options.check_nonce, options.tracer, options.vm_tracer)
self.transact_with_tracer(t, options.check_nonce, options.output_from_init_contract, options.tracer, options.vm_tracer)
}

/// Execute a transaction in a "virtual" context.
Expand All @@ -226,6 +239,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
&'a mut self,
t: &SignedTransaction,
check_nonce: bool,
output_from_create: bool,
mut tracer: T,
mut vm_tracer: V
) -> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer {
Expand Down Expand Up @@ -294,7 +308,8 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
data: None,
call_type: CallType::None,
};
(self.create(params, &mut substate, &mut tracer, &mut vm_tracer), vec![])
let mut out = if output_from_create { Some(vec![]) } else { None };
(self.create(params, &mut substate, &mut out, &mut tracer, &mut vm_tracer), out.unwrap_or_else(Vec::new))
},
Action::Call(ref address) => {
let params = ActionParams {
Expand Down Expand Up @@ -487,6 +502,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
&mut self,
params: ActionParams,
substate: &mut Substate,
output: &mut Option<Bytes>,
tracer: &mut T,
vm_tracer: &mut V,
) -> vm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer {
Expand Down Expand Up @@ -528,7 +544,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
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"));

let res = {
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract(trace_output.as_mut()), &mut subtracer, &mut subvmtracer)
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract(output.as_mut().or(trace_output.as_mut())), &mut subtracer, &mut subvmtracer)
Copy link
Contributor

@rphmeier rphmeier Sep 4, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this mean that whenever saving creation output, trace output won't be saved? the two settings aren't used together yet, but something to watch out for

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Because trace_output is always the same as output (if both are selected) we just re-use the same value to get it. Couple of lines below this you can see that trace_output is copied either from output or trace_output.

};

vm_tracer.done_subtrace(subvmtracer);
Expand All @@ -537,7 +553,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
Ok(ref res) => tracer.trace_create(
trace_info,
gas - res.gas_left,
trace_output,
trace_output.map(|data| output.as_ref().map(|out| out.to_vec()).unwrap_or(data)),
created,
subtracer.drain()
),
Expand Down Expand Up @@ -696,7 +712,7 @@ mod tests {

let (gas_left, _) = {
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};

assert_eq!(gas_left, U256::from(79_975));
Expand Down Expand Up @@ -754,7 +770,7 @@ mod tests {

let (gas_left, _) = {
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};

assert_eq!(gas_left, U256::from(62_976));
Expand Down Expand Up @@ -921,7 +937,7 @@ mod tests {

let (gas_left, _) = {
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params.clone(), &mut substate, &mut tracer, &mut vm_tracer).unwrap()
ex.create(params.clone(), &mut substate, &mut None, &mut tracer, &mut vm_tracer).unwrap()
};

assert_eq!(gas_left, U256::from(96_776));
Expand Down Expand Up @@ -1006,7 +1022,7 @@ mod tests {

let (gas_left, _) = {
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};

assert_eq!(gas_left, U256::from(62_976));
Expand Down Expand Up @@ -1057,7 +1073,7 @@ mod tests {

{
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap();
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap();
}

assert_eq!(substate.contracts_created.len(), 1);
Expand Down Expand Up @@ -1330,7 +1346,7 @@ mod tests {

let result = {
let mut ex = Executive::new(&mut state, &info, &engine);
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer)
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer)
};

match result {
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/externalities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth, self.static_flag);

// TODO: handle internal error separately
match ex.create(params, self.substate, self.tracer, self.vm_tracer) {
match ex.create(params, self.substate, &mut None, self.tracer, self.vm_tracer) {
Ok((gas_left, _)) => {
self.substate.contracts_created.push(address.clone());
ContractCreateResult::Created(address, gas_left)
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/spec/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ impl Spec {

{
let mut exec = Executive::new(&mut state, &env_info, self.engine.as_ref());
if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) {
if let Err(e) = exec.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer) {
warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e);
}
}
Expand Down