Fix queue flush and add working tests.
This commit is contained in:
parent
a43ca9ae34
commit
41508cbd50
@ -188,6 +188,7 @@ impl<'x, 'y> OpenBlock<'x, 'y> {
|
|||||||
// info!("env_info says gas_used={}", env_info.gas_used);
|
// info!("env_info says gas_used={}", env_info.gas_used);
|
||||||
match self.block.state.apply(&env_info, self.engine, &t) {
|
match self.block.state.apply(&env_info, self.engine, &t) {
|
||||||
Ok(receipt) => {
|
Ok(receipt) => {
|
||||||
|
flushln!("Transaction executed {:?}", receipt);
|
||||||
self.block.archive_set.insert(h.unwrap_or_else(||t.hash()));
|
self.block.archive_set.insert(h.unwrap_or_else(||t.hash()));
|
||||||
self.block.archive.push(Entry { transaction: t, receipt: receipt });
|
self.block.archive.push(Entry { transaction: t, receipt: receipt });
|
||||||
Ok(&self.block.archive.last().unwrap().receipt)
|
Ok(&self.block.archive.last().unwrap().receipt)
|
||||||
|
@ -19,11 +19,16 @@ pub struct BlockQueueInfo {
|
|||||||
pub unverified_queue_size: usize,
|
pub unverified_queue_size: usize,
|
||||||
/// Number of verified queued blocks pending import
|
/// Number of verified queued blocks pending import
|
||||||
pub verified_queue_size: usize,
|
pub verified_queue_size: usize,
|
||||||
|
/// Number of blocks being verified
|
||||||
|
pub verifying_queue_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockQueueInfo {
|
impl BlockQueueInfo {
|
||||||
/// The total size of the queues.
|
/// The total size of the queues.
|
||||||
pub fn total_queue_size(&self) -> usize { self.unverified_queue_size + self.verified_queue_size }
|
pub fn total_queue_size(&self) -> usize { self.unverified_queue_size + self.verified_queue_size + self.verifying_queue_size }
|
||||||
|
|
||||||
|
/// The size of the unverified and verifying queues.
|
||||||
|
pub fn incomplete_queue_size(&self) -> usize { self.unverified_queue_size + self.verifying_queue_size }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A queue of blocks. Sits between network or other I/O and the BlockChain.
|
/// A queue of blocks. Sits between network or other I/O and the BlockChain.
|
||||||
@ -91,7 +96,7 @@ impl BlockQueue {
|
|||||||
let ready_signal = ready_signal.clone();
|
let ready_signal = ready_signal.clone();
|
||||||
let empty = empty.clone();
|
let empty = empty.clone();
|
||||||
let deleting = deleting.clone();
|
let deleting = deleting.clone();
|
||||||
verifiers.push(thread::Builder::new().name(format!("Verifier #{}", i)).spawn(move || BlockQueue::verify(verification, engine, more_to_verify, ready_signal, deleting, empty))
|
verifiers.push(thread::Builder::new().name(format!("Verifier #{}", i)).spawn(move || BlockQueue::verify(verification, engine, more_to_verify, ready_signal, deleting, empty))
|
||||||
.expect("Error starting block verification thread"));
|
.expect("Error starting block verification thread"));
|
||||||
}
|
}
|
||||||
BlockQueue {
|
BlockQueue {
|
||||||
@ -115,7 +120,6 @@ impl BlockQueue {
|
|||||||
empty.notify_all();
|
empty.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
while lock.unverified.is_empty() && !deleting.load(AtomicOrdering::Relaxed) {
|
while lock.unverified.is_empty() && !deleting.load(AtomicOrdering::Relaxed) {
|
||||||
lock = wait.wait(lock).unwrap();
|
lock = wait.wait(lock).unwrap();
|
||||||
}
|
}
|
||||||
@ -154,7 +158,6 @@ impl BlockQueue {
|
|||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let mut v = verification.lock().unwrap();
|
let mut v = verification.lock().unwrap();
|
||||||
flushln!("Stage 2 block verification failed for {}\nError: {:?}", block_hash, err);
|
|
||||||
warn!(target: "client", "Stage 2 block verification failed for {}\nError: {:?}", block_hash, err);
|
warn!(target: "client", "Stage 2 block verification failed for {}\nError: {:?}", block_hash, err);
|
||||||
v.bad.insert(block_hash.clone());
|
v.bad.insert(block_hash.clone());
|
||||||
v.verifying.retain(|e| e.hash != block_hash);
|
v.verifying.retain(|e| e.hash != block_hash);
|
||||||
@ -187,9 +190,10 @@ impl BlockQueue {
|
|||||||
|
|
||||||
/// Wait for queue to be empty
|
/// Wait for queue to be empty
|
||||||
pub fn flush(&mut self) {
|
pub fn flush(&mut self) {
|
||||||
let mutex: Mutex<()> = Mutex::new(());
|
let mut verification = self.verification.lock().unwrap();
|
||||||
let lock = mutex.lock().unwrap();
|
while !verification.unverified.is_empty() && !verification.verifying.is_empty() {
|
||||||
let _ = self.empty.wait(lock).unwrap();
|
verification = self.empty.wait(verification).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a block to the queue.
|
/// Add a block to the queue.
|
||||||
@ -265,6 +269,7 @@ impl BlockQueue {
|
|||||||
full: false,
|
full: false,
|
||||||
verified_queue_size: verification.verified.len(),
|
verified_queue_size: verification.verified.len(),
|
||||||
unverified_queue_size: verification.unverified.len(),
|
unverified_queue_size: verification.unverified.len(),
|
||||||
|
verifying_queue_size: verification.verifying.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,6 @@ impl Client {
|
|||||||
|
|
||||||
/// Flush the block import queue.
|
/// Flush the block import queue.
|
||||||
pub fn flush_queue(&self) {
|
pub fn flush_queue(&self) {
|
||||||
flushln!("Flushing queue {:?}", self.block_queue.read().unwrap().queue_info());
|
|
||||||
self.block_queue.write().unwrap().flush();
|
self.block_queue.write().unwrap().flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,9 +188,8 @@ impl Client {
|
|||||||
pub fn import_verified_blocks(&self, _io: &IoChannel<NetSyncMessage>) {
|
pub fn import_verified_blocks(&self, _io: &IoChannel<NetSyncMessage>) {
|
||||||
let mut bad = HashSet::new();
|
let mut bad = HashSet::new();
|
||||||
let _import_lock = self.import_lock.lock();
|
let _import_lock = self.import_lock.lock();
|
||||||
|
let blocks = self.block_queue.write().unwrap().drain(128);
|
||||||
for block in self.block_queue.write().unwrap().drain(128) {
|
for block in blocks {
|
||||||
flushln!("Importing block...");
|
|
||||||
if bad.contains(&block.header.parent_hash) {
|
if bad.contains(&block.header.parent_hash) {
|
||||||
self.block_queue.write().unwrap().mark_as_bad(&block.header.hash());
|
self.block_queue.write().unwrap().mark_as_bad(&block.header.hash());
|
||||||
bad.insert(block.header.hash());
|
bad.insert(block.header.hash());
|
||||||
@ -238,6 +236,7 @@ impl Client {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Err(e) = verify_block_final(&header, result.block().header()) {
|
if let Err(e) = verify_block_final(&header, result.block().header()) {
|
||||||
|
flushln!("Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||||
warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||||
self.block_queue.write().unwrap().mark_as_bad(&header.hash());
|
self.block_queue.write().unwrap().mark_as_bad(&header.hash());
|
||||||
return;
|
return;
|
||||||
|
13
src/spec.rs
13
src/spec.rs
@ -80,7 +80,7 @@ pub struct Spec {
|
|||||||
/// TODO [arkpar] Please document me
|
/// TODO [arkpar] Please document me
|
||||||
pub extra_data: Bytes,
|
pub extra_data: Bytes,
|
||||||
/// TODO [Gav Wood] Please document me
|
/// TODO [Gav Wood] Please document me
|
||||||
pub genesis_state: PodState,
|
genesis_state: PodState,
|
||||||
/// TODO [Gav Wood] Please document me
|
/// TODO [Gav Wood] Please document me
|
||||||
pub seal_fields: usize,
|
pub seal_fields: usize,
|
||||||
/// TODO [Gav Wood] Please document me
|
/// TODO [Gav Wood] Please document me
|
||||||
@ -182,6 +182,17 @@ impl Spec {
|
|||||||
self.seal_rlp = seal_rlp;
|
self.seal_rlp = seal_rlp;
|
||||||
self.state_root_memo = RwLock::new(genesis.find("stateRoot").and_then(|_| Some(H256::from_json(&genesis["stateRoot"]))));
|
self.state_root_memo = RwLock::new(genesis.find("stateRoot").and_then(|_| Some(H256::from_json(&genesis["stateRoot"]))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Alter the value of the genesis state.
|
||||||
|
pub fn set_genesis_state(&mut self, s: PodState) {
|
||||||
|
self.genesis_state = s;
|
||||||
|
*self.state_root_memo.write().unwrap() = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `false` if the memoized state root is invalid. `true` otherwise.
|
||||||
|
pub fn is_state_root_valid(&self) -> bool {
|
||||||
|
self.state_root_memo.read().unwrap().clone().map_or(true, |sr| sr == self.genesis_state.root())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromJson for Spec {
|
impl FromJson for Spec {
|
||||||
|
@ -146,15 +146,15 @@ impl State {
|
|||||||
/// This will change the state accordingly.
|
/// This will change the state accordingly.
|
||||||
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &Transaction) -> ApplyResult {
|
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &Transaction) -> ApplyResult {
|
||||||
|
|
||||||
let old = self.to_pod();
|
// let old = self.to_pod();
|
||||||
|
|
||||||
let e = try!(Executive::new(self, env_info, engine).transact(t));
|
let e = try!(Executive::new(self, env_info, engine).transact(t));
|
||||||
//println!("Executed: {:?}", e);
|
//println!("Executed: {:?}", e);
|
||||||
|
|
||||||
trace!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod()));
|
// trace!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod()));
|
||||||
self.commit();
|
self.commit();
|
||||||
let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs);
|
let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs);
|
||||||
trace!("Transaction receipt: {:?}", receipt);
|
// trace!("Transaction receipt: {:?}", receipt);
|
||||||
Ok(receipt)
|
Ok(receipt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +158,7 @@ impl BlockChainClient for TestBlockChainClient {
|
|||||||
full: false,
|
full: false,
|
||||||
verified_queue_size: 0,
|
verified_queue_size: 0,
|
||||||
unverified_queue_size: 0,
|
unverified_queue_size: 0,
|
||||||
|
verifying_queue_size: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,9 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
|||||||
|
|
||||||
let blocks: Vec<Bytes> = test["blocks"].as_array().unwrap().iter().map(|e| xjson!(&e["rlp"])).collect();
|
let blocks: Vec<Bytes> = test["blocks"].as_array().unwrap().iter().map(|e| xjson!(&e["rlp"])).collect();
|
||||||
let mut spec = ethereum::new_frontier_like_test();
|
let mut spec = ethereum::new_frontier_like_test();
|
||||||
|
spec.set_genesis_state(PodState::from_json(test.find("pre").unwrap()));
|
||||||
spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap());
|
spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap());
|
||||||
spec.genesis_state = PodState::from_json(test.find("pre").unwrap());
|
assert!(spec.is_state_root_valid());
|
||||||
|
|
||||||
let mut dir = env::temp_dir();
|
let mut dir = env::temp_dir();
|
||||||
dir.push(H32::random().hex());
|
dir.push(H32::random().hex());
|
||||||
@ -32,9 +33,12 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
|||||||
blocks.into_iter().foreach(|b| {
|
blocks.into_iter().foreach(|b| {
|
||||||
client.import_block(b).unwrap();
|
client.import_block(b).unwrap();
|
||||||
});
|
});
|
||||||
|
flushln!("Imported all");
|
||||||
client.flush_queue();
|
client.flush_queue();
|
||||||
|
flushln!("Flushed");
|
||||||
client.import_verified_blocks(&IoChannel::disconnected());
|
client.import_verified_blocks(&IoChannel::disconnected());
|
||||||
flushln!("Best hash: {}", client.chain_info().best_block_hash);
|
flushln!("Checking...");
|
||||||
|
fail_unless(client.chain_info().best_block_hash == H256::from_json(&test["lastblockhash"]));
|
||||||
}
|
}
|
||||||
fs::remove_dir_all(&dir).unwrap();
|
fs::remove_dir_all(&dir).unwrap();
|
||||||
}
|
}
|
||||||
@ -46,4 +50,5 @@ fn do_json_test(json_data: &[u8]) -> Vec<String> {
|
|||||||
failed
|
failed
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"}
|
//declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"}
|
||||||
|
declare_test!{BlockchainTests_bcForkBlockTest, "BlockchainTests/bcForkBlockTest"}
|
||||||
|
Loading…
Reference in New Issue
Block a user