diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 7e1a8e23f..43920708b 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -103,6 +103,11 @@ pub trait BlockProvider { self.block(&address.block_hash).and_then(|bytes| BlockView::new(&bytes).localized_transaction_at(address.index)) } + /// Get transaction receipt. + fn transaction_receipt(&self, address: &TransactionAddress) -> Option { + self.block_receipts(&address.block_hash).and_then(|br| br.receipts.into_iter().nth(address.index)) + } + /// Get a list of transactions for a given block. /// Returns None if block does not exist. fn transactions(&self, hash: &H256) -> Option> { diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 1d34bf158..c8c9002d7 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -39,6 +39,7 @@ use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; use client::{BlockId, TransactionId, ClientConfig, BlockChainClient}; use env_info::EnvInfo; use executive::{Executive, Executed}; +use receipt::Receipt; pub use blockchain::CacheSize as BlockChainCacheSize; /// General block status @@ -384,6 +385,16 @@ impl Client where V: Verifier { BlockId::Latest => Some(self.chain.best_block_number()) } } + + fn transaction_address(&self, id: TransactionId) -> Option { + match id { + TransactionId::Hash(ref hash) => self.chain.transaction_address(hash), + TransactionId::Location(id, index) => Self::block_hash(&self.chain, id).map(|hash| TransactionAddress { + block_hash: hash, + index: index + }) + } + } } impl BlockChainClient for Client where V: Verifier { @@ -535,13 +546,11 @@ impl BlockChainClient for Client where V: Verifier { } fn transaction(&self, id: TransactionId) -> Option { - match id { - TransactionId::Hash(ref hash) => self.chain.transaction_address(hash), - TransactionId::Location(id, index) => Self::block_hash(&self.chain, id).map(|hash| TransactionAddress { - block_hash: hash, - index: index - }) - }.and_then(|address| self.chain.transaction(&address)) + self.transaction_address(id).and_then(|address| self.chain.transaction(&address)) + } + + fn transaction_receipt(&self, id: TransactionId) -> Option { + self.transaction_address(id).and_then(|address| self.chain.transaction_receipt(&address)) } fn tree_route(&self, from: &H256, to: &H256) -> Option { diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 9663ab62b..420fcf75e 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -39,6 +39,7 @@ use transaction::{LocalizedTransaction, SignedTransaction}; use log_entry::LocalizedLogEntry; use filter::Filter; use error::{ImportResult, Error}; +use receipt::Receipt; /// Blockchain database client. Owns and manages a blockchain and a block queue. pub trait BlockChainClient : Sync + Send { @@ -76,6 +77,9 @@ pub trait BlockChainClient : Sync + Send { /// Get transaction with given hash. fn transaction(&self, id: TransactionId) -> Option; + /// Get transaction receipt with given hash. + fn transaction_receipt(&self, id: TransactionId) -> Option; + /// Get a tree route between `from` and `to`. /// See `BlockChain::tree_route`. fn tree_route(&self, from: &H256, to: &H256) -> Option; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index ad73234b3..fbff834ba 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -224,6 +224,10 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } + fn transaction_receipt(&self, _id: TransactionId) -> Option { + unimplemented!(); + } + fn blocks_with_bloom(&self, _bloom: &H2048, _from_block: BlockId, _to_block: BlockId) -> Option> { unimplemented!(); } diff --git a/ethcore/src/receipt.rs b/ethcore/src/receipt.rs index ae83a174a..7f0b0d8dd 100644 --- a/ethcore/src/receipt.rs +++ b/ethcore/src/receipt.rs @@ -18,7 +18,8 @@ use util::*; use basic_types::LogBloom; -use log_entry::LogEntry; +use header::BlockNumber; +use log_entry::{LogEntry, LocalizedLogEntry}; /// Information describing execution of a transaction. #[derive(Default, Debug, Clone)] @@ -74,6 +75,26 @@ impl HeapSizeOf for Receipt { } } +/// Receipt with additional info. +pub struct LocalizedReceipt { + /// Transaction hash. + pub transaction_hash: H256, + /// Transaction index. + pub transaction_index: usize, + /// Block hash. + pub block_hash: H256, + /// Block number. + pub block_number: BlockNumber, + /// Cumulative gas used. + pub cumulative_gas_used: U256, + /// Gas used. + pub gas_used: U256, + /// Contract address. + pub contract_address: Option
, + /// Logs + pub logs: Vec, +} + #[test] fn test_basic() { let expected = FromHex::from_hex("f90162a02f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee83040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index a99a912f8..950cdb783 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -293,6 +293,12 @@ impl Eth for EthClient .and_then(|(number, index)| self.transaction(TransactionId::Location(number.into(), index.value()))) } + fn transaction_receipt(&self, params: Params) -> Result { + unimplemented!(); + //from_params::<(H256,)>(params) + //.and_then(|(hash,)| self.transaction_receipt(TransactionId::Hash(hash))) + } + 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())) diff --git a/rpc/src/v1/types/mod.rs.in b/rpc/src/v1/types/mod.rs.in index ebc3bc0ff..0121e4aea 100644 --- a/rpc/src/v1/types/mod.rs.in +++ b/rpc/src/v1/types/mod.rs.in @@ -24,6 +24,7 @@ mod optionals; mod sync; mod transaction; mod transaction_request; +mod receipt; pub use self::block::{Block, BlockTransactions}; pub use self::block_number::BlockNumber; @@ -35,4 +36,5 @@ pub use self::optionals::OptionalValue; pub use self::sync::{SyncStatus, SyncInfo}; pub use self::transaction::Transaction; pub use self::transaction_request::TransactionRequest; +pub use self::receipt::Receipt; diff --git a/rpc/src/v1/types/receipt.rs b/rpc/src/v1/types/receipt.rs new file mode 100644 index 000000000..fa34d5df5 --- /dev/null +++ b/rpc/src/v1/types/receipt.rs @@ -0,0 +1,56 @@ +// 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 . + +use util::numbers::U256; +use util::hash::{Address, H256}; +use v1::types::Log; +use ethcore::receipt::LocalizedReceipt; + +#[derive(Debug, Serialize)] +pub struct Receipt { + #[serde(rename="transactionHash")] + pub transaction_hash: H256, + #[serde(rename="transactionIndex")] + pub transaction_index: U256, + #[serde(rename="blockHash")] + pub block_hash: H256, + #[serde(rename="blockNumber")] + pub block_number: U256, + #[serde(rename="cumulativeGasUsed")] + pub cumulative_gas_used: U256, + #[serde(rename="gasUsed")] + pub gas_used: U256, + #[serde(rename="contractAddress")] + pub contract_address: Option
, + pub logs: Vec, +} + +impl From for Receipt { + fn from(r: LocalizedReceipt) -> Self { + Receipt { + transaction_hash: r.transaction_hash, + transaction_index: U256::from(r.transaction_index), + block_hash: r.block_hash, + block_number: U256::from(r.block_number), + cumulative_gas_used: r.cumulative_gas_used, + gas_used: r.gas_used, + contract_address: r.contract_address, + logs: r.logs.into_iter().map(From::from).collect(), + } + } +} + +