Moving all Client public API types to separate mod & binary serialization codegen for that mod (#1051)

* transaction moved

* trash remove

* ids move

* receipt

* tree-route

* blockchain info

* log_entry move

* trace filter moved

* executed & trace moved

* localized trace moved

* block status moved

* build scripts and codegen refs

* Cargo.lock update

* binary for blockstatus, blockchaininfo

* binary for trace

* trace filters binary ser

* binary for log entries & executed

* binary for receipt

* special case for u8 & transaction binary attribute

* resolved remaining issues & error binary serialization

* json-tests util import

* fix warnings

* ids attr

* add missing attributes

* Update build.rs
This commit is contained in:
Nikolay Volf
2016-05-16 19:33:32 +03:00
committed by Gav Wood
parent 9301963d98
commit 4e41cbca81
32 changed files with 503 additions and 192 deletions

View File

@@ -1,283 +0,0 @@
// 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 std::ops::Range;
use bloomchain::{Filter as BloomFilter, Bloom, Number};
use util::{Address, FixedHash};
use util::sha3::Hashable;
use basic_types::LogBloom;
use super::flat::FlatTrace;
use super::trace::Action;
/// Addresses filter.
///
/// Used to create bloom possibilities and match filters.
pub struct AddressesFilter(Vec<Address>);
impl From<Vec<Address>> for AddressesFilter {
fn from(addresses: Vec<Address>) -> Self {
AddressesFilter(addresses)
}
}
impl AddressesFilter {
/// Returns true if address matches one of the searched addresses.
pub fn matches(&self, address: &Address) -> bool {
self.matches_all() || self.0.contains(address)
}
/// Returns true if this address filter matches everything.
pub fn matches_all(&self) -> bool {
self.0.is_empty()
}
/// Returns blooms of this addresses filter.
pub fn blooms(&self) -> Vec<LogBloom> {
match self.0.is_empty() {
true => vec![LogBloom::new()],
false => self.0.iter()
.map(|address| LogBloom::from_bloomed(&address.sha3()))
.collect()
}
}
/// Returns vector of blooms zipped with blooms of this addresses filter.
pub fn with_blooms(&self, blooms: Vec<LogBloom>) -> Vec<LogBloom> {
match self.0.is_empty() {
true => blooms,
false => blooms
.into_iter()
.flat_map(|bloom| self.0.iter()
.map(|address| bloom.with_bloomed(&address.sha3()))
.collect::<Vec<_>>())
.collect()
}
}
}
/// Traces filter.
pub struct Filter {
/// Block range.
pub range: Range<usize>,
/// From address filter.
pub from_address: AddressesFilter,
/// To address filter.
pub to_address: AddressesFilter,
}
impl BloomFilter for Filter {
fn bloom_possibilities(&self) -> Vec<Bloom> {
self.bloom_possibilities()
.into_iter()
.map(|b| Bloom::from(b.0))
.collect()
}
fn range(&self) -> Range<Number> {
self.range.clone()
}
}
impl Filter {
/// Returns combinations of each address.
fn bloom_possibilities(&self) -> Vec<LogBloom> {
self.to_address.with_blooms(self.from_address.blooms())
}
/// Returns true if given trace matches the filter.
pub fn matches(&self, trace: &FlatTrace) -> bool {
match trace.action {
Action::Call(ref call) => {
let from_matches = self.from_address.matches(&call.from);
let to_matches = self.to_address.matches(&call.to);
from_matches && to_matches
},
Action::Create(ref create) => {
let from_matches = self.from_address.matches(&create.from);
let to_matches = self.to_address.matches_all();
from_matches && to_matches
}
}
}
}
#[cfg(test)]
mod tests {
use util::{FixedHash, Address, U256};
use util::sha3::Hashable;
use trace::trace::{Action, Call, Res};
use trace::flat::FlatTrace;
use trace::{Filter, AddressesFilter};
use basic_types::LogBloom;
#[test]
fn empty_trace_filter_bloom_possibilities() {
let filter = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![]),
to_address: AddressesFilter::from(vec![]),
};
let blooms = filter.bloom_possibilities();
assert_eq!(blooms, vec![LogBloom::new()]);
}
#[test]
fn single_trace_filter_bloom_possibility() {
let filter = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![Address::from(1)]),
to_address: AddressesFilter::from(vec![Address::from(2)]),
};
let blooms = filter.bloom_possibilities();
assert_eq!(blooms.len(), 1);
assert!(blooms[0].contains_bloomed(&Address::from(1).sha3()));
assert!(blooms[0].contains_bloomed(&Address::from(2).sha3()));
assert!(!blooms[0].contains_bloomed(&Address::from(3).sha3()));
}
#[test]
fn only_from_trace_filter_bloom_possibility() {
let filter = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![Address::from(1)]),
to_address: AddressesFilter::from(vec![]),
};
let blooms = filter.bloom_possibilities();
assert_eq!(blooms.len(), 1);
assert!(blooms[0].contains_bloomed(&Address::from(1).sha3()));
assert!(!blooms[0].contains_bloomed(&Address::from(2).sha3()));
}
#[test]
fn only_to_trace_filter_bloom_possibility() {
let filter = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![]),
to_address: AddressesFilter::from(vec![Address::from(1)]),
};
let blooms = filter.bloom_possibilities();
assert_eq!(blooms.len(), 1);
assert!(blooms[0].contains_bloomed(&Address::from(1).sha3()));
assert!(!blooms[0].contains_bloomed(&Address::from(2).sha3()));
}
#[test]
fn multiple_trace_filter_bloom_possibility() {
let filter = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![Address::from(1), Address::from(3)]),
to_address: AddressesFilter::from(vec![Address::from(2), Address::from(4)]),
};
let blooms = filter.bloom_possibilities();
assert_eq!(blooms.len(), 4);
assert!(blooms[0].contains_bloomed(&Address::from(1).sha3()));
assert!(blooms[0].contains_bloomed(&Address::from(2).sha3()));
assert!(!blooms[0].contains_bloomed(&Address::from(3).sha3()));
assert!(!blooms[0].contains_bloomed(&Address::from(4).sha3()));
assert!(blooms[1].contains_bloomed(&Address::from(1).sha3()));
assert!(blooms[1].contains_bloomed(&Address::from(4).sha3()));
assert!(!blooms[1].contains_bloomed(&Address::from(2).sha3()));
assert!(!blooms[1].contains_bloomed(&Address::from(3).sha3()));
assert!(blooms[2].contains_bloomed(&Address::from(2).sha3()));
assert!(blooms[2].contains_bloomed(&Address::from(3).sha3()));
assert!(!blooms[2].contains_bloomed(&Address::from(1).sha3()));
assert!(!blooms[2].contains_bloomed(&Address::from(4).sha3()));
assert!(blooms[3].contains_bloomed(&Address::from(3).sha3()));
assert!(blooms[3].contains_bloomed(&Address::from(4).sha3()));
assert!(!blooms[3].contains_bloomed(&Address::from(1).sha3()));
assert!(!blooms[3].contains_bloomed(&Address::from(2).sha3()));
}
#[test]
fn filter_matches() {
let f0 = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![Address::from(1)]),
to_address: AddressesFilter::from(vec![]),
};
let f1 = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![Address::from(3), Address::from(1)]),
to_address: AddressesFilter::from(vec![]),
};
let f2 = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![]),
to_address: AddressesFilter::from(vec![]),
};
let f3 = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![]),
to_address: AddressesFilter::from(vec![Address::from(2)]),
};
let f4 = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![]),
to_address: AddressesFilter::from(vec![Address::from(2), Address::from(3)]),
};
let f5 = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![Address::from(1)]),
to_address: AddressesFilter::from(vec![Address::from(2), Address::from(3)]),
};
let f6 = Filter {
range: (0..0),
from_address: AddressesFilter::from(vec![Address::from(1)]),
to_address: AddressesFilter::from(vec![Address::from(4)]),
};
let trace = FlatTrace {
action: Action::Call(Call {
from: Address::from(1),
to: Address::from(2),
value: U256::from(3),
gas: U256::from(4),
input: vec![0x5],
}),
result: Res::FailedCall,
trace_address: vec![0],
subtraces: 0,
};
assert!(f0.matches(&trace));
assert!(f1.matches(&trace));
assert!(f2.matches(&trace));
assert!(f3.matches(&trace));
assert!(f4.matches(&trace));
assert!(f5.matches(&trace));
assert!(!f6.matches(&trace));
}
}

