diff --git a/ethcore/src/client.rs b/ethcore/src/client.rs index 7a9888b5d..a722d0d44 100644 --- a/ethcore/src/client.rs +++ b/ethcore/src/client.rs @@ -37,7 +37,7 @@ use extras::TransactionAddress; pub use blockchain::TreeRoute; /// Uniquely identifies block. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum BlockId { /// Block's sha3. /// Querying by hash is always faster. @@ -51,7 +51,7 @@ pub enum BlockId { } /// Uniquely identifies transaction. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone)] pub enum TransactionId { /// Transaction's sha3. Hash(H256), diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 204a4a257..b595139f9 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -41,6 +41,50 @@ impl EthClient { sync: sync } } + + fn block(&self, id: BlockId, include_txs: bool) -> Result { + match (self.client.block(id.clone()), self.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: OptionalValue::Value(view.sha3()), + parent_hash: view.parent_hash(), + uncles_hash: view.uncles_hash(), + author: view.author(), + miner: view.author(), + state_root: view.state_root(), + transactions_root: view.transactions_root(), + receipts_root: view.receipts_root(), + number: OptionalValue::Value(U256::from(view.number())), + gas_used: view.gas_used(), + gas_limit: view.gas_limit(), + logs_bloom: view.log_bloom(), + timestamp: U256::from(view.timestamp()), + difficulty: view.difficulty(), + total_difficulty: total_difficulty, + uncles: vec![], + transactions: { + if include_txs { + BlockTransactions::Full(block_view.localized_transactions().into_iter().map(From::from).collect()) + } else { + BlockTransactions::Hashes(block_view.transaction_hashes()) + } + }, + extra_data: Bytes::default() + }; + to_value(&block) + }, + _ => Ok(Value::Null) + } + } + + fn transaction(&self, id: TransactionId) -> Result { + match self.client.transaction(id) { + Some(t) => to_value(&Transaction::from(t)), + None => Ok(Value::Null) + } + } } impl Eth for EthClient { @@ -129,66 +173,29 @@ impl Eth for EthClient { .and_then(|(address, _block_number)| to_value(&self.client.code(&address).map_or_else(Bytes::default, Bytes::new))) } - fn block(&self, params: Params) -> Result { + fn block_by_hash(&self, params: Params) -> Result { from_params::<(H256, bool)>(params) - .and_then(|(hash, include_txs)| match (self.client.block(BlockId::Hash(hash.clone())), self.client.block_total_difficulty(BlockId::Hash(hash))) { - (Some(bytes), Some(total_difficulty)) => { - let block_view = BlockView::new(&bytes); - let view = block_view.header_view(); - let block = Block { - hash: OptionalValue::Value(view.sha3()), - parent_hash: view.parent_hash(), - uncles_hash: view.uncles_hash(), - author: view.author(), - miner: view.author(), - state_root: view.state_root(), - transactions_root: view.transactions_root(), - receipts_root: view.receipts_root(), - number: OptionalValue::Value(U256::from(view.number())), - gas_used: view.gas_used(), - gas_limit: view.gas_limit(), - logs_bloom: view.log_bloom(), - timestamp: U256::from(view.timestamp()), - difficulty: view.difficulty(), - total_difficulty: total_difficulty, - uncles: vec![], - transactions: { - if include_txs { - BlockTransactions::Full(block_view.localized_transactions().into_iter().map(From::from).collect()) - } else { - BlockTransactions::Hashes(block_view.transaction_hashes()) - } - }, - extra_data: Bytes::default() - }; - to_value(&block) - }, - _ => Ok(Value::Null) - }) + .and_then(|(hash, include_txs)| self.block(BlockId::Hash(hash), include_txs)) + } + + fn block_by_number(&self, params: Params) -> Result { + from_params::<(BlockNumber, bool)>(params) + .and_then(|(number, include_txs)| self.block(number.into(), include_txs)) } fn transaction_by_hash(&self, params: Params) -> Result { from_params::<(H256,)>(params) - .and_then(|(hash,)| match self.client.transaction(TransactionId::Hash(hash)) { - Some(t) => to_value(&Transaction::from(t)), - None => Ok(Value::Null) - }) + .and_then(|(hash,)| self.transaction(TransactionId::Hash(hash))) } fn transaction_by_block_hash_and_index(&self, params: Params) -> Result { from_params::<(H256, Index)>(params) - .and_then(|(hash, index)| match self.client.transaction(TransactionId::Location(BlockId::Hash(hash), index.value())) { - Some(t) => to_value(&Transaction::from(t)), - None => Ok(Value::Null) - }) + .and_then(|(hash, index)| self.transaction(TransactionId::Location(BlockId::Hash(hash), index.value()))) } fn transaction_by_block_number_and_index(&self, params: Params) -> Result { from_params::<(BlockNumber, Index)>(params) - .and_then(|(number, index)| match self.client.transaction(TransactionId::Location(number.into(), index.value())) { - Some(t) => to_value(&Transaction::from(t)), - None => Ok(Value::Null) - }) + .and_then(|(number, index)| self.transaction(TransactionId::Location(number.into(), index.value()))) } } diff --git a/rpc/src/v1/traits/eth.rs b/rpc/src/v1/traits/eth.rs index 640af1f82..d2aeb0f9e 100644 --- a/rpc/src/v1/traits/eth.rs +++ b/rpc/src/v1/traits/eth.rs @@ -50,8 +50,11 @@ pub trait Eth: Sized + Send + Sync + 'static { /// Returns content of the storage at given address. fn storage_at(&self, _: Params) -> Result { rpc_unimplemented!() } - /// Returns block with given index / hash. - fn block(&self, _: Params) -> Result { rpc_unimplemented!() } + /// Returns block with given hash. + fn block_by_hash(&self, _: Params) -> Result { rpc_unimplemented!() } + + /// Returns block with given number. + fn block_by_number(&self, _: Params) -> Result { rpc_unimplemented!() } /// Returns the number of transactions sent from given address at given time (block number). fn transaction_count(&self, _: Params) -> Result { rpc_unimplemented!() } @@ -135,8 +138,8 @@ pub trait Eth: Sized + Send + Sync + 'static { delegate.add_method("eth_sendTransaction", Eth::send_transaction); delegate.add_method("eth_call", Eth::call); delegate.add_method("eth_estimateGas", Eth::estimate_gas); - delegate.add_method("eth_getBlockByHash", Eth::block); - delegate.add_method("eth_getBlockByNumber", Eth::block); + delegate.add_method("eth_getBlockByHash", Eth::block_by_hash); + delegate.add_method("eth_getBlockByNumber", Eth::block_by_number); delegate.add_method("eth_getTransactionByHash", Eth::transaction_by_hash); delegate.add_method("eth_getTransactionByBlockHashAndIndex", Eth::transaction_by_block_hash_and_index); delegate.add_method("eth_getTransactionByBlockNumberAndIndex", Eth::transaction_by_block_number_and_index);