From 5d05c367916191b0312cd6dfe9a728d4f2b16269 Mon Sep 17 00:00:00 2001 From: debris Date: Tue, 9 Feb 2016 15:17:01 +0100 Subject: [PATCH] LocalizedTransaction --- ethcore/src/blockchain.rs | 10 +++++----- ethcore/src/client.rs | 6 +++--- ethcore/src/transaction.rs | 21 +++++++++++++++++++++ ethcore/src/views.rs | 16 ++++++++++++++++ rpc/src/v1/impls/eth.rs | 18 +++++++++--------- rpc/src/v1/types/block.rs | 2 +- rpc/src/v1/types/transaction.rs | 4 ++-- 7 files changed, 57 insertions(+), 20 deletions(-) diff --git a/ethcore/src/blockchain.rs b/ethcore/src/blockchain.rs index ff1e508d3..af7800870 100644 --- a/ethcore/src/blockchain.rs +++ b/ethcore/src/blockchain.rs @@ -111,19 +111,19 @@ pub trait BlockProvider { } /// Get transaction with given transaction hash. - fn transaction(&self, hash: &H256) -> Option { + fn transaction(&self, hash: &H256) -> Option { self.transaction_address(hash).and_then(|address| self.transaction_at(&address)) } /// Get transaction at given address. - fn transaction_at(&self, address: &TransactionAddress) -> Option { - self.block(&address.block_hash).map(|bytes| BlockView::new(&bytes).transactions()).and_then(|t| t.into_iter().nth(address.index)) + fn transaction_at(&self, address: &TransactionAddress) -> Option { + self.block(&address.block_hash).map(|bytes| BlockView::new(&bytes).localized_transactions()).and_then(|t| t.into_iter().nth(address.index)) } /// Get a list of transactions for a given block. /// Returns None if block deos not exist. - fn transactions(&self, hash: &H256) -> Option> { - self.block(hash).map(|bytes| BlockView::new(&bytes).transactions()) + fn transactions(&self, hash: &H256) -> Option> { + self.block(hash).map(|bytes| BlockView::new(&bytes).localized_transactions()) } /// Returns reference to genesis hash. diff --git a/ethcore/src/client.rs b/ethcore/src/client.rs index 84d7a7209..002f5bffe 100644 --- a/ethcore/src/client.rs +++ b/ethcore/src/client.rs @@ -31,7 +31,7 @@ use service::{NetSyncMessage, SyncMessage}; use env_info::LastHashes; use verification::*; use block::*; -use transaction::SignedTransaction; +use transaction::LocalizedTransaction; pub use blockchain::TreeRoute; /// General block status @@ -106,7 +106,7 @@ pub trait BlockChainClient : Sync + Send { fn block_total_difficulty_at(&self, n: BlockNumber) -> Option; /// Get transaction with given hash. - fn transaction(&self, hash: &H256) -> Option; + fn transaction(&self, hash: &H256) -> Option; /// Get a tree route between `from` and `to`. /// See `BlockChain::tree_route`. @@ -392,7 +392,7 @@ impl BlockChainClient for Client { self.chain.read().unwrap().block_hash(n).and_then(|h| self.block_total_difficulty(&h)) } - fn transaction(&self, hash: &H256) -> Option { + fn transaction(&self, hash: &H256) -> Option { self.chain.read().unwrap().transaction(hash) } diff --git a/ethcore/src/transaction.rs b/ethcore/src/transaction.rs index c431fe605..2713290bb 100644 --- a/ethcore/src/transaction.rs +++ b/ethcore/src/transaction.rs @@ -19,6 +19,7 @@ use util::*; use error::*; use evm::Schedule; +use header::BlockNumber; #[derive(Debug, Clone, PartialEq, Eq)] /// Transaction action type. @@ -289,6 +290,26 @@ impl SignedTransaction { } } +/// Signed Transaction that is a part of canon blockchain. +pub struct LocalizedTransaction { + /// Signed part. + pub signed: SignedTransaction, + /// Block number. + pub block_number: BlockNumber, + /// Block hash. + pub block_hash: H256, + /// Transaction index within block. + pub transaction_index: usize +} + +impl Deref for LocalizedTransaction { + type Target = SignedTransaction; + + fn deref(&self) -> &Self::Target { + &self.signed + } +} + #[test] fn sender_test() { let t: SignedTransaction = decode(&FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); diff --git a/ethcore/src/views.rs b/ethcore/src/views.rs index 5b6b56ea5..3cfe5f183 100644 --- a/ethcore/src/views.rs +++ b/ethcore/src/views.rs @@ -155,6 +155,22 @@ impl<'a> BlockView<'a> { self.rlp.val_at(1) } + /// Return List of transactions with additional localization info. + pub fn localized_transactions(&self) -> Vec { + let header = self.header_view(); + let block_hash = header.sha3(); + let block_number = header.number(); + self.rlp.val_at::>(1) + .into_iter() + .enumerate() + .map(|(i, t)| LocalizedTransaction { + signed: t, + block_hash: block_hash.clone(), + block_number: block_number, + transaction_index: i + }).collect() + } + /// Return number of transactions in given block, without deserializing them. pub fn transactions_count(&self) -> usize { self.rlp.at(1).iter().count() diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 4ef75bdd2..ef5f5b732 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -97,8 +97,8 @@ impl Eth for EthClient { } fn block_transaction_count(&self, params: Params) -> Result { - match from_params::(params) { - Ok(hash) => match self.client.block(&hash) { + match from_params::<(H256,)>(params) { + Ok((hash,)) => match self.client.block(&hash) { Some(bytes) => to_value(&BlockView::new(&bytes).transactions_count()), None => Ok(Value::Null) }, @@ -107,8 +107,8 @@ impl Eth for EthClient { } fn block_uncles_count(&self, params: Params) -> Result { - match from_params::(params) { - Ok(hash) => match self.client.block(&hash) { + match from_params::<(H256,)>(params) { + Ok((hash,)) => match self.client.block(&hash) { Some(bytes) => to_value(&BlockView::new(&bytes).uncles_count()), None => Ok(Value::Null) }, @@ -164,14 +164,14 @@ impl Eth for EthClient { } fn transaction_at(&self, params: Params) -> Result { - match from_params::(params) { - Ok(hash) => match self.client.transaction(&hash) { + match from_params::<(H256,)>(params) { + Ok((hash,)) => match self.client.transaction(&hash) { Some(t) => to_value(&Transaction { hash: t.hash(), nonce: t.nonce, - block_hash: OptionalValue::Value(H256::default()), // todo - block_number: OptionalValue::Value(U256::default()), // todo - transaction_index: U256::default(), // todo + block_hash: OptionalValue::Value(t.block_hash.clone()), + block_number: OptionalValue::Value(U256::from(t.block_number)), + transaction_index: OptionalValue::Value(U256::from(t.transaction_index)), from: t.sender().unwrap(), to: match t.action { Action::Create => OptionalValue::Null, diff --git a/rpc/src/v1/types/block.rs b/rpc/src/v1/types/block.rs index d3dced686..b92111bcb 100644 --- a/rpc/src/v1/types/block.rs +++ b/rpc/src/v1/types/block.rs @@ -80,7 +80,7 @@ mod tests { fn test_serialize_block_transactions() { let t = BlockTransactions::Full(vec![Transaction::default()]); let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":"0x00","from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x00"}]"#); + assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x00"}]"#); let t = BlockTransactions::Hashes(vec![H256::default()]); let serialized = serde_json::to_string(&t).unwrap(); diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index 147e6d2a7..e45fe033b 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -27,7 +27,7 @@ pub struct Transaction { #[serde(rename="blockNumber")] pub block_number: OptionalValue, #[serde(rename="transactionIndex")] - pub transaction_index: U256, + pub transaction_index: OptionalValue, pub from: Address, pub to: OptionalValue
, pub value: U256, @@ -46,7 +46,7 @@ mod tests { fn test_transaction_serialize() { let t = Transaction::default(); let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":"0x00","from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x00"}"#); + assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x00"}"#); } }