Correct log index in transaction receipt (#3995)
* Moving logs to separate, testable function * Adding test * Fixing log index * Adding transaction log index * Fixing rpc tests * Making interface of a bit cleaner.
This commit is contained in:
		
							parent
							
								
									9814251a28
								
							
						
					
					
						commit
						b24fc97cb6
					
				| @ -378,7 +378,8 @@ impl BlockProvider for BlockChain { | |||||||
| 					.enumerate() | 					.enumerate() | ||||||
| 					.flat_map(move |(index, (mut logs, tx_hash))| { | 					.flat_map(move |(index, (mut logs, tx_hash))| { | ||||||
| 						let current_log_index = log_index; | 						let current_log_index = log_index; | ||||||
| 						log_index -= logs.len(); | 						let no_of_logs = logs.len(); | ||||||
|  | 						log_index -= no_of_logs; | ||||||
| 
 | 
 | ||||||
| 						logs.reverse(); | 						logs.reverse(); | ||||||
| 						logs.into_iter() | 						logs.into_iter() | ||||||
| @ -390,6 +391,7 @@ impl BlockProvider for BlockChain { | |||||||
| 								transaction_hash: tx_hash, | 								transaction_hash: tx_hash, | ||||||
| 								// iterating in reverse order
 | 								// iterating in reverse order
 | ||||||
| 								transaction_index: receipts_len - index - 1, | 								transaction_index: receipts_len - index - 1, | ||||||
|  | 								transaction_log_index: no_of_logs - i - 1, | ||||||
| 								log_index: current_log_index - i - 1, | 								log_index: current_log_index - i - 1, | ||||||
| 							}) | 							}) | ||||||
| 					}) | 					}) | ||||||
| @ -1936,6 +1938,7 @@ mod tests { | |||||||
| 				block_number: block1.header().number(), | 				block_number: block1.header().number(), | ||||||
| 				transaction_hash: tx_hash1.clone(), | 				transaction_hash: tx_hash1.clone(), | ||||||
| 				transaction_index: 0, | 				transaction_index: 0, | ||||||
|  | 				transaction_log_index: 0, | ||||||
| 				log_index: 0, | 				log_index: 0, | ||||||
| 			}, | 			}, | ||||||
| 			LocalizedLogEntry { | 			LocalizedLogEntry { | ||||||
| @ -1944,6 +1947,7 @@ mod tests { | |||||||
| 				block_number: block1.header().number(), | 				block_number: block1.header().number(), | ||||||
| 				transaction_hash: tx_hash1.clone(), | 				transaction_hash: tx_hash1.clone(), | ||||||
| 				transaction_index: 0, | 				transaction_index: 0, | ||||||
|  | 				transaction_log_index: 1, | ||||||
| 				log_index: 1, | 				log_index: 1, | ||||||
| 			}, | 			}, | ||||||
| 			LocalizedLogEntry { | 			LocalizedLogEntry { | ||||||
| @ -1952,6 +1956,7 @@ mod tests { | |||||||
| 				block_number: block1.header().number(), | 				block_number: block1.header().number(), | ||||||
| 				transaction_hash: tx_hash2.clone(), | 				transaction_hash: tx_hash2.clone(), | ||||||
| 				transaction_index: 1, | 				transaction_index: 1, | ||||||
|  | 				transaction_log_index: 0, | ||||||
| 				log_index: 2, | 				log_index: 2, | ||||||
| 			}, | 			}, | ||||||
| 			LocalizedLogEntry { | 			LocalizedLogEntry { | ||||||
| @ -1960,6 +1965,7 @@ mod tests { | |||||||
| 				block_number: block2.header().number(), | 				block_number: block2.header().number(), | ||||||
| 				transaction_hash: tx_hash3.clone(), | 				transaction_hash: tx_hash3.clone(), | ||||||
| 				transaction_index: 0, | 				transaction_index: 0, | ||||||
|  | 				transaction_log_index: 0, | ||||||
| 				log_index: 0, | 				log_index: 0, | ||||||
| 			} | 			} | ||||||
| 		]); | 		]); | ||||||
| @ -1970,6 +1976,7 @@ mod tests { | |||||||
| 				block_number: block2.header().number(), | 				block_number: block2.header().number(), | ||||||
| 				transaction_hash: tx_hash3.clone(), | 				transaction_hash: tx_hash3.clone(), | ||||||
| 				transaction_index: 0, | 				transaction_index: 0, | ||||||
|  | 				transaction_log_index: 0, | ||||||
| 				log_index: 0, | 				log_index: 0, | ||||||
| 			} | 			} | ||||||
| 		]); | 		]); | ||||||
|  | |||||||
| @ -59,7 +59,7 @@ use client::{ | |||||||
| use client::Error as ClientError; | use client::Error as ClientError; | ||||||
| use env_info::EnvInfo; | use env_info::EnvInfo; | ||||||
| use executive::{Executive, Executed, TransactOptions, contract_address}; | use executive::{Executive, Executed, TransactOptions, contract_address}; | ||||||
| use receipt::LocalizedReceipt; | use receipt::{Receipt, LocalizedReceipt}; | ||||||
| use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase}; | use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase}; | ||||||
| use trace; | use trace; | ||||||
| use trace::FlatTransactionTraces; | use trace::FlatTransactionTraces; | ||||||
| @ -837,7 +837,6 @@ impl snapshot::DatabaseRestore for Client { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| impl BlockChainClient for Client { | impl BlockChainClient for Client { | ||||||
| 	fn call(&self, t: &SignedTransaction, block: BlockId, analytics: CallAnalytics) -> Result<Executed, CallError> { | 	fn call(&self, t: &SignedTransaction, block: BlockId, analytics: CallAnalytics) -> Result<Executed, CallError> { | ||||||
| 		let header = self.block_header(block).ok_or(CallError::StatePruned)?; | 		let header = self.block_header(block).ok_or(CallError::StatePruned)?; | ||||||
| @ -1134,53 +1133,23 @@ impl BlockChainClient for Client { | |||||||
| 		let chain = self.chain.read(); | 		let chain = self.chain.read(); | ||||||
| 		self.transaction_address(id) | 		self.transaction_address(id) | ||||||
| 			.and_then(|address| chain.block_number(&address.block_hash).and_then(|block_number| { | 			.and_then(|address| chain.block_number(&address.block_hash).and_then(|block_number| { | ||||||
| 			let t = chain.block_body(&address.block_hash) | 				let transaction = chain.block_body(&address.block_hash) | ||||||
| 				.and_then(|body| { | 					.and_then(|body| body.view().localized_transaction_at(&address.block_hash, block_number, address.index)); | ||||||
| 					body.view().localized_transaction_at(&address.block_hash, block_number, address.index) |  | ||||||
| 				}); |  | ||||||
| 
 | 
 | ||||||
| 			let tx_and_sender = t.and_then(|tx| tx.sender().ok().map(|sender| (tx, sender))); | 				let previous_receipts = (0..address.index + 1) | ||||||
| 
 | 					.map(|index| { | ||||||
| 			match (tx_and_sender, chain.transaction_receipt(&address)) { | 						let mut address = address.clone(); | ||||||
| 				(Some((tx, sender)), Some(receipt)) => { | 						address.index = index; | ||||||
| 					let block_hash = tx.block_hash.clone(); | 						chain.transaction_receipt(&address) | ||||||
| 					let block_number = tx.block_number.clone(); |  | ||||||
| 					let transaction_hash = tx.hash(); |  | ||||||
| 					let transaction_index = tx.transaction_index; |  | ||||||
| 					let prior_gas_used = match tx.transaction_index { |  | ||||||
| 						0 => U256::zero(), |  | ||||||
| 						i => { |  | ||||||
| 							let prior_address = TransactionAddress { block_hash: address.block_hash, index: i - 1 }; |  | ||||||
| 							let prior_receipt = chain.transaction_receipt(&prior_address).expect("Transaction receipt at `address` exists; `prior_address` has lower index in same block; qed"); |  | ||||||
| 							prior_receipt.gas_used |  | ||||||
| 						} |  | ||||||
| 					}; |  | ||||||
| 					Some(LocalizedReceipt { |  | ||||||
| 						transaction_hash: tx.hash(), |  | ||||||
| 						transaction_index: tx.transaction_index, |  | ||||||
| 						block_hash: tx.block_hash, |  | ||||||
| 						block_number: tx.block_number, |  | ||||||
| 						cumulative_gas_used: receipt.gas_used, |  | ||||||
| 						gas_used: receipt.gas_used - prior_gas_used, |  | ||||||
| 						contract_address: match tx.action { |  | ||||||
| 							Action::Call(_) => None, |  | ||||||
| 							Action::Create => Some(contract_address(&sender, &tx.nonce)) |  | ||||||
| 						}, |  | ||||||
| 						logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry { |  | ||||||
| 							entry: log, |  | ||||||
| 							block_hash: block_hash.clone(), |  | ||||||
| 							block_number: block_number, |  | ||||||
| 							transaction_hash: transaction_hash.clone(), |  | ||||||
| 							transaction_index: transaction_index, |  | ||||||
| 							log_index: i |  | ||||||
| 						}).collect(), |  | ||||||
| 						log_bloom: receipt.log_bloom, |  | ||||||
| 						state_root: receipt.state_root, |  | ||||||
| 					}) | 					}) | ||||||
| 				}, | 					.collect(); | ||||||
| 				_ => None | 				match (transaction, previous_receipts) { | ||||||
| 			} | 					(Some(transaction), Some(previous_receipts)) => { | ||||||
| 		})) | 						Some(transaction_receipt(transaction, previous_receipts)) | ||||||
|  | 					}, | ||||||
|  | 					_ => None, | ||||||
|  | 				} | ||||||
|  | 			})) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> { | 	fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> { | ||||||
| @ -1535,6 +1504,49 @@ impl Drop for Client { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /// Returns `LocalizedReceipt` given `LocalizedTransaction`
 | ||||||
|  | /// and a vector of receipts from given block up to transaction index.
 | ||||||
|  | fn transaction_receipt(tx: LocalizedTransaction, mut receipts: Vec<Receipt>) -> LocalizedReceipt { | ||||||
|  | 	assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided."); | ||||||
|  | 
 | ||||||
|  | 	let sender = tx.sender() | ||||||
|  | 		.expect("LocalizedTransaction is part of the blockchain; We have only valid transactions in chain; qed"); | ||||||
|  | 	let receipt = receipts.pop().expect("Current receipt is provided; qed"); | ||||||
|  | 	let prior_gas_used = match tx.transaction_index { | ||||||
|  | 		0 => 0.into(), | ||||||
|  | 		i => receipts.get(i - 1).expect("All previous receipts are provided; qed").gas_used, | ||||||
|  | 	}; | ||||||
|  | 	let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::<usize>(); | ||||||
|  | 	let transaction_hash = tx.hash(); | ||||||
|  | 	let block_hash = tx.block_hash; | ||||||
|  | 	let block_number = tx.block_number; | ||||||
|  | 	let transaction_index = tx.transaction_index; | ||||||
|  | 
 | ||||||
|  | 	LocalizedReceipt { | ||||||
|  | 		transaction_hash: transaction_hash, | ||||||
|  | 		transaction_index: transaction_index, | ||||||
|  | 		block_hash: block_hash, | ||||||
|  | 		block_number:block_number, | ||||||
|  | 		cumulative_gas_used: receipt.gas_used, | ||||||
|  | 		gas_used: receipt.gas_used - prior_gas_used, | ||||||
|  | 		contract_address: match tx.action { | ||||||
|  | 			Action::Call(_) => None, | ||||||
|  | 			Action::Create => Some(contract_address(&sender, &tx.nonce)) | ||||||
|  | 		}, | ||||||
|  | 		logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry { | ||||||
|  | 			entry: log, | ||||||
|  | 			block_hash: block_hash, | ||||||
|  | 			block_number: block_number, | ||||||
|  | 			transaction_hash: transaction_hash, | ||||||
|  | 			transaction_index: transaction_index, | ||||||
|  | 			transaction_log_index: i, | ||||||
|  | 			log_index: no_of_logs + i, | ||||||
|  | 		}).collect(), | ||||||
|  | 		log_bloom: receipt.log_bloom, | ||||||
|  | 		state_root: receipt.state_root, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod tests { | mod tests { | ||||||
| 
 | 
 | ||||||
| @ -1570,4 +1582,91 @@ mod tests { | |||||||
| 
 | 
 | ||||||
| 		assert!(client.tree_route(&genesis, &new_hash).is_none()); | 		assert!(client.tree_route(&genesis, &new_hash).is_none()); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	#[test] | ||||||
|  | 	fn should_return_correct_log_index() { | ||||||
|  | 		use super::transaction_receipt; | ||||||
|  | 		use ethkey::KeyPair; | ||||||
|  | 		use log_entry::{LogEntry, LocalizedLogEntry}; | ||||||
|  | 		use receipt::{Receipt, LocalizedReceipt}; | ||||||
|  | 		use transaction::{Transaction, LocalizedTransaction, Action}; | ||||||
|  | 		use util::Hashable; | ||||||
|  | 
 | ||||||
|  | 		// given
 | ||||||
|  | 		let key = KeyPair::from_secret("test".sha3()).unwrap(); | ||||||
|  | 		let secret = key.secret(); | ||||||
|  | 
 | ||||||
|  | 		let block_number = 1; | ||||||
|  | 		let block_hash = 5.into(); | ||||||
|  | 		let state_root = 99.into(); | ||||||
|  | 		let gas_used = 10.into(); | ||||||
|  | 		let raw_tx = Transaction { | ||||||
|  | 			nonce: 0.into(), | ||||||
|  | 			gas_price: 0.into(), | ||||||
|  | 			gas: 21000.into(), | ||||||
|  | 			action: Action::Call(10.into()), | ||||||
|  | 			value: 0.into(), | ||||||
|  | 			data: vec![], | ||||||
|  | 		}; | ||||||
|  | 		let tx1 = raw_tx.clone().sign(secret, None); | ||||||
|  | 		let transaction = LocalizedTransaction { | ||||||
|  | 			signed: tx1.clone(), | ||||||
|  | 			block_number: block_number, | ||||||
|  | 			block_hash: block_hash, | ||||||
|  | 			transaction_index: 1, | ||||||
|  | 		}; | ||||||
|  | 		let logs = vec![LogEntry { | ||||||
|  | 			address: 5.into(), | ||||||
|  | 			topics: vec![], | ||||||
|  | 			data: vec![], | ||||||
|  | 		}, LogEntry { | ||||||
|  | 			address: 15.into(), | ||||||
|  | 			topics: vec![], | ||||||
|  | 			data: vec![], | ||||||
|  | 		}]; | ||||||
|  | 		let receipts = vec![Receipt { | ||||||
|  | 			state_root: state_root, | ||||||
|  | 			gas_used: 5.into(), | ||||||
|  | 			log_bloom: Default::default(), | ||||||
|  | 			logs: vec![logs[0].clone()], | ||||||
|  | 		}, Receipt { | ||||||
|  | 			state_root: state_root, | ||||||
|  | 			gas_used: gas_used, | ||||||
|  | 			log_bloom: Default::default(), | ||||||
|  | 			logs: logs.clone(), | ||||||
|  | 		}]; | ||||||
|  | 
 | ||||||
|  | 		// when
 | ||||||
|  | 		let receipt = transaction_receipt(transaction, receipts); | ||||||
|  | 
 | ||||||
|  | 		// then
 | ||||||
|  | 		assert_eq!(receipt, LocalizedReceipt { | ||||||
|  | 			transaction_hash: tx1.hash(), | ||||||
|  | 			transaction_index: 1, | ||||||
|  | 			block_hash: block_hash, | ||||||
|  | 			block_number: block_number, | ||||||
|  | 			cumulative_gas_used: gas_used, | ||||||
|  | 			gas_used: gas_used - 5.into(), | ||||||
|  | 			contract_address: None, | ||||||
|  | 			logs: vec![LocalizedLogEntry { | ||||||
|  | 				entry: logs[0].clone(), | ||||||
|  | 				block_hash: block_hash, | ||||||
|  | 				block_number: block_number, | ||||||
|  | 				transaction_hash: tx1.hash(), | ||||||
|  | 				transaction_index: 1, | ||||||
|  | 				transaction_log_index: 0, | ||||||
|  | 				log_index: 1, | ||||||
|  | 			}, LocalizedLogEntry { | ||||||
|  | 				entry: logs[1].clone(), | ||||||
|  | 				block_hash: block_hash, | ||||||
|  | 				block_number: block_number, | ||||||
|  | 				transaction_hash: tx1.hash(), | ||||||
|  | 				transaction_index: 1, | ||||||
|  | 				transaction_log_index: 1, | ||||||
|  | 				log_index: 2, | ||||||
|  | 			}], | ||||||
|  | 			log_bloom: Default::default(), | ||||||
|  | 			state_root: state_root, | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -320,4 +320,3 @@ fn does_not_propagate_delayed_transactions() { | |||||||
| 	assert_eq!(2, client.ready_transactions().len()); | 	assert_eq!(2, client.ready_transactions().len()); | ||||||
| 	assert_eq!(2, client.miner().pending_transactions().len()); | 	assert_eq!(2, client.miner().pending_transactions().len()); | ||||||
| } | } | ||||||
| 
 |  | ||||||
|  | |||||||
| @ -97,6 +97,8 @@ pub struct LocalizedLogEntry { | |||||||
| 	pub transaction_index: usize, | 	pub transaction_index: usize, | ||||||
| 	/// Log position in the block.
 | 	/// Log position in the block.
 | ||||||
| 	pub log_index: usize, | 	pub log_index: usize, | ||||||
|  | 	/// Log position in the transaction.
 | ||||||
|  | 	pub transaction_log_index: usize, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Deref for LocalizedLogEntry { | impl Deref for LocalizedLogEntry { | ||||||
|  | |||||||
| @ -373,7 +373,7 @@ impl SignedTransaction { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Signed Transaction that is a part of canon blockchain.
 | /// Signed Transaction that is a part of canon blockchain.
 | ||||||
| #[derive(Debug, PartialEq, Eq)] | #[derive(Debug, Clone, PartialEq, Eq)] | ||||||
| #[cfg_attr(feature = "ipc", binary)] | #[cfg_attr(feature = "ipc", binary)] | ||||||
| pub struct LocalizedTransaction { | pub struct LocalizedTransaction { | ||||||
| 	/// Signed part.
 | 	/// Signed part.
 | ||||||
|  | |||||||
| @ -193,6 +193,7 @@ fn rpc_eth_logs() { | |||||||
| 			data: vec![1,2,3], | 			data: vec![1,2,3], | ||||||
| 		}, | 		}, | ||||||
| 		transaction_index: 0, | 		transaction_index: 0, | ||||||
|  | 		transaction_log_index: 0, | ||||||
| 		transaction_hash: H256::default(), | 		transaction_hash: H256::default(), | ||||||
| 		log_index: 0, | 		log_index: 0, | ||||||
| 	}, LocalizedLogEntry { | 	}, LocalizedLogEntry { | ||||||
| @ -204,8 +205,9 @@ fn rpc_eth_logs() { | |||||||
| 			data: vec![1,2,3], | 			data: vec![1,2,3], | ||||||
| 		}, | 		}, | ||||||
| 		transaction_index: 0, | 		transaction_index: 0, | ||||||
|  | 		transaction_log_index: 1, | ||||||
| 		transaction_hash: H256::default(), | 		transaction_hash: H256::default(), | ||||||
| 		log_index: 0, | 		log_index: 1, | ||||||
| 	}]); | 	}]); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -213,8 +215,8 @@ fn rpc_eth_logs() { | |||||||
| 	let request2 = r#"{"jsonrpc": "2.0", "method": "eth_getLogs", "params": [{"limit":1}], "id": 1}"#; | 	let request2 = r#"{"jsonrpc": "2.0", "method": "eth_getLogs", "params": [{"limit":1}], "id": 1}"#; | ||||||
| 	let request3 = r#"{"jsonrpc": "2.0", "method": "eth_getLogs", "params": [{"limit":0}], "id": 1}"#; | 	let request3 = r#"{"jsonrpc": "2.0", "method": "eth_getLogs", "params": [{"limit":0}], "id": 1}"#; | ||||||
| 
 | 
 | ||||||
| 	let response1 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"},{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"id":1}"#; | 	let response1 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"},{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x1","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x1","type":"mined"}],"id":1}"#; | ||||||
| 	let response2 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"id":1}"#; | 	let response2 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x1","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x1","type":"mined"}],"id":1}"#; | ||||||
| 	let response3 = r#"{"jsonrpc":"2.0","result":[],"id":1}"#; | 	let response3 = r#"{"jsonrpc":"2.0","result":[],"id":1}"#; | ||||||
| 
 | 
 | ||||||
| 	assert_eq!(tester.io.handle_request_sync(request1), Some(response1.to_owned())); | 	assert_eq!(tester.io.handle_request_sync(request1), Some(response1.to_owned())); | ||||||
| @ -235,6 +237,7 @@ fn rpc_logs_filter() { | |||||||
| 			data: vec![1,2,3], | 			data: vec![1,2,3], | ||||||
| 		}, | 		}, | ||||||
| 		transaction_index: 0, | 		transaction_index: 0, | ||||||
|  | 		transaction_log_index: 0, | ||||||
| 		transaction_hash: H256::default(), | 		transaction_hash: H256::default(), | ||||||
| 		log_index: 0, | 		log_index: 0, | ||||||
| 	}, LocalizedLogEntry { | 	}, LocalizedLogEntry { | ||||||
| @ -246,8 +249,9 @@ fn rpc_logs_filter() { | |||||||
| 			data: vec![1,2,3], | 			data: vec![1,2,3], | ||||||
| 		}, | 		}, | ||||||
| 		transaction_index: 0, | 		transaction_index: 0, | ||||||
|  | 		transaction_log_index: 1, | ||||||
| 		transaction_hash: H256::default(), | 		transaction_hash: H256::default(), | ||||||
| 		log_index: 0, | 		log_index: 1, | ||||||
| 	}]); | 	}]); | ||||||
| 
 | 
 | ||||||
| 	// Register filters first
 | 	// Register filters first
 | ||||||
| @ -261,8 +265,8 @@ fn rpc_logs_filter() { | |||||||
| 
 | 
 | ||||||
| 	let request_changes1 = r#"{"jsonrpc": "2.0", "method": "eth_getFilterChanges", "params": ["0x0"], "id": 1}"#; | 	let request_changes1 = r#"{"jsonrpc": "2.0", "method": "eth_getFilterChanges", "params": ["0x0"], "id": 1}"#; | ||||||
| 	let request_changes2 = r#"{"jsonrpc": "2.0", "method": "eth_getFilterChanges", "params": ["0x1"], "id": 1}"#; | 	let request_changes2 = r#"{"jsonrpc": "2.0", "method": "eth_getFilterChanges", "params": ["0x1"], "id": 1}"#; | ||||||
| 	let response1 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"},{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"id":1}"#; | 	let response1 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"},{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x1","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x1","type":"mined"}],"id":1}"#; | ||||||
| 	let response2 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x0","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"id":1}"#; | 	let response2 = r#"{"jsonrpc":"2.0","result":[{"address":"0x0000000000000000000000000000000000000000","blockHash":"0x0000000000000000000000000000000000000000000000000000000000000000","blockNumber":"0x1","data":"0x010203","logIndex":"0x1","topics":[],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x1","type":"mined"}],"id":1}"#; | ||||||
| 
 | 
 | ||||||
| 	assert_eq!(tester.io.handle_request_sync(request_changes1), Some(response1.to_owned())); | 	assert_eq!(tester.io.handle_request_sync(request_changes1), Some(response1.to_owned())); | ||||||
| 	assert_eq!(tester.io.handle_request_sync(request_changes2), Some(response2.to_owned())); | 	assert_eq!(tester.io.handle_request_sync(request_changes2), Some(response2.to_owned())); | ||||||
| @ -951,6 +955,7 @@ fn rpc_eth_transaction_receipt() { | |||||||
| 			block_number: 0x4510c, | 			block_number: 0x4510c, | ||||||
| 			transaction_hash: H256::new(), | 			transaction_hash: H256::new(), | ||||||
| 			transaction_index: 0, | 			transaction_index: 0, | ||||||
|  | 			transaction_log_index: 0, | ||||||
| 			log_index: 1, | 			log_index: 1, | ||||||
| 		}], | 		}], | ||||||
| 		log_bloom: 0.into(), | 		log_bloom: 0.into(), | ||||||
| @ -967,7 +972,7 @@ fn rpc_eth_transaction_receipt() { | |||||||
| 		"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], | 		"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"], | ||||||
| 		"id": 1 | 		"id": 1 | ||||||
| 	}"#;
 | 	}"#;
 | ||||||