View File

@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Flat trace module
use trace::BlockTraces;
use super::trace::{Trace, Action, Res};

View File

@@ -1,42 +0,0 @@
// 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::H256;
use super::trace::{Action, Res};
use header::BlockNumber;
/// Localized trace.
#[derive(Debug, PartialEq)]
pub struct LocalizedTrace {
/// Type of action performed by a transaction.
pub action: Action,
/// Result of this action.
pub result: Res,
/// Number of subtraces.
pub subtraces: usize,
/// Exact location of trace.
///
/// [index in root, index in first CALL, index in second CALL, ...]
pub trace_address: Vec<usize>,
/// Transaction number within the block.
pub transaction_number: usize,
/// Signed transaction hash.
pub transaction_hash: H256,
/// Block number.
pub block_number: BlockNumber,
/// Block hash.
pub block_hash: H256,
}

View File

@@ -21,20 +21,18 @@ mod bloom;
mod config;
mod db;
mod executive_tracer;
mod filter;
mod flat;
pub mod flat;
mod import;
mod localized;
mod noop_tracer;
pub mod trace;
pub use types::trace_types::*;
pub use self::block::BlockTraces;
pub use self::config::{Config, Switch};
pub use self::db::TraceDB;
pub use self::trace::Trace;
pub use types::trace_types::trace::Trace;
pub use self::noop_tracer::NoopTracer;
pub use self::executive_tracer::ExecutiveTracer;
pub use self::filter::{Filter, AddressesFilter};
pub use types::trace_types::filter::{Filter, AddressesFilter};
pub use self::import::ImportRequest;
pub use self::localized::LocalizedTrace;
use util::{Bytes, Address, U256, H256};

