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,
|
T: trace::Tracer,
|
||||||
V: trace::VMTracer,
|
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 original_state = if state_diff { Some(state.clone()) } else { None };
|
||||||
|
|
||||||
let mut ret = Executive::new(state, env_info, engine).transact_virtual(transaction, options)?;
|
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>> {
|
fn epoch_signal(&self, hash: H256) -> Option<Vec<u8>> {
|
||||||
// pending transitions are never deleted, and do not contain
|
// pending transitions are never deleted, and do not contain
|
||||||
// finality proofs by definition.
|
// finality proofs by definition.
|
||||||
|
@ -77,6 +77,8 @@ pub struct TransactOptions<T, V> {
|
|||||||
pub vm_tracer: V,
|
pub vm_tracer: V,
|
||||||
/// Check transaction nonce before execution.
|
/// Check transaction nonce before execution.
|
||||||
pub check_nonce: bool,
|
pub check_nonce: bool,
|
||||||
|
/// Records the output from init contract calls.
|
||||||
|
pub output_from_init_contract: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, V> TransactOptions<T, V> {
|
impl<T, V> TransactOptions<T, V> {
|
||||||
@ -86,6 +88,7 @@ impl<T, V> TransactOptions<T, V> {
|
|||||||
tracer,
|
tracer,
|
||||||
vm_tracer,
|
vm_tracer,
|
||||||
check_nonce: true,
|
check_nonce: true,
|
||||||
|
output_from_init_contract: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +97,12 @@ impl<T, V> TransactOptions<T, V> {
|
|||||||
self.check_nonce = false;
|
self.check_nonce = false;
|
||||||
self
|
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> {
|
impl TransactOptions<trace::ExecutiveTracer, trace::ExecutiveVMTracer> {
|
||||||
@ -103,6 +112,7 @@ impl TransactOptions<trace::ExecutiveTracer, trace::ExecutiveVMTracer> {
|
|||||||
tracer: trace::ExecutiveTracer::default(),
|
tracer: trace::ExecutiveTracer::default(),
|
||||||
vm_tracer: trace::ExecutiveVMTracer::toplevel(),
|
vm_tracer: trace::ExecutiveVMTracer::toplevel(),
|
||||||
check_nonce: true,
|
check_nonce: true,
|
||||||
|
output_from_init_contract: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,6 +124,7 @@ impl TransactOptions<trace::ExecutiveTracer, trace::NoopVMTracer> {
|
|||||||
tracer: trace::ExecutiveTracer::default(),
|
tracer: trace::ExecutiveTracer::default(),
|
||||||
vm_tracer: trace::NoopVMTracer,
|
vm_tracer: trace::NoopVMTracer,
|
||||||
check_nonce: true,
|
check_nonce: true,
|
||||||
|
output_from_init_contract: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,6 +136,7 @@ impl TransactOptions<trace::NoopTracer, trace::ExecutiveVMTracer> {
|
|||||||
tracer: trace::NoopTracer,
|
tracer: trace::NoopTracer,
|
||||||
vm_tracer: trace::ExecutiveVMTracer::toplevel(),
|
vm_tracer: trace::ExecutiveVMTracer::toplevel(),
|
||||||
check_nonce: true,
|
check_nonce: true,
|
||||||
|
output_from_init_contract: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,6 +148,7 @@ impl TransactOptions<trace::NoopTracer, trace::NoopVMTracer> {
|
|||||||
tracer: trace::NoopTracer,
|
tracer: trace::NoopTracer,
|
||||||
vm_tracer: trace::NoopVMTracer,
|
vm_tracer: trace::NoopVMTracer,
|
||||||
check_nonce: true,
|
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>)
|
pub fn transact<T, V>(&'a mut self, t: &SignedTransaction, options: TransactOptions<T, V>)
|
||||||
-> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer,
|
-> 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.
|
/// 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,
|
&'a mut self,
|
||||||
t: &SignedTransaction,
|
t: &SignedTransaction,
|
||||||
check_nonce: bool,
|
check_nonce: bool,
|
||||||
|
output_from_create: bool,
|
||||||
mut tracer: T,
|
mut tracer: T,
|
||||||
mut vm_tracer: V
|
mut vm_tracer: V
|
||||||
) -> Result<Executed, ExecutionError> where T: Tracer, V: VMTracer {
|
) -> 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,
|
data: None,
|
||||||
call_type: CallType::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) => {
|
Action::Call(ref address) => {
|
||||||
let params = ActionParams {
|
let params = ActionParams {
|
||||||
@ -490,6 +505,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
params: ActionParams,
|
params: ActionParams,
|
||||||
substate: &mut Substate,
|
substate: &mut Substate,
|
||||||
|
output: &mut Option<Bytes>,
|
||||||
tracer: &mut T,
|
tracer: &mut T,
|
||||||
vm_tracer: &mut V,
|
vm_tracer: &mut V,
|
||||||
) -> vm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer {
|
) -> 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 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 = {
|
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);
|
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(
|
Ok(ref res) => tracer.trace_create(
|
||||||
trace_info,
|
trace_info,
|
||||||
gas - res.gas_left,
|
gas - res.gas_left,
|
||||||
trace_output,
|
trace_output.map(|data| output.as_ref().map(|out| out.to_vec()).unwrap_or(data)),
|
||||||
created,
|
created,
|
||||||
subtracer.drain()
|
subtracer.drain()
|
||||||
),
|
),
|
||||||
@ -701,7 +717,7 @@ mod tests {
|
|||||||
|
|
||||||
let (gas_left, _) = {
|
let (gas_left, _) = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
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));
|
assert_eq!(gas_left, U256::from(79_975));
|
||||||
@ -759,7 +775,7 @@ mod tests {
|
|||||||
|
|
||||||
let (gas_left, _) = {
|
let (gas_left, _) = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
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));
|
assert_eq!(gas_left, U256::from(62_976));
|
||||||
@ -926,7 +942,7 @@ mod tests {
|
|||||||
|
|
||||||
let (gas_left, _) = {
|
let (gas_left, _) = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
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));
|
assert_eq!(gas_left, U256::from(96_776));
|
||||||
@ -1011,7 +1027,7 @@ mod tests {
|
|||||||
|
|
||||||
let (gas_left, _) = {
|
let (gas_left, _) = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
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));
|
assert_eq!(gas_left, U256::from(62_976));
|
||||||
@ -1062,7 +1078,7 @@ mod tests {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
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);
|
assert_eq!(substate.contracts_created.len(), 1);
|
||||||
@ -1335,7 +1351,7 @@ mod tests {
|
|||||||
|
|
||||||
let result = {
|
let result = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
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 {
|
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);
|
let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth, self.static_flag);
|
||||||
|
|
||||||
// TODO: handle internal error separately
|
// 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, _)) => {
|
Ok((gas_left, _)) => {
|
||||||
self.substate.contracts_created.push(address.clone());
|
self.substate.contracts_created.push(address.clone());
|
||||||
ContractCreateResult::Created(address, gas_left)
|
ContractCreateResult::Created(address, gas_left)
|
||||||
|
@ -355,7 +355,7 @@ impl Spec {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut exec = Executive::new(&mut state, &env_info, self.engine.as_ref());
|
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);
|
warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,8 @@ pub fn check_proof(
|
|||||||
Err(_) => return ProvedExecution::BadProof,
|
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),
|
Ok(executed) => ProvedExecution::Complete(executed),
|
||||||
Err(ExecutionError::Internal(_)) => ProvedExecution::BadProof,
|
Err(ExecutionError::Internal(_)) => ProvedExecution::BadProof,
|
||||||
Err(e) => ProvedExecution::Failed(e),
|
Err(e) => ProvedExecution::Failed(e),
|
||||||
@ -246,7 +247,7 @@ pub fn prove_transaction<H: AsHashDB + Send + Sync>(
|
|||||||
Err(_) => return None,
|
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) {
|
match state.execute(env_info, engine, transaction, options, virt) {
|
||||||
Err(ExecutionError::Internal(_)) => None,
|
Err(ExecutionError::Internal(_)) => None,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user