blockchain cleanup

This commit is contained in:
debris 2015-12-21 15:22:24 +01:00
parent f9457cc584
commit 49fa99ae05

View File

@ -216,8 +216,8 @@ impl BlockChain {
self._tree_route((from_details, from), (to_details, to)) self._tree_route((from_details, from), (to_details, to))
} }
/// Same as `tree_route` function, but returns a root between blocks that may not /// Same as `tree_route` function, but returns a route
/// be in database yet /// between blocks that might not yet be in database.
fn _tree_route(&self, from: (BlockDetails, H256), to: (BlockDetails, H256)) -> TreeRoute { fn _tree_route(&self, from: (BlockDetails, H256), to: (BlockDetails, H256)) -> TreeRoute {
let mut from_branch = vec![]; let mut from_branch = vec![];
let mut to_branch = vec![]; let mut to_branch = vec![];
@ -272,11 +272,37 @@ impl BlockChain {
// create views onto rlp // create views onto rlp
let block = BlockView::new(bytes); let block = BlockView::new(bytes);
let header = block.header_view(); let header = block.header_view();
let hash = block.sha3();
if self.is_known(&header.sha3()) { if self.is_known(&hash) {
return; return;
} }
// store block in db
self.blocks_db.put(&hash, &bytes).unwrap();
let (batch, new_best) = self.block_to_extras_insert_batch(bytes);
// update best block
let mut best_block = self.best_block.borrow_mut();
if let Some(b) = new_best {
*best_block = b;
}
// update caches
let mut write = self.block_details.borrow_mut();
write.remove(&header.parent_hash());
// update extras database
self.extras_db.write(batch).unwrap();
}
/// Transforms block into WriteBatch that may be written into database
/// Additionally, if it's new best block it returns new best block object.
fn block_to_extras_insert_batch(&self, bytes: &[u8]) -> (WriteBatch, Option<BestBlock>) {
// create views onto rlp
let block = BlockView::new(bytes);
let header = block.header_view();
// prepare variables // prepare variables
let hash = block.sha3(); let hash = block.sha3();
let mut parent_details = self.block_details(&header.parent_hash()).expect("Invalid parent hash."); let mut parent_details = self.block_details(&header.parent_hash()).expect("Invalid parent hash.");
@ -292,65 +318,54 @@ impl BlockChain {
children: vec![] children: vec![]
}; };
// store block in db
self.blocks_db.put(&hash, &bytes).unwrap();
let batch = WriteBatch::new();
// prepare update for extra details // prepare update for extra details
{ let batch = WriteBatch::new();
// insert new block details
batch.put_extras(&hash, &details);
// update parent details // insert new block details
parent_details.children.push(hash.clone()); batch.put_extras(&hash, &details);
batch.put_extras(&parent_hash, &parent_details);
// update parent details
parent_details.children.push(hash.clone());
batch.put_extras(&parent_hash, &parent_details);
// if it's not new best block, just return
if !is_new_best {
return (batch, None);
} }
// if its new best block we need to make sure that all ancestors // if its new best block we need to make sure that all ancestors
// are moved to "canon chain" // are moved to "canon chain"
if is_new_best { // find the route between old best block and the new one
// find the route between old best block and the new one let best_hash = self.best_block_hash();
let best_hash = self.best_block_hash(); let best_details = self.block_details(&best_hash).expect("best block hash is invalid!");
let best_details = self.block_details(&best_hash).expect("best block hash is invalid!"); let route = self._tree_route((best_details, best_hash), (details, hash.clone()));
let route = self._tree_route((best_details, best_hash), (details, hash.clone()));
match route.blocks.len() { match route.blocks.len() {
// its our parent // its our parent
1 => batch.put_extras(&header.number(), &hash), 1 => batch.put_extras(&header.number(), &hash),
// it is a fork // it is a fork
i if i > 1 => { i if i > 1 => {
let ancestor_number = self.block_number(&route.ancestor).unwrap(); let ancestor_number = self.block_number(&route.ancestor).unwrap();
let start_number = ancestor_number + U256::from(1u8); let start_number = ancestor_number + U256::from(1u8);
for (index, hash) in route.blocks.iter().skip(route.index).enumerate() { for (index, hash) in route.blocks.iter().skip(route.index).enumerate() {
batch.put_extras(&(start_number + U256::from(index as u64)), hash); batch.put_extras(&(start_number + U256::from(index as u64)), hash);
} }
}, },
// route.len() could be 0 only if inserted block is best block, // route.len() could be 0 only if inserted block is best block,
// and this is not possible at this stage // and this is not possible at this stage
_ => { unreachable!(); } _ => { unreachable!(); }
}; };
// this is new extras db // this is new extras db
batch.put(b"best", &hash).unwrap(); batch.put(b"best", &hash).unwrap();
}
// apply update let best_block = BestBlock {
{ hash: hash,
// update local caches number: header.number(),
let mut best_block = self.best_block.borrow_mut(); total_difficulty: total_difficulty
if is_new_best { };
best_block.hash = hash;
best_block.number = header.number();
best_block.total_difficulty = total_difficulty;
}
// remove outdated cached parent details (batch, Some(best_block))
let mut write = self.block_details.borrow_mut();
write.remove(&parent_hash);
// update extras database
self.extras_db.write(batch).unwrap();
}
} }
/// Returns true if the given block is known /// Returns true if the given block is known