From 924941432be77d51460293d7f7805641b40921f4 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 28 Sep 2016 11:56:36 +0200 Subject: [PATCH 1/6] Fix the traceAddress field in transaction traces. --- ethcore/src/trace/executive_tracer.rs | 39 +++++++++++---------------- rpc/src/v1/types/trace.rs | 12 ++++----- 2 files changed, 22 insertions(+), 29 deletions(-) diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index b086b237873..02e74a2fc2a 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -31,7 +31,7 @@ fn top_level_subtraces(traces: &[FlatTrace]) -> usize { traces.iter().filter(|t| t.trace_address.is_empty()).count() } -fn update_trace_address(traces: Vec) -> Vec { +fn prefix_subtrace_addresses(mut traces: Vec) -> Vec { // input traces are expected to be ordered like // [] // [0] @@ -48,24 +48,17 @@ fn update_trace_address(traces: Vec) -> Vec { // [0, 0, 1] // [1] // [1, 0] - let mut top_subtrace_index = 0; - let mut subtrace_subtraces_left = 0; - traces.into_iter().map(|mut trace| { - let is_top_subtrace = trace.trace_address.is_empty(); - let is_subtrace = trace.trace_address.len() == 1; - trace.trace_address.push_front(top_subtrace_index); - - if is_top_subtrace { - subtrace_subtraces_left = trace.subtraces; - } else if is_subtrace { - subtrace_subtraces_left -= 1; - } - - if subtrace_subtraces_left == 0 { - top_subtrace_index += 1; - } - trace - }).collect() + let mut current_subtrace_index = 0; + let mut first = true; + for trace in traces.iter_mut() { + match (first, trace.trace_address.is_empty()) { + (true, _) => first = false, + (_, true) => current_subtrace_index += 1, + _ => {} + } + trace.trace_address.push_front(current_subtrace_index); + } + traces } impl Tracer for ExecutiveTracer { @@ -93,7 +86,7 @@ impl Tracer for ExecutiveTracer { }; debug!(target: "trace", "Traced call {:?}", trace); self.traces.push(trace); - self.traces.extend(update_trace_address(subs)); + self.traces.extend(prefix_subtrace_addresses(subs)); } fn trace_create(&mut self, create: Option, gas_used: U256, code: Option, address: Address, subs: Vec) { @@ -109,7 +102,7 @@ impl Tracer for ExecutiveTracer { }; debug!(target: "trace", "Traced create {:?}", trace); self.traces.push(trace); - self.traces.extend(update_trace_address(subs)); + self.traces.extend(prefix_subtrace_addresses(subs)); } fn trace_failed_call(&mut self, call: Option, subs: Vec, error: TraceError) { @@ -121,7 +114,7 @@ impl Tracer for ExecutiveTracer { }; debug!(target: "trace", "Traced failed call {:?}", trace); self.traces.push(trace); - self.traces.extend(update_trace_address(subs)); + self.traces.extend(prefix_subtrace_addresses(subs)); } fn trace_failed_create(&mut self, create: Option, subs: Vec, error: TraceError) { @@ -133,7 +126,7 @@ impl Tracer for ExecutiveTracer { }; debug!(target: "trace", "Traced failed create {:?}", trace); self.traces.push(trace); - self.traces.extend(update_trace_address(subs)); + self.traces.extend(prefix_subtrace_addresses(subs)); } fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address) { diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index f66d8e0c10a..27ae1ebe1dd 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -414,15 +414,15 @@ pub struct LocalizedTrace { /// Result result: Res, /// Trace address - trace_address: Vec, + trace_address: Vec, /// Subtraces - subtraces: U256, + subtraces: usize, /// Transaction position - transaction_position: U256, + transaction_position: usize, /// Transaction hash transaction_hash: H256, /// Block Number - block_number: U256, + block_number: u64, /// Block Hash block_hash: H256, } @@ -485,9 +485,9 @@ impl From for LocalizedTrace { #[derive(Debug)] pub struct Trace { /// Trace address - trace_address: Vec, + trace_address: Vec, /// Subtraces - subtraces: U256, + subtraces: usize, /// Action action: Action, /// Result From d76dbae3d4be912541f20ff5e624c26778c0388b Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 28 Sep 2016 12:20:46 +0200 Subject: [PATCH 2/6] Add test --- ethcore/src/trace/executive_tracer.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index 02e74a2fc2a..2bc8979250e 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -61,6 +61,25 @@ fn prefix_subtrace_addresses(mut traces: Vec) -> Vec { traces } +#[test] +fn should_prefix_address_properly() { + use super::trace::{Action, Res, Suicide}; + + let f = |v: Vec| FlatTrace { + action: Action::Suicide(Suicide { + address: Default::default(), + balance: Default::default(), + refund_address: Default::default(), + }), + result: Res::None, + subtraces: 0, + trace_address: v.into_iter().collect(), + }; + let mut t = vec![vec![], vec![0], vec![0, 0], vec![0], vec![], vec![], vec![0], vec![]].into_iter().map(&f).collect(); + let t = prefix_subtrace_addresses(t); + assert_eq!(t, vec![vec![0], vec![0, 0], vec![0, 0, 0], vec![0, 0], vec![1], vec![2], vec![2, 0], vec![3]].into_iter().map(&f).collect::>()); +} + impl Tracer for ExecutiveTracer { fn prepare_trace_call(&self, params: &ActionParams) -> Option { Some(Call::from(params.clone())) From 41514dc7af8d8cf128e9513fff9192fa4b78caef Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 28 Sep 2016 12:28:13 +0200 Subject: [PATCH 3/6] Fix warning. --- ethcore/src/trace/executive_tracer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index 2bc8979250e..ca9bc30b51d 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -75,7 +75,7 @@ fn should_prefix_address_properly() { subtraces: 0, trace_address: v.into_iter().collect(), }; - let mut t = vec![vec![], vec![0], vec![0, 0], vec![0], vec![], vec![], vec![0], vec![]].into_iter().map(&f).collect(); + let t = vec![vec![], vec![0], vec![0, 0], vec![0], vec![], vec![], vec![0], vec![]].into_iter().map(&f).collect(); let t = prefix_subtrace_addresses(t); assert_eq!(t, vec![vec![0], vec![0, 0], vec![0, 0, 0], vec![0, 0], vec![1], vec![2], vec![2, 0], vec![3]].into_iter().map(&f).collect::>()); } From 50f7af2b83bfbce2ac39ed38ad2f3a8130a41db6 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 28 Sep 2016 14:06:03 +0200 Subject: [PATCH 4/6] Fix test --- rpc/src/v1/types/trace.rs | 44 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index 27ae1ebe1dd..c83911c86f5 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -601,11 +601,11 @@ mod tests { gas_used: 8.into(), output: vec![0x56, 0x78].into(), }), - trace_address: vec![10.into()], - subtraces: 1.into(), - transaction_position: 11.into(), + trace_address: vec![10], + subtraces: 1, + transaction_position: 11, transaction_hash: 12.into(), - block_number: 13.into(), + block_number: 13, block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); @@ -624,11 +624,11 @@ mod tests { call_type: CallType::Call, }), result: Res::FailedCall(TraceError::OutOfGas), - trace_address: vec![10.into()], - subtraces: 1.into(), - transaction_position: 11.into(), + trace_address: vec![10], + subtraces: 1, + transaction_position: 11, transaction_hash: 12.into(), - block_number: 13.into(), + block_number: 13, block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); @@ -649,11 +649,11 @@ mod tests { code: vec![0x56, 0x78].into(), address: 0xff.into(), }), - trace_address: vec![10.into()], - subtraces: 1.into(), - transaction_position: 11.into(), + trace_address: vec![10], + subtraces: 1, + transaction_position: 11, transaction_hash: 12.into(), - block_number: 13.into(), + block_number: 13, block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); @@ -670,11 +670,11 @@ mod tests { init: Bytes::new(vec![0x12, 0x34]), }), result: Res::FailedCreate(TraceError::OutOfGas), - trace_address: vec![10.into()], - subtraces: 1.into(), - transaction_position: 11.into(), + trace_address: vec![10], + subtraces: 1, + transaction_position: 11, transaction_hash: 12.into(), - block_number: 13.into(), + block_number: 13, block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); @@ -690,11 +690,11 @@ mod tests { balance: 7.into(), }), result: Res::None, - trace_address: vec![10.into()], - subtraces: 1.into(), - transaction_position: 11.into(), + trace_address: vec![10], + subtraces: 1, + transaction_position: 11, transaction_hash: 12.into(), - block_number: 13.into(), + block_number: 13, block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); @@ -749,7 +749,7 @@ mod tests { let t = StateDiff(map![ 42.into() => AccountDiff { balance: Diff::Same, - nonce: Diff::Born(1.into()), + nonce: Diff::Born(1), code: Diff::Same, storage: map![ 42.into() => Diff::Same @@ -757,7 +757,7 @@ mod tests { }, 69.into() => AccountDiff { balance: Diff::Same, - nonce: Diff::Changed(ChangedType { from: 1.into(), to: 0.into() }), + nonce: Diff::Changed(ChangedType { from: 1, to: 0.into() }), code: Diff::Died(vec![96].into()), storage: map![], } From 4a51fa3d6f03b082075066712f8e6b2445cad2f9 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 28 Sep 2016 14:08:41 +0200 Subject: [PATCH 5/6] Additional fix. --- rpc/src/v1/types/trace.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index c83911c86f5..107e9101162 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -749,7 +749,7 @@ mod tests { let t = StateDiff(map![ 42.into() => AccountDiff { balance: Diff::Same, - nonce: Diff::Born(1), + nonce: Diff::Born(1.into()), code: Diff::Same, storage: map![ 42.into() => Diff::Same @@ -757,7 +757,7 @@ mod tests { }, 69.into() => AccountDiff { balance: Diff::Same, - nonce: Diff::Changed(ChangedType { from: 1, to: 0.into() }), + nonce: Diff::Changed(ChangedType { from: 1.into(), to: 0.into() }), code: Diff::Died(vec![96].into()), storage: map![], } From fb52e81492a878e822279813112956fcd9cef264 Mon Sep 17 00:00:00 2001 From: Gav Wood Date: Wed, 28 Sep 2016 14:12:17 +0200 Subject: [PATCH 6/6] Fix tests content. --- rpc/src/v1/types/trace.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rpc/src/v1/types/trace.rs b/rpc/src/v1/types/trace.rs index 107e9101162..ace76827c04 100644 --- a/rpc/src/v1/types/trace.rs +++ b/rpc/src/v1/types/trace.rs @@ -609,7 +609,7 @@ mod tests { block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"type":"call","action":{"from":"0x0000000000000000000000000000000000000004","to":"0x0000000000000000000000000000000000000005","value":"0x6","gas":"0x7","input":"0x1234","callType":"call"},"result":{"gasUsed":"0x8","output":"0x5678"},"traceAddress":["0xa"],"subtraces":"0x1","transactionPosition":"0xb","transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":"0xd","blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + assert_eq!(serialized, r#"{"type":"call","action":{"from":"0x0000000000000000000000000000000000000004","to":"0x0000000000000000000000000000000000000005","value":"0x6","gas":"0x7","input":"0x1234","callType":"call"},"result":{"gasUsed":"0x8","output":"0x5678"},"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); } #[test] @@ -632,7 +632,7 @@ mod tests { block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"type":"call","action":{"from":"0x0000000000000000000000000000000000000004","to":"0x0000000000000000000000000000000000000005","value":"0x6","gas":"0x7","input":"0x1234","callType":"call"},"error":"Out of gas","traceAddress":["0xa"],"subtraces":"0x1","transactionPosition":"0xb","transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":"0xd","blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + assert_eq!(serialized, r#"{"type":"call","action":{"from":"0x0000000000000000000000000000000000000004","to":"0x0000000000000000000000000000000000000005","value":"0x6","gas":"0x7","input":"0x1234","callType":"call"},"error":"Out of gas","traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); } #[test] @@ -657,7 +657,7 @@ mod tests { block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"type":"create","action":{"from":"0x0000000000000000000000000000000000000004","value":"0x6","gas":"0x7","init":"0x1234"},"result":{"gasUsed":"0x8","code":"0x5678","address":"0x00000000000000000000000000000000000000ff"},"traceAddress":["0xa"],"subtraces":"0x1","transactionPosition":"0xb","transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":"0xd","blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + assert_eq!(serialized, r#"{"type":"create","action":{"from":"0x0000000000000000000000000000000000000004","value":"0x6","gas":"0x7","init":"0x1234"},"result":{"gasUsed":"0x8","code":"0x5678","address":"0x00000000000000000000000000000000000000ff"},"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); } #[test] @@ -678,7 +678,7 @@ mod tests { block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"type":"create","action":{"from":"0x0000000000000000000000000000000000000004","value":"0x6","gas":"0x7","init":"0x1234"},"error":"Out of gas","traceAddress":["0xa"],"subtraces":"0x1","transactionPosition":"0xb","transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":"0xd","blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + assert_eq!(serialized, r#"{"type":"create","action":{"from":"0x0000000000000000000000000000000000000004","value":"0x6","gas":"0x7","init":"0x1234"},"error":"Out of gas","traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); } #[test] @@ -698,7 +698,7 @@ mod tests { block_hash: 14.into(), }; let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"type":"suicide","action":{"address":"0x0000000000000000000000000000000000000004","refundAddress":"0x0000000000000000000000000000000000000006","balance":"0x7"},"result":null,"traceAddress":["0xa"],"subtraces":"0x1","transactionPosition":"0xb","transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":"0xd","blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); + assert_eq!(serialized, r#"{"type":"suicide","action":{"address":"0x0000000000000000000000000000000000000004","refundAddress":"0x0000000000000000000000000000000000000006","balance":"0x7"},"result":null,"traceAddress":[10],"subtraces":1,"transactionPosition":11,"transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":13,"blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#); } #[test]