diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index b2254e285..61e3b4cd8 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -21,7 +21,7 @@ use util::*; use util::panics::*; use views::BlockView; use error::*; -use header::{BlockNumber}; +use header::{BlockNumber, Header}; use state::State; use spec::Spec; use engine::Engine; @@ -36,7 +36,7 @@ use filter::Filter; use log_entry::LocalizedLogEntry; use block_queue::{BlockQueue, BlockQueueInfo}; use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; -use client::{BlockId, TransactionId, ClientConfig, BlockChainClient}; +use client::{BlockId, TransactionId, UncleId, ClientConfig, BlockChainClient}; use env_info::EnvInfo; use executive::{Executive, Executed}; use receipt::LocalizedReceipt; @@ -549,6 +549,11 @@ impl BlockChainClient for Client where V: Verifier { self.transaction_address(id).and_then(|address| self.chain.transaction(&address)) } + fn uncle(&self, id: UncleId) -> Option
{ + let index = id.1; + self.block(id.0).and_then(|block| BlockView::new(&block).uncle_at(index)) + } + fn transaction_receipt(&self, id: TransactionId) -> Option { self.transaction_address(id).and_then(|address| { let t = self.chain.block(&address.block_hash) diff --git a/ethcore/src/client/ids.rs b/ethcore/src/client/ids.rs index 9bd59b177..79302354f 100644 --- a/ethcore/src/client/ids.rs +++ b/ethcore/src/client/ids.rs @@ -42,3 +42,11 @@ pub enum TransactionId { /// Querying by block position is always faster. Location(BlockId, usize) } + +/// Uniquely identifies Uncle. +pub struct UncleId ( + /// Block id. + pub BlockId, + /// Position in block. + pub usize +); diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 74b05652f..65733f3bf 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -23,7 +23,7 @@ mod test_client; pub use self::client::*; pub use self::config::{ClientConfig, BlockQueueConfig, BlockChainConfig}; -pub use self::ids::{BlockId, TransactionId}; +pub use self::ids::{BlockId, TransactionId, UncleId}; pub use self::test_client::{TestBlockChainClient, EachBlockWith}; pub use executive::Executed; @@ -34,7 +34,7 @@ use util::numbers::U256; use blockchain::TreeRoute; use block_queue::BlockQueueInfo; use block::{ClosedBlock, SealedBlock}; -use header::BlockNumber; +use header::{BlockNumber, Header}; use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; @@ -77,6 +77,9 @@ pub trait BlockChainClient : Sync + Send { /// Get transaction with given hash. fn transaction(&self, id: TransactionId) -> Option; + /// Get uncle with given id. + fn uncle(&self, id: UncleId) -> Option
; + /// Get transaction receipt with given hash. fn transaction_receipt(&self, id: TransactionId) -> Option; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 2b9f1051a..1c3068f12 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -19,7 +19,7 @@ use util::*; use transaction::{Transaction, LocalizedTransaction, SignedTransaction, Action}; use blockchain::TreeRoute; -use client::{BlockChainClient, BlockChainInfo, BlockStatus, BlockId, TransactionId}; +use client::{BlockChainClient, BlockChainInfo, BlockStatus, BlockId, TransactionId, UncleId}; use header::{Header as BlockHeader, BlockNumber}; use filter::Filter; use log_entry::LocalizedLogEntry; @@ -232,6 +232,10 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } + fn uncle(&self, _id: UncleId) -> Option { + unimplemented!(); + } + fn transaction_receipt(&self, id: TransactionId) -> Option { self.receipts.read().unwrap().get(&id).cloned() } diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index fd35cb963..6d8bd4b07 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -126,9 +126,36 @@ impl EthClient } } - fn uncle(&self, _block: BlockId, _index: usize) -> Result { - // TODO: implement! - Ok(Value::Null) + fn uncle(&self, id: UncleId) -> Result { + let client = take_weak!(self.client); + match client.uncle(id).and_then(|u| client.block_total_difficulty(BlockId::Hash(u.hash())).map(|diff| (diff, u))) { + Some((difficulty, uncle)) => { + let block = Block { + hash: OptionalValue::Value(uncle.hash()), + parent_hash: uncle.parent_hash, + uncles_hash: uncle.uncles_hash, + author: uncle.author, + miner: uncle.author, + state_root: uncle.state_root, + transactions_root: uncle.transactions_root, + number: OptionalValue::Value(U256::from(uncle.number)), + gas_used: uncle.gas_used, + gas_limit: uncle.gas_limit, + logs_bloom: uncle.log_bloom, + timestamp: U256::from(uncle.timestamp), + difficulty: uncle.difficulty, + total_difficulty: difficulty, + receipts_root: uncle.receipts_root, + extra_data: Bytes::new(uncle.extra_data), + // todo: + nonce: H64::from(0), + uncles: vec![], + transactions: BlockTransactions::Hashes(vec![]), + }; + to_value(&block) + }, + None => Ok(Value::Null) + } } } @@ -303,12 +330,12 @@ impl Eth for EthClient fn uncle_by_block_hash_and_index(&self, params: Params) -> Result { from_params::<(H256, Index)>(params) - .and_then(|(hash, index)| self.uncle(BlockId::Hash(hash), index.value())) + .and_then(|(hash, index)| self.uncle(UncleId(BlockId::Hash(hash), index.value()))) } fn uncle_by_block_number_and_index(&self, params: Params) -> Result { from_params::<(BlockNumber, Index)>(params) - .and_then(|(number, index)| self.uncle(number.into(), index.value())) + .and_then(|(number, index)| self.uncle(UncleId(number.into(), index.value()))) } fn compilers(&self, params: Params) -> Result { @@ -434,6 +461,7 @@ impl Eth for EthClient } fn call(&self, params: Params) -> Result { + println!("params: {:?}", params); from_params::<(TransactionRequest, BlockNumber)>(params) .and_then(|(transaction_request, _block_number)| { let accounts = take_weak!(self.accounts);