Newer
Older
fn epoch_signal(&self, hash: H256) -> Option<Vec<u8>> {
// pending transitions are never deleted, and do not contain
// finality proofs by definition.
self.chain.read().get_pending_transition(hash).map(|pending| pending.proof)
impl Drop for Client {
fn drop(&mut self) {
self.engine.stop();
}
}
/// Returns `LocalizedReceipt` given `LocalizedTransaction`
/// and a vector of receipts from given block up to transaction index.
fn transaction_receipt(engine: &Engine, mut tx: LocalizedTransaction, mut receipts: Vec<Receipt>) -> LocalizedReceipt {
assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided.");
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,
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(engine.create_address_scheme(block_number), &sender, &tx.nonce, &tx.data).0)
},
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,
outcome: receipt.outcome,
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
#[cfg(test)]
mod tests {
#[test]
fn should_not_cache_details_before_commit() {
use client::BlockChainClient;
use tests::helpers::*;
use std::thread;
use std::time::Duration;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use util::kvdb::DBTransaction;
let client = generate_dummy_client(0);
let genesis = client.chain_info().best_block_hash;
let (new_hash, new_block) = get_good_dummy_block_hash();
let go = {
// Separate thread uncommited transaction
let go = Arc::new(AtomicBool::new(false));
let go_thread = go.clone();
let another_client = client.clone();
let mut batch = DBTransaction::new();
another_client.chain.read().insert_block(&mut batch, &new_block, Vec::new());
go_thread.store(true, Ordering::SeqCst);
});
go
};
while !go.load(Ordering::SeqCst) { thread::park_timeout(Duration::from_millis(5)); }
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, TransactionOutcome};
use transaction::{Transaction, LocalizedTransaction, Action};
let key = KeyPair::from_secret_slice(&keccak("test")).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 {
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 {
outcome: TransactionOutcome::StateRoot(state_root),
gas_used: 5.into(),
log_bloom: Default::default(),
logs: vec![logs[0].clone()],
}, Receipt {
outcome: TransactionOutcome::StateRoot(state_root),
gas_used: gas_used,
log_bloom: Default::default(),
logs: logs.clone(),
}];
// when
let receipt = transaction_receipt(&engine, transaction, receipts);
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
// 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(),
outcome: TransactionOutcome::StateRoot(state_root),