Newer
Older
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()
})
},
_ => None
}
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> {
let chain = self.chain.read();
match chain.is_known(from) && chain.is_known(to) {
true => Some(chain.tree_route(from.clone(), to.clone())),
Marek Kotewicz
committed
false => None
}
fn find_uncles(&self, hash: &H256) -> Option<Vec<H256>> {
self.chain.read().find_uncle_hashes(hash, self.engine.maximum_uncle_age())
fn state_data(&self, hash: &H256) -> Option<Bytes> {
self.state_db.lock().journal_db().state(hash)
fn block_receipts(&self, hash: &H256) -> Option<Bytes> {
self.chain.read().block_receipts(hash).map(|receipts| ::rlp::encode(&receipts).to_vec())
fn import_block(&self, bytes: Bytes) -> Result<H256, BlockImportError> {
asynchronous rob
committed
use verification::queue::kind::HasHash;
use verification::queue::kind::blocks::Unverified;
// create unverified block here so the `sha3` calculation can be cached.
let unverified = Unverified::new(bytes);
asynchronous rob
committed
if self.chain.read().is_known(&unverified.hash()) {
return Err(BlockImportError::Import(ImportError::AlreadyInChain));
asynchronous rob
committed
if self.block_status(BlockID::Hash(unverified.parent_hash())) == BlockStatus::Unknown {
return Err(BlockImportError::Block(BlockError::UnknownParent(unverified.parent_hash())));
asynchronous rob
committed
Ok(try!(self.block_queue.import(unverified)))
fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result<H256, BlockImportError> {
{
// check block order
let header = BlockView::new(&block_bytes).header_view();
if self.chain.read().is_known(&header.hash()) {
return Err(BlockImportError::Import(ImportError::AlreadyInChain));
}
if self.block_status(BlockID::Hash(header.parent_hash())) == BlockStatus::Unknown {
return Err(BlockImportError::Block(BlockError::UnknownParent(header.parent_hash())));
}
}
self.import_old_block(block_bytes, receipts_bytes).map_err(Into::into)
}
fn chain_info(&self) -> BlockChainInfo {
fn additional_params(&self) -> BTreeMap<String, String> {
self.engine.additional_params().into_iter().collect()
}
fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockID, to_block: BlockID) -> Option<Vec<BlockNumber>> {
match (self.block_number(from_block), self.block_number(to_block)) {
(Some(from), Some(to)) => Some(self.chain.read().blocks_with_bloom(bloom, from, to)),
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
let blocks = filter.bloom_possibilities().iter()
.filter_map(|bloom| self.blocks_with_bloom(bloom, filter.from_block.clone(), filter.to_block.clone()))
.flat_map(|m| m)
// remove duplicate elements
.collect::<HashSet<u64>>()
.into_iter()
.collect::<Vec<u64>>();
self.chain.read().logs(blocks, |entry| filter.matches(entry), filter.limit)
fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {
let start = self.block_number(filter.range.start);
let end = self.block_number(filter.range.end);
match (start, end) {
(Some(s), Some(e)) => {
let filter = trace::Filter {
range: s as usize..e as usize,
from_address: From::from(filter.from_address),
to_address: From::from(filter.to_address),
};
let traces = self.tracedb.read().filter(&filter);
Some(traces)
},
_ => None,
}
}
fn trace(&self, trace: TraceId) -> Option<LocalizedTrace> {
let trace_address = trace.address;
self.transaction_address(trace.transaction)
.and_then(|tx_address| {
self.block_number(BlockID::Hash(tx_address.block_hash))
.and_then(|number| self.tracedb.read().trace(number, tx_address.index, trace_address))
fn transaction_traces(&self, transaction: TransactionID) -> Option<Vec<LocalizedTrace>> {
self.transaction_address(transaction)
.and_then(|tx_address| {
self.block_number(BlockID::Hash(tx_address.block_hash))
.and_then(|number| self.tracedb.read().transaction_traces(number, tx_address.index))
fn block_traces(&self, block: BlockID) -> Option<Vec<LocalizedTrace>> {
.and_then(|number| self.tracedb.read().block_traces(number))
fn last_hashes(&self) -> LastHashes {
(*self.build_last_hashes(self.chain.read().best_block_hash())).clone()
fn queue_transactions(&self, transactions: Vec<Bytes>) {
if self.queue_transactions.load(AtomicOrdering::Relaxed) > MAX_TX_QUEUE_SIZE {
debug!("Ignoring {} transactions: queue is full", transactions.len());
} else {
let len = transactions.len();
match self.io_channel.lock().send(ClientIoMessage::NewTransactions(transactions)) {
Ok(_) => {
self.queue_transactions.fetch_add(len, AtomicOrdering::SeqCst);
}
Err(e) => {
debug!("Ignoring {} transactions: error queueing: {}", len, e);
}
}
}
}
fn pending_transactions(&self) -> Vec<SignedTransaction> {
self.miner.pending_transactions(self.chain.read().best_block_number())
Tomusdrw
committed
impl MiningBlockChainClient for Client {
fn latest_schedule(&self) -> Schedule {
let header_data = self.best_block_header();
let view = HeaderView::new(&header_data);
let env_info = EnvInfo {
number: view.number(),
author: view.author(),
timestamp: view.timestamp(),
difficulty: view.difficulty(),
last_hashes: self.build_last_hashes(view.hash()),
gas_used: U256::default(),
gas_limit: view.gas_limit(),
};
self.engine.schedule(&env_info)
}
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
let engine = &*self.engine;
let chain = self.chain.read();
let h = chain.best_block_hash();
self.factories.clone(),
false, // TODO: this will need to be parameterised once we want to do immediate mining insertion.
self.state_db.lock().boxed_clone_canon(&h),
&chain.block_header(&h).expect("h is best block hash: so its header must exist: qed"),
).expect("OpenBlock::new only fails if parent state root invalid; state root of best block's header is never invalid; qed");
.into_iter()
.take(engine.maximum_uncle_count())
.foreach(|h| {
open_block.push_uncle(h).expect("pushing maximum_uncle_count;
open_block was just created;
push_uncle is not ok only if more than maximum_uncle_count is pushed;
so all push_uncle are Ok;
qed");
&self.factories.vm
fn import_sealed_block(&self, block: SealedBlock) -> ImportResult {
let h = block.header().hash();
let start = precise_time_ns();
let route = {
// scope for self.import_lock
let _import_lock = self.import_lock.lock();
let _timer = PerfTimer::new("import_sealed_block");
let number = block.header().number();
let block_data = block.rlp_bytes();
let route = self.commit_block(block, &h, &block_data);
trace!(target: "client", "Imported sealed block #{} ({})", number, h);
self.state_db.lock().sync_cache(&route.enacted, &route.retracted, false);
route
};
let (enacted, retracted) = self.calculate_enacted_retracted(&[route]);
self.miner.chain_new_blocks(self, &[h.clone()], &[], &enacted, &retracted);
self.notify(|notify| {
notify.new_blocks(
vec![h.clone()],
vec![],
enacted.clone(),
retracted.clone(),
vec![h.clone()],
precise_time_ns() - start,
);
});
self.db.read().flush().expect("DB flush failed.");
Tomusdrw
committed
impl MayPanic for Client {
fn on_panic<F>(&self, closure: F) where F: OnPanicListener {
Tomusdrw
committed
self.panic_handler.on_panic(closure);
}
}
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
#[test]
fn should_not_cache_details_before_commit() {
use tests::helpers::*;
use std::thread;
use std::time::Duration;
use std::sync::atomic::{AtomicBool, Ordering};
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.reference().clone();
thread::spawn(move || {
let mut batch = DBTransaction::new(&*another_client.chain.read().db().clone());
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());
}