| 	let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","type":"mined"}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0"},"id":1}"#; | 	let response = r#"{"jsonrpc":"2.0","result":{"blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","contractAddress":null,"cumulativeGasUsed":"0x20","gasUsed":"0x10","logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","data":"0x","logIndex":"0x1","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","transactionLogIndex":"0x0","type":"mined"}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","root":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0"},"id":1}"#; | ||||||
| 
 | 
 | ||||||
| 	assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); | 	assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); | ||||||
| } | } | ||||||
|  | |||||||
| @ -38,9 +38,12 @@ pub struct Log { | |||||||
| 	/// Transaction Index
 | 	/// Transaction Index
 | ||||||
| 	#[serde(rename="transactionIndex")] | 	#[serde(rename="transactionIndex")] | ||||||
| 	pub transaction_index: Option<U256>, | 	pub transaction_index: Option<U256>, | ||||||
| 	/// Log Index
 | 	/// Log Index in Block
 | ||||||
| 	#[serde(rename="logIndex")] | 	#[serde(rename="logIndex")] | ||||||
| 	pub log_index: Option<U256>, | 	pub log_index: Option<U256>, | ||||||
|  | 	/// Log Index in Transaction
 | ||||||
|  | 	#[serde(rename="transactionLogIndex")] | ||||||
|  | 	pub transaction_log_index: Option<U256>, | ||||||
| 	/// Log Type
 | 	/// Log Type
 | ||||||
| 	#[serde(rename="type")] | 	#[serde(rename="type")] | ||||||
| 	pub log_type: String, | 	pub log_type: String, | ||||||
| @ -57,6 +60,7 @@ impl From<LocalizedLogEntry> for Log { | |||||||
| 			transaction_hash: Some(e.transaction_hash.into()), | 			transaction_hash: Some(e.transaction_hash.into()), | ||||||
| 			transaction_index: Some(e.transaction_index.into()), | 			transaction_index: Some(e.transaction_index.into()), | ||||||
| 			log_index: Some(e.log_index.into()), | 			log_index: Some(e.log_index.into()), | ||||||
|  | 			transaction_log_index: Some(e.transaction_log_index.into()), | ||||||
| 			log_type: "mined".to_owned(), | 			log_type: "mined".to_owned(), | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @ -73,6 +77,7 @@ impl From<LogEntry> for Log { | |||||||
| 			transaction_hash: None, | 			transaction_hash: None, | ||||||
| 			transaction_index: None, | 			transaction_index: None, | ||||||
| 			log_index: None, | 			log_index: None, | ||||||
|  | 			transaction_log_index: None, | ||||||
| 			log_type: "pending".to_owned(), | 			log_type: "pending".to_owned(), | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @ -86,7 +91,7 @@ mod tests { | |||||||
| 
 | 
 | ||||||
| 	#[test] | 	#[test] | ||||||
| 	fn log_serialization() { | 	fn log_serialization() { | ||||||
| 		let s = r#"{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","type":"mined"}"#; | 		let s = r#"{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","transactionLogIndex":"0x1","type":"mined"}"#; | ||||||
| 
 | 
 | ||||||
| 		let log = Log { | 		let log = Log { | ||||||
| 			address: H160::from_str("33990122638b9132ca29c723bdf037f1a891a70c").unwrap(), | 			address: H160::from_str("33990122638b9132ca29c723bdf037f1a891a70c").unwrap(), | ||||||
| @ -99,6 +104,7 @@ mod tests { | |||||||
| 			block_number: Some(U256::from(0x4510c)), | 			block_number: Some(U256::from(0x4510c)), | ||||||
| 			transaction_hash: Some(H256::default()), | 			transaction_hash: Some(H256::default()), | ||||||
| 			transaction_index: Some(U256::default()), | 			transaction_index: Some(U256::default()), | ||||||
|  | 			transaction_log_index: Some(1.into()), | ||||||
| 			log_index: Some(U256::from(1)), | 			log_index: Some(U256::from(1)), | ||||||
| 			log_type: "mined".to_owned(), | 			log_type: "mined".to_owned(), | ||||||
| 		}; | 		}; | ||||||
|  | |||||||
| @ -109,7 +109,7 @@ mod tests { | |||||||
| 
 | 
 | ||||||
| 	#[test] | 	#[test] | ||||||
| 	fn receipt_serialization() { | 	fn receipt_serialization() { | ||||||
| 		let s = r#"{"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","type":"mined"}],"root":"0x000000000000000000000000000000000000000000000000000000000000000a","logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f"}"#; | 		let s = r#"{"transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","cumulativeGasUsed":"0x20","gasUsed":"0x10","contractAddress":null,"logs":[{"address":"0x33990122638b9132ca29c723bdf037f1a891a70c","topics":["0xa6697e974e6a320f454390be03f74955e8978f1a6971ea6730542e37b66179bc","0x4861736852656700000000000000000000000000000000000000000000000000"],"data":"0x","blockHash":"0xed76641c68a1c641aee09a94b3b471f4dc0316efe5ac19cf488e2674cf8d05b5","blockNumber":"0x4510c","transactionHash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionIndex":"0x0","logIndex":"0x1","transactionLogIndex":null,"type":"mined"}],"root":"0x000000000000000000000000000000000000000000000000000000000000000a","logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f"}"#; | ||||||
| 
 | 
 | ||||||
| 		let receipt = Receipt { | 		let receipt = Receipt { | ||||||
| 			transaction_hash: Some(0.into()), | 			transaction_hash: Some(0.into()), | ||||||
| @ -130,6 +130,7 @@ mod tests { | |||||||
| 				block_number: Some(0x4510c.into()), | 				block_number: Some(0x4510c.into()), | ||||||
| 				transaction_hash: Some(0.into()), | 				transaction_hash: Some(0.into()), | ||||||
| 				transaction_index: Some(0.into()), | 				transaction_index: Some(0.into()), | ||||||
|  | 				transaction_log_index: None, | ||||||
| 				log_index: Some(1.into()), | 				log_index: Some(1.into()), | ||||||
| 				log_type: "mined".into(), | 				log_type: "mined".into(), | ||||||
| 			}], | 			}], | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user