eth_call returns output of contract creations (#6420)
* eth_call returns output of contract creations * Fix parameters order. * Save outputs for light client as well.
This commit is contained in:
parent
c49beccadc
commit
7462a69583
@ -1131,7 +1131,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)?;
|
||||
@ -2001,6 +2003,7 @@ impl ProvingBlockChainClient for Client {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
fn epoch_signal(&self, hash: H256) -> Option<Vec<u8>> {
|
||||
// pending transitions are never deleted, and do not contain
|
||||
// finality proofs by definition.
|
||||
|
@ -77,6 +77,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> {
|
||||
@ -86,6 +88,7 @@ impl<T, V> TransactOptions<T, V> {
|
||||
tracer,
|
||||
vm_tracer,
|
||||
check_nonce: true,
|
||||
output_from_init_contract: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,6 +97,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> {
|
||||
@ -103,6 +112,7 @@ impl TransactOptions<trace::ExecutiveTracer, trace::ExecutiveVMTracer> {
|
||||
tracer: trace::ExecutiveTracer::default(),
|
||||
vm_tracer: trace::ExecutiveVMTracer::toplevel(),
|
||||
check_nonce: true,
|
||||
output_from_init_contract: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,6 +124,7 @@ impl TransactOptions<trace::ExecutiveTracer, trace::NoopVMTracer> {
|
||||
tracer: trace::ExecutiveTracer::default(),
|
||||
vm_tracer: trace::NoopVMTracer,
|
||||
check_nonce: true,
|
||||
output_from_init_contract: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -125,6 +136,7 @@ impl TransactOptions<trace::NoopTracer, trace::ExecutiveVMTracer> {
|
||||
tracer: trace::NoopTracer,
|
||||
vm_tracer: trace::ExecutiveVMTracer::toplevel(),
|
||||
check_nonce: true,
|
||||
output_from_init_contract: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -136,6 +148,7 @@ impl TransactOptions<trace::NoopTracer, trace::NoopVMTracer> {
|
||||
tracer: trace::NoopTracer,
|
||||
vm_tracer: trace::NoopVMTracer,
|
||||
check_nonce: true,
|
||||
output_from_init_contract: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -204,7 +217,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.
|
||||
@ -229,6 +242,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 {
|
||||
@ -297,7 +311,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 {
|
||||
@ -490,6 +505,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 {
|
||||
@ -531,7 +547,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)
|
||||
};
|
||||
|
||||
vm_tracer.done_subtrace(subvmtracer);
|
||||
@ -540,7 +556,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()
|
||||
),
|
||||
@ -701,7 +717,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));
|
||||
@ -759,7 +775,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));
|
||||
@ -926,7 +942,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));
|
||||
@ -1011,7 +1027,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));
|
||||
@ -1062,7 +1078,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);
|
||||
@ -1335,7 +1351,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 {
|
||||
|
@ -224,7 +224,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)
|
||||
|
@ -355,7 +355,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);
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +212,8 @@ pub fn check_proof(
|
||||
Err(_) => return ProvedExecution::BadProof,
|
||||
};
|
||||
|
||||
match state.execute(env_info, engine, transaction, TransactOptions::with_no_tracing(), true) {
|
||||
let options = TransactOptions::with_no_tracing().save_output_from_contract();
|
||||
match state.execute(env_info, engine, transaction, options, true) {
|
||||
Ok(executed) => ProvedExecution::Complete(executed),
|
||||
Err(ExecutionError::Internal(_)) => ProvedExecution::BadProof,
|
||||
Err(e) => ProvedExecution::Failed(e),
|
||||
@ -246,7 +247,7 @@ pub fn prove_transaction<H: AsHashDB + Send + Sync>(
|
||||
Err(_) => return None,
|
||||
};
|
||||
|
||||
let options = TransactOptions::with_no_tracing().dont_check_nonce();
|
||||
let options = TransactOptions::with_no_tracing().dont_check_nonce().save_output_from_contract();
|
||||
match state.execute(env_info, engine, transaction, options, virt) {
|
||||
Err(ExecutionError::Internal(_)) => None,
|
||||
Err(e) => {
|
||||
|
Loading…
Reference in New Issue
Block a user