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

Exposing engine extra info in block RPC #3169

Merged
merged 3 commits into from
Nov 4, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -1189,6 +1189,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
110 changes: 59 additions & 51 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
10 changes: 5 additions & 5 deletions rpc/src/v1/traits/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! Eth rpc interface.
use jsonrpc_core::*;

use v1::types::{Block, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index};
use v1::types::{RichBlock, BlockNumber, Bytes, CallRequest, Filter, FilterChanges, Index};
use v1::types::{Log, Receipt, SyncStatus, Transaction, Work};
use v1::types::{H64, H160, H256, U256};

Expand Down Expand Up @@ -68,11 +68,11 @@ build_rpc_trait! {

/// Returns block with given hash.
#[rpc(name = "eth_getBlockByHash")]
fn block_by_hash(&self, H256, bool) -> Result<Option<Block>, Error>;
fn block_by_hash(&self, H256, bool) -> Result<Option<RichBlock>, Error>;

/// Returns block with given number.
#[rpc(name = "eth_getBlockByNumber")]
fn block_by_number(&self, BlockNumber, bool) -> Result<Option<Block>, Error>;
fn block_by_number(&self, BlockNumber, bool) -> Result<Option<RichBlock>, Error>;

/// Returns the number of transactions sent from given address at given time (block number).
#[rpc(name = "eth_getTransactionCount")]
Expand Down Expand Up @@ -128,11 +128,11 @@ build_rpc_trait! {

/// Returns an uncles at given block and index.
#[rpc(name = "eth_getUncleByBlockHashAndIndex")]
fn uncle_by_block_hash_and_index(&self, H256, Index) -> Result<Option<Block>, Error>;
fn uncle_by_block_hash_and_index(&self, H256, Index) -> Result<Option<RichBlock>, Error>;

/// Returns an uncles at given block and index.
#[rpc(name = "eth_getUncleByBlockNumberAndIndex")]
fn uncle_by_block_number_and_index(&self, BlockNumber, Index) -> Result<Option<Block>, Error>;
fn uncle_by_block_number_and_index(&self, BlockNumber, Index) -> Result<Option<RichBlock>, Error>;

/// Returns available compilers.
#[rpc(name = "eth_getCompilers")]
Expand Down
Loading