From 0f324df7c2df1d2ec7233104836fad102ddf49fb Mon Sep 17 00:00:00 2001 From: debris Date: Mon, 23 Jul 2018 12:20:39 +0200 Subject: [PATCH] calculate gas_used of the transaction trace correctly, fixes #9178, fixes #6964 --- ethcore/src/executive.rs | 19 ++++++++--- ethcore/src/externalities.rs | 3 ++ ethcore/src/machine.rs | 1 + ethcore/src/spec/spec.rs | 1 + ethcore/src/state/mod.rs | 56 ++++++++++++++++---------------- ethcore/src/tests/evm.rs | 2 ++ ethcore/src/trace/types/trace.rs | 6 ++-- ethcore/vm/src/action_params.rs | 6 +++- 8 files changed, 58 insertions(+), 36 deletions(-) diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 37dc03dee28..da60c0ea230 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -299,6 +299,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { address: new_address, sender: sender.clone(), origin: sender.clone(), + entire_gas: t.gas, gas: init_gas, gas_price: t.gas_price, value: ActionValue::Transfer(t.value), @@ -316,6 +317,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { address: address.clone(), sender: sender.clone(), origin: sender.clone(), + entire_gas: t.gas, gas: init_gas, gas_price: t.gas_price, value: ActionValue::Transfer(t.value), @@ -469,7 +471,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let mut trace_output = tracer.prepare_trace_output(); let mut subtracer = tracer.subtracer(); - let gas = params.gas; + let entire_gas = params.entire_gas; if params.code.is_some() { // part of substate that may be reverted @@ -490,7 +492,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { match res { Ok(ref res) if res.apply_state => tracer.trace_call( trace_info, - gas - res.gas_left, + entire_gas - res.gas_left, trace_output, traces ), @@ -565,7 +567,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let trace_info = tracer.prepare_trace_create(¶ms); let mut trace_output = tracer.prepare_trace_output(); let mut subtracer = tracer.subtracer(); - let gas = params.gas; + let entire_gas = params.entire_gas; let created = params.address.clone(); 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")); @@ -584,7 +586,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { match res { Ok(ref res) if res.apply_state => tracer.trace_create( trace_info, - gas - res.gas_left, + entire_gas - res.gas_left, trace_output.map(|data| output.as_ref().map(|out| out.to_vec()).unwrap_or(data)), created, subtracer.drain() @@ -750,6 +752,7 @@ mod tests { params.address = address.clone(); params.sender = sender.clone(); params.gas = U256::from(100_000); + params.entire_gas = U256::from(100_000); params.code = Some(Arc::new("3331600055".from_hex().unwrap())); params.value = ActionValue::Transfer(U256::from(0x7)); let mut state = get_temp_state_with_factory(factory); @@ -807,6 +810,7 @@ mod tests { params.sender = sender.clone(); params.origin = sender.clone(); params.gas = U256::from(100_000); + params.entire_gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::from(100)); let mut state = get_temp_state_with_factory(factory); @@ -848,6 +852,7 @@ mod tests { params.sender = sender.clone(); params.origin = sender.clone(); params.gas = U256::from(100_000); + params.entire_gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::from(100)); params.call_type = CallType::Call; @@ -932,6 +937,7 @@ mod tests { params.sender = sender.clone(); params.origin = sender.clone(); params.gas = U256::from(100_000); + params.entire_gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::from(100)); params.call_type = CallType::Call; @@ -1048,6 +1054,7 @@ mod tests { params.sender = sender.clone(); params.origin = sender.clone(); params.gas = U256::from(100_000); + params.entire_gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::from(100)); params.call_type = CallType::Call; @@ -1121,6 +1128,7 @@ mod tests { params.sender = sender.clone(); params.origin = sender.clone(); params.gas = U256::from(100_000); + params.entire_gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(100.into()); let mut state = get_temp_state(); @@ -1208,6 +1216,7 @@ mod tests { params.sender = sender.clone(); params.origin = sender.clone(); params.gas = U256::from(100_000); + params.entire_gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::from(100)); let mut state = get_temp_state_with_factory(factory); @@ -1259,6 +1268,7 @@ mod tests { params.sender = sender.clone(); params.origin = sender.clone(); params.gas = U256::from(100_000); + params.entire_gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::from(100)); let mut state = get_temp_state_with_factory(factory); @@ -1606,6 +1616,7 @@ mod tests { params.sender = sender.clone(); params.address = contract_address.clone(); params.gas = U256::from(20025); + params.entire_gas = U256::from(20025); params.code = Some(wasm_sample_code()); let mut info = EnvInfo::default(); diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index d315122d56a..55be97c8eea 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -160,6 +160,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> value: ActionValue::Apparent(self.origin_info.value), code_address: blockhash_contract_address.clone(), origin: self.origin_info.origin.clone(), + entire_gas: self.machine.params().eip210_contract_gas, gas: self.machine.params().eip210_contract_gas, gas_price: 0.into(), code: code, @@ -208,6 +209,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> address: address.clone(), sender: self.origin_info.address.clone(), origin: self.origin_info.origin.clone(), + entire_gas: *gas, gas: *gas, gas_price: self.origin_info.gas_price, value: ActionValue::Transfer(*value), @@ -267,6 +269,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> value: ActionValue::Apparent(self.origin_info.value), code_address: code_address.clone(), origin: self.origin_info.origin.clone(), + entire_gas: *gas, gas: *gas, gas_price: self.origin_info.gas_price, code: code, diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index dbf66aa1217..b4081516b04 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -136,6 +136,7 @@ impl EthereumMachine { address: contract_address.clone(), sender: SYSTEM_ADDRESS.clone(), origin: SYSTEM_ADDRESS.clone(), + entire_gas: gas, gas: gas, gas_price: 0.into(), value: ActionValue::Transfer(0.into()), diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index d88bdb83364..36fb66ec8f9 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -619,6 +619,7 @@ impl Spec { address: address.clone(), sender: from.clone(), origin: from.clone(), + entire_gas: U256::max_value(), gas: U256::max_value(), gas_price: Default::default(), value: ActionValue::Transfer(Default::default()), diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 0da61425442..eecc1d2ee4f 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -1175,11 +1175,11 @@ mod tests { action: trace::Action::Create(trace::Create { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), value: 100.into(), - gas: 77412.into(), + gas: 100_000.into(), 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], }), result: trace::Res::Create(trace::CreateResult { - gas_used: U256::from(3224), + gas_used: U256::from(25_812), address: Address::from_str("8988167e088c87cd314df6d3c2b83da5acb93ace").unwrap(), code: vec![96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53] }), @@ -1232,7 +1232,7 @@ mod tests { action: trace::Action::Create(trace::Create { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), value: 100.into(), - gas: 78792.into(), + gas: 100_000.into(), init: vec![91, 96, 0, 86], }), result: trace::Res::FailedCreate(TraceError::OutOfGas), @@ -1270,12 +1270,12 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 100.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(3), + gas_used: 21_003.into(), output: vec![] }), subtraces: 0, @@ -1311,7 +1311,7 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 100.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), @@ -1352,7 +1352,7 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: "0000000000000000000000000000000000000001".into(), value: 0.into(), - gas: 79_000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), @@ -1394,12 +1394,12 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 0.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(3_721), // in post-eip150 + gas_used: 24_721.into(), // in post-eip150 output: vec![] }), subtraces: 0, @@ -1438,12 +1438,12 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 0.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: 724.into(), // in post-eip150 + gas_used: 21_724.into(), // in post-eip150 output: vec![] }), }, FlatTrace { @@ -1497,12 +1497,12 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 0.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(736), // in post-eip150 + gas_used: 21_736.into(), // in post-eip150 output: vec![] }), }, FlatTrace { @@ -1553,7 +1553,7 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 100.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), @@ -1595,12 +1595,12 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 100.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(69), + gas_used: 21_069.into(), output: vec![] }), }, FlatTrace { @@ -1652,12 +1652,12 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 100.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(31761), + gas_used: 52_761.into(), output: vec![] }), }, FlatTrace { @@ -1706,12 +1706,12 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 100.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(31761), + gas_used: U256::from(52_761), output: vec![] }), }]; @@ -1749,12 +1749,12 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 100.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(79_000), + gas_used: 100_000.into(), output: vec![] }), }, FlatTrace { @@ -1805,12 +1805,12 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 100.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(135), + gas_used: 21_135.into(), output: vec![] }), }, FlatTrace { @@ -1880,12 +1880,12 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 100.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(79_000), + gas_used: 100_000.into(), output: vec![] }) }, FlatTrace { @@ -1950,12 +1950,12 @@ mod tests { from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), to: 0xa.into(), value: 100.into(), - gas: 79000.into(), + gas: 100_000.into(), input: vec![], call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: 3.into(), + gas_used: 21_003.into(), output: vec![] }), }, FlatTrace { diff --git a/ethcore/src/tests/evm.rs b/ethcore/src/tests/evm.rs index 4f4ad4241f2..dc53d12b05b 100644 --- a/ethcore/src/tests/evm.rs +++ b/ethcore/src/tests/evm.rs @@ -53,6 +53,7 @@ fn test_blockhash_eip210(factory: Factory) { address: contract_address, sender: SYSTEM_ADDRESS.clone(), origin: SYSTEM_ADDRESS.clone(), + entire_gas: 100000.into(), gas: 100000.into(), gas_price: 0.into(), value: ActionValue::Transfer(0.into()), @@ -76,6 +77,7 @@ fn test_blockhash_eip210(factory: Factory) { address: Address::new(), sender: Address::new(), origin: Address::new(), + entire_gas: 100000.into(), gas: 100000.into(), gas_price: 0.into(), value: ActionValue::Transfer(0.into()), diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index 1dde16e23ba..cdb3038277a 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -75,7 +75,7 @@ impl From for Call { from: p.address, to: p.code_address, value: p.value.value(), - gas: p.gas, + gas: p.entire_gas, input: p.data.unwrap_or_else(Vec::new), call_type: p.call_type, }, @@ -83,7 +83,7 @@ impl From for Call { from: p.sender, to: p.address, value: p.value.value(), - gas: p.gas, + gas: p.entire_gas, input: p.data.unwrap_or_else(Vec::new), call_type: p.call_type, }, @@ -120,7 +120,7 @@ impl From for Create { Create { from: p.sender, value: p.value.value(), - gas: p.gas, + gas: p.entire_gas, init: p.code.map_or_else(Vec::new, |c| (*c).clone()), } } diff --git a/ethcore/vm/src/action_params.rs b/ethcore/vm/src/action_params.rs index 481f6373104..7112e9ec633 100644 --- a/ethcore/vm/src/action_params.rs +++ b/ethcore/vm/src/action_params.rs @@ -76,7 +76,9 @@ pub struct ActionParams { pub sender: Address, /// Transaction initiator. pub origin: Address, - /// Gas paid up front for transaction execution + /// Gas paid up front for entire transaction execution. + pub entire_gas: U256, + /// Gas paid up front for action execution. pub gas: U256, /// Gas price. pub gas_price: U256, @@ -101,6 +103,7 @@ impl Default for ActionParams { address: Address::new(), sender: Address::new(), origin: Address::new(), + entire_gas: U256::zero(), gas: U256::zero(), gas_price: U256::zero(), value: ActionValue::Transfer(U256::zero()), @@ -123,6 +126,7 @@ impl From for ActionParams { origin: t.origin.into(), code: Some(Arc::new(t.code.into())), data: Some(t.data.into()), + entire_gas: t.gas.into(), gas: t.gas.into(), gas_price: t.gas_price.into(), value: ActionValue::Transfer(t.value.into()),