2016-05-02 12:17:30 +02:00
|
|
|
// Copyright 2015, 2016 Ethcore (UK) Ltd.
|
|
|
|
// This file is part of Parity.
|
|
|
|
|
|
|
|
// Parity is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
|
|
|
// Parity is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
use util::{Address, U256, H256};
|
|
|
|
use ethcore::trace::trace;
|
|
|
|
use ethcore::trace::LocalizedTrace;
|
|
|
|
use v1::types::Bytes;
|
|
|
|
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Create response
|
2016-05-02 12:17:30 +02:00
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
pub struct Create {
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Sender
|
2016-05-02 12:17:30 +02:00
|
|
|
from: Address,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Value
|
2016-05-02 12:17:30 +02:00
|
|
|
value: U256,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Gas
|
2016-05-02 12:17:30 +02:00
|
|
|
gas: U256,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Initialization code
|
2016-05-02 12:17:30 +02:00
|
|
|
init: Bytes,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<trace::Create> for Create {
|
|
|
|
fn from(c: trace::Create) -> Self {
|
|
|
|
Create {
|
|
|
|
from: c.from,
|
|
|
|
value: c.value,
|
|
|
|
gas: c.gas,
|
|
|
|
init: Bytes::new(c.init),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Call response
|
2016-05-02 12:17:30 +02:00
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
pub struct Call {
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Sender
|
2016-05-02 12:17:30 +02:00
|
|
|
from: Address,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Recipient
|
2016-05-02 12:17:30 +02:00
|
|
|
to: Address,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Transfered Value
|
2016-05-02 12:17:30 +02:00
|
|
|
value: U256,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Gas
|
2016-05-02 12:17:30 +02:00
|
|
|
gas: U256,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Input data
|
2016-05-02 12:17:30 +02:00
|
|
|
input: Bytes,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<trace::Call> for Call {
|
|
|
|
fn from(c: trace::Call) -> Self {
|
|
|
|
Call {
|
|
|
|
from: c.from,
|
|
|
|
to: c.to,
|
|
|
|
value: c.value,
|
|
|
|
gas: c.gas,
|
|
|
|
input: Bytes::new(c.input),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Action
|
2016-05-02 12:17:30 +02:00
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
pub enum Action {
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Call
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="call")]
|
|
|
|
Call(Call),
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Create
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="create")]
|
|
|
|
Create(Create),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<trace::Action> for Action {
|
|
|
|
fn from(c: trace::Action) -> Self {
|
|
|
|
match c {
|
|
|
|
trace::Action::Call(call) => Action::Call(Call::from(call)),
|
|
|
|
trace::Action::Create(create) => Action::Create(Create::from(create)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Call Result
|
2016-05-02 12:17:30 +02:00
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
pub struct CallResult {
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Gas used
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="gasUsed")]
|
|
|
|
gas_used: U256,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Output bytes
|
2016-05-02 12:17:30 +02:00
|
|
|
output: Bytes,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<trace::CallResult> for CallResult {
|
|
|
|
fn from(c: trace::CallResult) -> Self {
|
|
|
|
CallResult {
|
|
|
|
gas_used: c.gas_used,
|
|
|
|
output: Bytes::new(c.output),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Craete Result
|
2016-05-02 12:17:30 +02:00
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
pub struct CreateResult {
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Gas used
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="gasUsed")]
|
|
|
|
gas_used: U256,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Code
|
2016-05-02 12:17:30 +02:00
|
|
|
code: Bytes,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Assigned address
|
2016-05-02 12:17:30 +02:00
|
|
|
address: Address,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<trace::CreateResult> for CreateResult {
|
|
|
|
fn from(c: trace::CreateResult) -> Self {
|
|
|
|
CreateResult {
|
|
|
|
gas_used: c.gas_used,
|
|
|
|
code: Bytes::new(c.code),
|
|
|
|
address: c.address,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Response
|
2016-05-02 12:17:30 +02:00
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
pub enum Res {
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Call
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="call")]
|
|
|
|
Call(CallResult),
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Create
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="create")]
|
|
|
|
Create(CreateResult),
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Call failure
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="failedCall")]
|
|
|
|
FailedCall,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Creation failure
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="failedCreate")]
|
|
|
|
FailedCreate,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<trace::Res> for Res {
|
|
|
|
fn from(t: trace::Res) -> Self {
|
|
|
|
match t {
|
|
|
|
trace::Res::Call(call) => Res::Call(CallResult::from(call)),
|
|
|
|
trace::Res::Create(create) => Res::Create(CreateResult::from(create)),
|
|
|
|
trace::Res::FailedCall => Res::FailedCall,
|
|
|
|
trace::Res::FailedCreate => Res::FailedCreate,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Trace
|
2016-05-02 12:17:30 +02:00
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
pub struct Trace {
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Action
|
2016-05-02 12:17:30 +02:00
|
|
|
action: Action,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Result
|
2016-05-02 12:17:30 +02:00
|
|
|
result: Res,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Trace address
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="traceAddress")]
|
|
|
|
trace_address: Vec<U256>,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Subtraces
|
2016-05-02 12:17:30 +02:00
|
|
|
subtraces: U256,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Transaction position
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="transactionPosition")]
|
|
|
|
transaction_position: U256,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Transaction hash
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="transactionHash")]
|
|
|
|
transaction_hash: H256,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Block Number
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="blockNumber")]
|
|
|
|
block_number: U256,
|
2016-05-28 19:30:31 +02:00
|
|
|
/// Block Hash
|
2016-05-02 12:17:30 +02:00
|
|
|
#[serde(rename="blockHash")]
|
|
|
|
block_hash: H256,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<LocalizedTrace> for Trace {
|
|
|
|
fn from(t: LocalizedTrace) -> Self {
|
|
|
|
Trace {
|
|
|
|
action: From::from(t.action),
|
|
|
|
result: From::from(t.result),
|
|
|
|
trace_address: t.trace_address.into_iter().map(From::from).collect(),
|
|
|
|
subtraces: From::from(t.subtraces),
|
|
|
|
transaction_position: From::from(t.transaction_number),
|
|
|
|
transaction_hash: t.transaction_hash,
|
|
|
|
block_number: From::from(t.block_number),
|
|
|
|
block_hash: t.block_hash,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use serde_json;
|
|
|
|
use util::{U256, H256, Address};
|
|
|
|
use v1::types::Bytes;
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_trace_serialize() {
|
|
|
|
let t = Trace {
|
|
|
|
action: Action::Call(Call {
|
|
|
|
from: Address::from(4),
|
|
|
|
to: Address::from(5),
|
|
|
|
value: U256::from(6),
|
|
|
|
gas: U256::from(7),
|
|
|
|
input: Bytes::new(vec![0x12, 0x34]),
|
|
|
|
}),
|
|
|
|
result: Res::Call(CallResult {
|
|
|
|
gas_used: U256::from(8),
|
|
|
|
output: Bytes::new(vec![0x56, 0x78]),
|
|
|
|
}),
|
|
|
|
trace_address: vec![U256::from(10)],
|
|
|
|
subtraces: U256::from(1),
|
|
|
|
transaction_position: U256::from(11),
|
|
|
|
transaction_hash: H256::from(12),
|
|
|
|
block_number: U256::from(13),
|
|
|
|
block_hash: H256::from(14),
|
|
|
|
};
|
|
|
|
let serialized = serde_json::to_string(&t).unwrap();
|
|
|
|
assert_eq!(serialized, r#"{"action":{"call":{"from":"0x0000000000000000000000000000000000000004","to":"0x0000000000000000000000000000000000000005","value":"0x06","gas":"0x07","input":"0x1234"}},"result":{"call":{"gasUsed":"0x08","output":"0x5678"}},"traceAddress":["0x0a"],"subtraces":"0x01","transactionPosition":"0x0b","transactionHash":"0x000000000000000000000000000000000000000000000000000000000000000c","blockNumber":"0x0d","blockHash":"0x000000000000000000000000000000000000000000000000000000000000000e"}"#);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_action_serialize() {
|
|
|
|
let actions = vec![Action::Call(Call {
|
|
|
|
from: Address::from(1),
|
|
|
|
to: Address::from(2),
|
|
|
|
value: U256::from(3),
|
|
|
|
gas: U256::from(4),
|
|
|
|
input: Bytes::new(vec![0x12, 0x34]),
|
|
|
|
}), Action::Create(Create {
|
|
|
|
from: Address::from(5),
|
|
|
|
value: U256::from(6),
|
|
|
|
gas: U256::from(7),
|
|
|
|
init: Bytes::new(vec![0x56, 0x78]),
|
|
|
|
})];
|
|
|
|
|
|
|
|
let serialized = serde_json::to_string(&actions).unwrap();
|
|
|
|
assert_eq!(serialized, r#"[{"call":{"from":"0x0000000000000000000000000000000000000001","to":"0x0000000000000000000000000000000000000002","value":"0x03","gas":"0x04","input":"0x1234"}},{"create":{"from":"0x0000000000000000000000000000000000000005","value":"0x06","gas":"0x07","init":"0x5678"}}]"#);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_result_serialize() {
|
|
|
|
let results = vec![
|
|
|
|
Res::Call(CallResult {
|
|
|
|
gas_used: U256::from(1),
|
|
|
|
output: Bytes::new(vec![0x12, 0x34]),
|
|
|
|
}),
|
|
|
|
Res::Create(CreateResult {
|
|
|
|
gas_used: U256::from(2),
|
|
|
|
code: Bytes::new(vec![0x45, 0x56]),
|
|
|
|
address: Address::from(3),
|
|
|
|
}),
|
|
|
|
Res::FailedCall,
|
|
|
|
Res::FailedCreate,
|
|
|
|
];
|
|
|
|
|
|
|
|
let serialized = serde_json::to_string(&results).unwrap();
|
|
|
|
assert_eq!(serialized, r#"[{"call":{"gasUsed":"0x01","output":"0x1234"}},{"create":{"gasUsed":"0x02","code":"0x4556","address":"0x0000000000000000000000000000000000000003"}},{"failedCall":[]},{"failedCreate":[]}]"#);
|
|
|
|
}
|
|
|
|
}
|