View File

@@ -1,428 +0,0 @@
// 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/>.
//! Tracing datatypes.
use util::{U256, Bytes, Address, FixedHash};
use util::rlp::*;
use util::sha3::Hashable;
use action_params::ActionParams;
use basic_types::LogBloom;
/// `Call` result.
#[derive(Debug, Clone, PartialEq, Default)]
pub struct CallResult {
/// Gas used by call.
pub gas_used: U256,
/// Call Output.
pub output: Bytes,
}
impl Encodable for CallResult {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(2);
s.append(&self.gas_used);
s.append(&self.output);
}
}
impl Decodable for CallResult {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
let d = decoder.as_rlp();
let res = CallResult {
gas_used: try!(d.val_at(0)),
output: try!(d.val_at(1)),
};
Ok(res)
}
}
/// `Create` result.
#[derive(Debug, Clone, PartialEq)]
pub struct CreateResult {
/// Gas used by create.
pub gas_used: U256,
/// Code of the newly created contract.
pub code: Bytes,
/// Address of the newly created contract.
pub address: Address,
}
impl Encodable for CreateResult {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(3);
s.append(&self.gas_used);
s.append(&self.code);
s.append(&self.address);
}
}
impl Decodable for CreateResult {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
let d = decoder.as_rlp();
let res = CreateResult {
gas_used: try!(d.val_at(0)),
code: try!(d.val_at(1)),
address: try!(d.val_at(2)),
};
Ok(res)
}
}
/// Description of a _call_ action, either a `CALL` operation or a message transction.
#[derive(Debug, Clone, PartialEq)]
pub struct Call {
/// The sending account.
pub from: Address,
/// The destination account.
pub to: Address,
/// The value transferred to the destination account.
pub value: U256,
/// The gas available for executing the call.
pub gas: U256,
/// The input data provided to the call.
pub input: Bytes,
}
impl From<ActionParams> for Call {
fn from(p: ActionParams) -> Self {
Call {
from: p.sender,
to: p.address,
value: p.value.value(),
gas: p.gas,
input: p.data.unwrap_or_else(Vec::new),
}
}
}
impl Encodable for Call {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(5);
s.append(&self.from);
s.append(&self.to);
s.append(&self.value);
s.append(&self.gas);
s.append(&self.input);
}
}
impl Decodable for Call {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
let d = decoder.as_rlp();
let res = Call {
from: try!(d.val_at(0)),
to: try!(d.val_at(1)),
value: try!(d.val_at(2)),
gas: try!(d.val_at(3)),
input: try!(d.val_at(4)),
};
Ok(res)
}
}
impl Call {
/// Returns call action bloom.
/// The bloom contains from and to addresses.
pub fn bloom(&self) -> LogBloom {
LogBloom::from_bloomed(&self.from.sha3())
.with_bloomed(&self.to.sha3())
}
}
/// Description of a _create_ action, either a `CREATE` operation or a create transction.
#[derive(Debug, Clone, PartialEq)]
pub struct Create {
/// The address of the creator.
pub from: Address,
/// The value with which the new account is endowed.
pub value: U256,
/// The gas available for the creation init code.
pub gas: U256,
/// The init code.
pub init: Bytes,
}
impl From<ActionParams> for Create {
fn from(p: ActionParams) -> Self {
Create {
from: p.sender,
value: p.value.value(),
gas: p.gas,
init: p.code.unwrap_or_else(Vec::new),
}
}
}
impl Encodable for Create {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(4);
s.append(&self.from);
s.append(&self.value);
s.append(&self.gas);
s.append(&self.init);
}
}
impl Decodable for Create {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
let d = decoder.as_rlp();
let res = Create {
from: try!(d.val_at(0)),
value: try!(d.val_at(1)),
gas: try!(d.val_at(2)),
init: try!(d.val_at(3)),
};
Ok(res)
}
}
impl Create {
/// Returns bloom create action bloom.
/// The bloom contains only from address.
pub fn bloom(&self) -> LogBloom {
LogBloom::from_bloomed(&self.from.sha3())
}
}
/// Description of an action that we trace; will be either a call or a create.
#[derive(Debug, Clone, PartialEq)]
pub enum Action {
/// It's a call action.
Call(Call),
/// It's a create action.
Create(Create),
}
impl Encodable for Action {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(2);
match *self {
Action::Call(ref call) => {
s.append(&0u8);
s.append(call);
},
Action::Create(ref create) => {
s.append(&1u8);
s.append(create);
}
}
}
}
impl Decodable for Action {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
let d = decoder.as_rlp();
let action_type: u8 = try!(d.val_at(0));
match action_type {
0 => d.val_at(1).map(Action::Call),
1 => d.val_at(1).map(Action::Create),
_ => Err(DecoderError::Custom("Invalid action type.")),
}
}
}
impl Action {
/// Returns action bloom.
pub fn bloom(&self) -> LogBloom {
match *self {
Action::Call(ref call) => call.bloom(),
Action::Create(ref create) => create.bloom(),
}
}
}
/// The result of the performed action.
#[derive(Debug, Clone, PartialEq)]
pub enum Res {
/// Successful call action result.
Call(CallResult),
/// Successful create action result.
Create(CreateResult),
/// Failed call.
FailedCall,
/// Failed create.
FailedCreate,
}
impl Encodable for Res {
fn rlp_append(&self, s: &mut RlpStream) {
match *self {
Res::Call(ref call) => {
s.begin_list(2);
s.append(&0u8);
s.append(call);
},
Res::Create(ref create) => {
s.begin_list(2);
s.append(&1u8);
s.append(create);
},
Res::FailedCall => {
s.begin_list(1);
s.append(&2u8);
},
Res::FailedCreate => {
s.begin_list(1);
s.append(&3u8);
}
}
}
}
impl Decodable for Res {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
let d = decoder.as_rlp();
let action_type: u8 = try!(d.val_at(0));
match action_type {
0 => d.val_at(1).map(Res::Call),
1 => d.val_at(1).map(Res::Create),
2 => Ok(Res::FailedCall),
3 => Ok(Res::FailedCreate),
_ => Err(DecoderError::Custom("Invalid result type.")),
}
}
}
#[derive(Debug, Clone, PartialEq)]
/// A trace; includes a description of the action being traced and sub traces of each interior action.
pub struct Trace {
/// The number of EVM execution environments active when this action happened; 0 if it's
/// the outer action of the transaction.
pub depth: usize,
/// The action being performed.
pub action: Action,
/// The sub traces for each interior action performed as part of this call.
pub subs: Vec<Trace>,
/// The result of the performed action.
pub result: Res,
}
impl Encodable for Trace {
fn rlp_append(&self, s: &mut RlpStream) {
s.begin_list(4);
s.append(&self.depth);
s.append(&self.action);
s.append(&self.subs);
s.append(&self.result);
}
}
impl Decodable for Trace {
fn decode<D>(decoder: &D) -> Result<Self, DecoderError> where D: Decoder {
let d = decoder.as_rlp();
let res = Trace {
depth: try!(d.val_at(0)),
action: try!(d.val_at(1)),
subs: try!(d.val_at(2)),
result: try!(d.val_at(3)),
};
Ok(res)
}
}
impl Trace {
/// Returns trace bloom.
pub fn bloom(&self) -> LogBloom {
self.subs.iter().fold(self.action.bloom(), |b, s| b | s.bloom())
}
}
#[cfg(test)]
mod tests {
use util::{Address, U256, FixedHash};
use util::rlp::{encode, decode};
use util::sha3::Hashable;
use trace::trace::{Call, CallResult, Create, Res, Action, Trace};
#[test]
fn traces_rlp() {
let trace = Trace {
depth: 2,
action: Action::Call(Call {
from: Address::from(1),
to: Address::from(2),
value: U256::from(3),
gas: U256::from(4),
input: vec![0x5]
}),
subs: vec![
Trace {
depth: 3,
action: Action::Create(Create {
from: Address::from(6),
value: U256::from(7),
gas: U256::from(8),
init: vec![0x9]
}),
subs: vec![],
result: Res::FailedCreate
}
],
result: Res::Call(CallResult {
gas_used: U256::from(10),
output: vec![0x11, 0x12]
})
};
let encoded = encode(&trace);
let decoded: Trace = decode(&encoded);
assert_eq!(trace, decoded);
}
#[test]
fn traces_bloom() {
let trace = Trace {
depth: 2,
action: Action::Call(Call {
from: Address::from(1),
to: Address::from(2),
value: U256::from(3),
gas: U256::from(4),
input: vec![0x5]
}),
subs: vec![
Trace {
depth: 3,
action: Action::Create(Create {
from: Address::from(6),
value: U256::from(7),
gas: U256::from(8),
init: vec![0x9]
}),
subs: vec![],
result: Res::FailedCreate
}
],
result: Res::Call(CallResult {
gas_used: U256::from(10),
output: vec![0x11, 0x12]
})
};
let bloom = trace.bloom();
// right now only addresses are bloomed
assert!(bloom.contains_bloomed(&Address::from(1).sha3()));
assert!(bloom.contains_bloomed(&Address::from(2).sha3()));
assert!(!bloom.contains_bloomed(&Address::from(20).sha3()));
assert!(bloom.contains_bloomed(&Address::from(6).sha3()));
}
}