Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Backporting (#3198)
Browse files Browse the repository at this point in the history
* sendRawTransaction invalid RLP error

* Returning proper error for estimate_gas

* Exposing engine extra info in block RPC (#3169)

* Exposing extra info in RPC

* Proper serialization and client trait API

* Fixing possible race condition in ethcore_hashContent (#3191)

* Remove dapp logos (GHH points to dapp-assets) (#3192)
  • Loading branch information
arkpar committed Nov 4, 2016
1 parent 5224012 commit 33cc105
Show file tree
Hide file tree
Showing 24 changed files with 195 additions and 80 deletions.
14 changes: 13 additions & 1 deletion ethcore/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ use evm::{Factory as EvmFactory, Schedule};
use miner::{Miner, MinerService};
use snapshot::{self, io as snapshot_io};
use factory::Factories;
use rlp::{View, UntrustedRlp};
use rlp::{decode, View, UntrustedRlp};
use state_db::StateDB;
use rand::OsRng;

Expand Down Expand Up @@ -1187,6 +1187,18 @@ impl BlockChainClient for Client {
fn signing_network_id(&self) -> Option<u8> {
self.engine.signing_network_id(&self.latest_env_info())
}

fn block_extra_info(&self, id: BlockID) -> Option<BTreeMap<String, String>> {
self.block_header(id)
.map(|block| decode(&block))
.map(|header| self.engine.extra_info(&header))
}

fn uncle_extra_info(&self, id: UncleID) -> Option<BTreeMap<String, String>> {
self.uncle(id)
.map(|block| BlockView::new(&block).header())
.map(|header| self.engine.extra_info(&header))
}
}

impl MiningBlockChainClient for Client {
Expand Down
12 changes: 12 additions & 0 deletions ethcore/src/client/test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use evm::{Factory as EvmFactory, VMType, Schedule};
use miner::{Miner, MinerService, TransactionImportResult};
use spec::Spec;
use types::mode::Mode;
use views::BlockView;

use verification::queue::QueueInfo;
use block::{OpenBlock, SealedBlock};
Expand Down Expand Up @@ -417,6 +418,10 @@ impl BlockChainClient for TestBlockChainClient {
None // Simple default.
}

fn uncle_extra_info(&self, _id: UncleID) -> Option<BTreeMap<String, String>> {
None
}

fn transaction_receipt(&self, id: TransactionID) -> Option<LocalizedReceipt> {
self.receipts.read().get(&id).cloned()
}
Expand Down Expand Up @@ -459,6 +464,13 @@ impl BlockChainClient for TestBlockChainClient {
self.block_hash(id).and_then(|hash| self.blocks.read().get(&hash).cloned())
}

fn block_extra_info(&self, id: BlockID) -> Option<BTreeMap<String, String>> {
self.block(id)
.map(|block| BlockView::new(&block).header())
.map(|header| self.spec.engine.extra_info(&header))
}


fn block_status(&self, id: BlockID) -> BlockStatus {
match id {
BlockID::Number(number) if (number as usize) < self.blocks.read().len() => BlockStatus::InChain,
Expand Down
12 changes: 9 additions & 3 deletions ethcore/src/client/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ use error::{ImportResult, CallError};
use receipt::LocalizedReceipt;
use trace::LocalizedTrace;
use evm::{Factory as EvmFactory, Schedule};
use types::ids::*;
use types::trace_filter::Filter as TraceFilter;
use executive::Executed;
use env_info::LastHashes;
use types::call_analytics::CallAnalytics;
use block_import_error::BlockImportError;
use ipc::IpcConfig;
use types::ids::*;
use types::trace_filter::Filter as TraceFilter;
use types::call_analytics::CallAnalytics;
use types::blockchain_info::BlockChainInfo;
use types::block_status::BlockStatus;
use types::mode::Mode;
Expand Down Expand Up @@ -235,6 +235,12 @@ pub trait BlockChainClient : Sync + Send {

/// Set the mode.
fn set_mode(&self, mode: Mode);

/// Returns engine-related extra info for `BlockID`.
fn block_extra_info(&self, id: BlockID) -> Option<BTreeMap<String, String>>;

/// Returns engine-related extra info for `UncleID`.
fn uncle_extra_info(&self, id: UncleID) -> Option<BTreeMap<String, String>>;
}

/// Extended client interface used for mining
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/engines/basic_authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl Engine for BasicAuthority {
fn builtins(&self) -> &BTreeMap<Address, Builtin> { &self.builtins }

/// Additional engine-specific information for the user/developer concerning `header`.
fn extra_info(&self, _header: &Header) -> HashMap<String, String> { hash_map!["signature".to_owned() => "TODO".to_owned()] }
fn extra_info(&self, _header: &Header) -> BTreeMap<String, String> { map!["signature".to_owned() => "TODO".to_owned()] }

fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
Schedule::new_homestead()
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/engines/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub trait Engine : Sync + Send {
fn seal_fields(&self) -> usize { 0 }

/// Additional engine-specific information for the user/developer concerning `header`.
fn extra_info(&self, _header: &Header) -> HashMap<String, String> { HashMap::new() }
fn extra_info(&self, _header: &Header) -> BTreeMap<String, String> { BTreeMap::new() }

/// Additional information.
fn additional_params(&self) -> HashMap<String, String> { HashMap::new() }
Expand Down
4 changes: 2 additions & 2 deletions ethcore/src/ethereum/ethash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ impl Engine for Ethash {
}

/// Additional engine-specific information for the user/developer concerning `header`.
fn extra_info(&self, header: &Header) -> HashMap<String, String> {
hash_map!["nonce".to_owned() => format!("0x{}", header.nonce().hex()), "mixHash".to_owned() => format!("0x{}", header.mix_hash().hex())]
fn extra_info(&self, header: &Header) -> BTreeMap<String, String> {
map!["nonce".to_owned() => format!("0x{}", header.nonce().hex()), "mixHash".to_owned() => format!("0x{}", header.mix_hash().hex())]
}

fn schedule(&self, env_info: &EnvInfo) -> Schedule {
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/types/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub struct TraceId {
}

/// Uniquely identifies Uncle.
#[derive(Debug, Binary)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, Binary)]
pub struct UncleID {
/// Block id.
pub block: BlockID,
Expand Down
Binary file removed js/assets/images/dapps/coins-64x64.jpg
Binary file not shown.
Binary file removed js/assets/images/dapps/coins.jpg
Binary file not shown.
Binary file removed js/assets/images/dapps/hex-64x64.jpg
Binary file not shown.
Binary file removed js/assets/images/dapps/hex.jpg
Binary file not shown.
Binary file removed js/assets/images/dapps/interlock-64x64.png
Binary file not shown.
Binary file removed js/assets/images/dapps/interlock.png
Binary file not shown.
Binary file removed js/assets/images/dapps/link-64x64.jpg
Binary file not shown.
Binary file removed js/assets/images/dapps/link.jpg
Binary file not shown.
Binary file removed js/assets/images/dapps/register-64x64.jpg
Binary file not shown.
Binary file removed js/assets/images/dapps/register.jpg
Binary file not shown.
9 changes: 9 additions & 0 deletions rpc/src/v1/helpers/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ macro_rules! rpc_unimplemented {
}

use std::fmt;
use rlp::DecoderError;
use ethcore::error::{Error as EthcoreError, CallError};
use ethcore::account_provider::{Error as AccountError};
use fetch::FetchError;
Expand Down Expand Up @@ -271,6 +272,14 @@ pub fn from_transaction_error(error: EthcoreError) -> Error {
}
}

pub fn from_rlp_error(error: DecoderError) -> Error {
Error {
code: ErrorCode::InvalidParams,
message: "Invalid RLP.".into(),
data: Some(Value::String(format!("{:?}", error))),
}
}

pub fn from_call_error(error: CallError) -> Error {
match error {
CallError::StatePruned => state_pruned(),
Expand Down
128 changes: 69 additions & 59 deletions rpc/src/v1/impls/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use ethcore::snapshot::SnapshotService;
use self::ethash::SeedHashCompute;
use v1::traits::Eth;
use v1::types::{
Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo,
RichBlock, Block, BlockTransactions, BlockNumber, Bytes, SyncStatus, SyncInfo,
Transaction, CallRequest, Index, Filter, Log, Receipt, Work,
H64 as RpcH64, H256 as RpcH256, H160 as RpcH160, U256 as RpcU256,
};
Expand All @@ -53,6 +53,8 @@ use v1::helpers::dispatch::{default_gas_price, dispatch_transaction};
use v1::helpers::block_import::is_major_importing;
use v1::helpers::auto_args::Trailing;

const EXTRA_INFO_PROOF: &'static str = "Object exists in in blockchain (fetched earlier), extra_info is always available if object exists; qed";

/// Eth RPC options
pub struct EthClientOptions {
/// Returns receipt from pending blocks
Expand Down Expand Up @@ -117,36 +119,39 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
}
}

fn block(&self, id: BlockID, include_txs: bool) -> Result<Option<Block>, Error> {
fn block(&self, id: BlockID, include_txs: bool) -> Result<Option<RichBlock>, Error> {
let client = take_weak!(self.client);
match (client.block(id.clone()), client.block_total_difficulty(id)) {
(Some(bytes), Some(total_difficulty)) => {
let block_view = BlockView::new(&bytes);
let view = block_view.header_view();
let block = Block {
hash: Some(view.sha3().into()),
size: Some(bytes.len().into()),
parent_hash: view.parent_hash().into(),
uncles_hash: view.uncles_hash().into(),
author: view.author().into(),
miner: view.author().into(),
state_root: view.state_root().into(),
transactions_root: view.transactions_root().into(),
receipts_root: view.receipts_root().into(),
number: Some(view.number().into()),
gas_used: view.gas_used().into(),
gas_limit: view.gas_limit().into(),
logs_bloom: view.log_bloom().into(),
timestamp: view.timestamp().into(),
difficulty: view.difficulty().into(),
total_difficulty: total_difficulty.into(),
seal_fields: view.seal().into_iter().map(|f| rlp::decode(&f)).map(Bytes::new).collect(),
uncles: block_view.uncle_hashes().into_iter().map(Into::into).collect(),
transactions: match include_txs {
true => BlockTransactions::Full(block_view.localized_transactions().into_iter().map(Into::into).collect()),
false => BlockTransactions::Hashes(block_view.transaction_hashes().into_iter().map(Into::into).collect()),
let block = RichBlock {
block: Block {
hash: Some(view.sha3().into()),
size: Some(bytes.len().into()),
parent_hash: view.parent_hash().into(),
uncles_hash: view.uncles_hash().into(),
author: view.author().into(),
miner: view.author().into(),
state_root: view.state_root().into(),
transactions_root: view.transactions_root().into(),
receipts_root: view.receipts_root().into(),
number: Some(view.number().into()),
gas_used: view.gas_used().into(),
gas_limit: view.gas_limit().into(),
logs_bloom: view.log_bloom().into(),
timestamp: view.timestamp().into(),
difficulty: view.difficulty().into(),
total_difficulty: total_difficulty.into(),
seal_fields: view.seal().into_iter().map(|f| rlp::decode(&f)).map(Bytes::new).collect(),
uncles: block_view.uncle_hashes().into_iter().map(Into::into).collect(),
transactions: match include_txs {
true => BlockTransactions::Full(block_view.localized_transactions().into_iter().map(Into::into).collect()),
false => BlockTransactions::Hashes(block_view.transaction_hashes().into_iter().map(Into::into).collect()),
},
extra_data: Bytes::new(view.extra_data()),
},
extra_data: Bytes::new(view.extra_data())
extra_info: client.block_extra_info(id.clone()).expect(EXTRA_INFO_PROOF),
};
Ok(Some(block))
},
Expand All @@ -161,7 +166,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
}
}

fn uncle(&self, id: UncleID) -> Result<Option<Block>, Error> {
fn uncle(&self, id: UncleID) -> Result<Option<RichBlock>, Error> {
let client = take_weak!(self.client);
let uncle: BlockHeader = match client.uncle(id) {
Some(rlp) => rlp::decode(&rlp),
Expand All @@ -172,27 +177,30 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
None => { return Ok(None); }
};

let block = Block {
hash: Some(uncle.hash().into()),
size: None,
parent_hash: uncle.parent_hash().clone().into(),
uncles_hash: uncle.uncles_hash().clone().into(),
author: uncle.author().clone().into(),
miner: uncle.author().clone().into(),
state_root: uncle.state_root().clone().into(),
transactions_root: uncle.transactions_root().clone().into(),
number: Some(uncle.number().into()),
gas_used: uncle.gas_used().clone().into(),
gas_limit: uncle.gas_limit().clone().into(),
logs_bloom: uncle.log_bloom().clone().into(),
timestamp: uncle.timestamp().into(),
difficulty: uncle.difficulty().clone().into(),
total_difficulty: (uncle.difficulty().clone() + parent_difficulty).into(),
receipts_root: uncle.receipts_root().clone().into(),
extra_data: uncle.extra_data().clone().into(),
seal_fields: uncle.seal().clone().into_iter().map(|f| rlp::decode(&f)).map(Bytes::new).collect(),
uncles: vec![],
transactions: BlockTransactions::Hashes(vec![]),
let block = RichBlock {
block: Block {
hash: Some(uncle.hash().into()),
size: None,
parent_hash: uncle.parent_hash().clone().into(),
uncles_hash: uncle.uncles_hash().clone().into(),
author: uncle.author().clone().into(),
miner: uncle.author().clone().into(),
state_root: uncle.state_root().clone().into(),
transactions_root: uncle.transactions_root().clone().into(),
number: Some(uncle.number().into()),
gas_used: uncle.gas_used().clone().into(),
gas_limit: uncle.gas_limit().clone().into(),
logs_bloom: uncle.log_bloom().clone().into(),
timestamp: uncle.timestamp().into(),
difficulty: uncle.difficulty().clone().into(),
total_difficulty: (uncle.difficulty().clone() + parent_difficulty).into(),
receipts_root: uncle.receipts_root().clone().into(),
extra_data: uncle.extra_data().clone().into(),
seal_fields: uncle.seal().clone().into_iter().map(|f| rlp::decode(&f)).map(Bytes::new).collect(),
uncles: vec![],
transactions: BlockTransactions::Hashes(vec![]),
},
extra_info: client.uncle_extra_info(id).expect(EXTRA_INFO_PROOF),
};
Ok(Some(block))
}
Expand Down Expand Up @@ -435,13 +443,13 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
}
}

fn block_by_hash(&self, hash: RpcH256, include_txs: bool) -> Result<Option<Block>, Error> {
fn block_by_hash(&self, hash: RpcH256, include_txs: bool) -> Result<Option<RichBlock>, Error> {
try!(self.active());

self.block(BlockID::Hash(hash.into()), include_txs)
}

fn block_by_number(&self, num: BlockNumber, include_txs: bool) -> Result<Option<Block>, Error> {
fn block_by_number(&self, num: BlockNumber, include_txs: bool) -> Result<Option<RichBlock>, Error> {
try!(self.active());

self.block(num.into(), include_txs)
Expand Down Expand Up @@ -483,13 +491,13 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
}
}

fn uncle_by_block_hash_and_index(&self, hash: RpcH256, index: Index) -> Result<Option<Block>, Error> {
fn uncle_by_block_hash_and_index(&self, hash: RpcH256, index: Index) -> Result<Option<RichBlock>, Error> {
try!(self.active());

self.uncle(UncleID { block: BlockID::Hash(hash.into()), position: index.value() })
}

fn uncle_by_block_number_and_index(&self, num: BlockNumber, index: Index) -> Result<Option<Block>, Error> {
fn uncle_by_block_number_and_index(&self, num: BlockNumber, index: Index) -> Result<Option<RichBlock>, Error> {
try!(self.active());

self.uncle(UncleID { block: num.into(), position: index.value() })
Expand Down Expand Up @@ -603,7 +611,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
let raw_transaction = raw.to_vec();
match UntrustedRlp::new(&raw_transaction).as_val() {
Ok(signed_transaction) => dispatch_transaction(&*take_weak!(self.client), &*take_weak!(self.miner), signed_transaction),
Err(_) => Ok(RpcH256::from(H256::from(0))),
Err(e) => Err(errors::from_rlp_error(e)),
}
}

Expand All @@ -613,28 +621,30 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
let request = CallRequest::into(request);
let signed = try!(self.sign_call(request));

let r = match num.0 {
let result = match num.0 {
BlockNumber::Pending => take_weak!(self.miner).call(&*take_weak!(self.client), &signed, Default::default()),
num => take_weak!(self.client).call(&signed, num.into(), Default::default()),
};

match r {
Ok(b) => Ok(Bytes(b.output)),
Err(e) => Err(errors::from_call_error(e)),
}

result
.map(|b| b.output.into())
.map_err(errors::from_call_error)
}

fn estimate_gas(&self, request: CallRequest, num: Trailing<BlockNumber>) -> Result<RpcU256, Error> {
try!(self.active());

let request = CallRequest::into(request);
let signed = try!(self.sign_call(request));
let r = match num.0 {
let result = match num.0 {
BlockNumber::Pending => take_weak!(self.miner).call(&*take_weak!(self.client), &signed, Default::default()),
num => take_weak!(self.client).call(&signed, num.into(), Default::default()),
};

Ok(RpcU256::from(r.map(|res| res.gas_used + res.refunded).unwrap_or(From::from(0))))
result
.map(|res| (res.gas_used + res.refunded).into())
.map_err(errors::from_call_error)
}

fn compile_lll(&self, _: String) -> Result<Bytes, Error> {
Expand Down
8 changes: 6 additions & 2 deletions rpc/src/v1/impls/ethcore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,15 +302,19 @@ impl<C, M, S: ?Sized, F> Ethcore for EthcoreClient<C, M, S, F> where
.map(Into::into);

// Receive ready and invoke with result.
let ready: Ready<H256> = rx.try_recv().expect("When on_done is invoked ready object is always sent.");
let ready: Ready<H256> = rx.recv().expect(
"recv() fails when `tx` has been dropped, if this closure is invoked `tx` is not dropped (`res == Ok()`); qed"
);
ready.ready(result);
}));

// Either invoke ready right away or transfer it to the closure.
if let Err(e) = res {
ready.ready(Err(errors::from_fetch_error(e)));
} else {
tx.send(ready).expect("Rx end is sent to on_done closure.");
tx.send(ready).expect(
"send() fails when `rx` end is dropped, if `res == Ok()`: `rx` is moved to the closure; qed"
);
}
}
}
Expand Down
Loading

0 comments on commit 33cc105

Please sign in to comment.