Skip to content

Commit

Permalink
feat(Store Validator): move check_refcount_map into Store Validator
Browse files Browse the repository at this point in the history
  • Loading branch information
Kouprin committed Jul 3, 2020
1 parent 445a7f1 commit 6b8cd8e
Show file tree
Hide file tree
Showing 12 changed files with 222 additions and 360 deletions.
98 changes: 21 additions & 77 deletions chain/chain/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,13 +573,21 @@ impl Chain {
if gc_blocks_remaining == 0 {
return Ok(());
}
let chunk_tail = self.store.chunk_tail()?;
let mut min_chunk_height = chunk_tail;
let mut chain_store_update = self.store.store_update();
if let Ok(blocks_current_height) =
chain_store_update.get_all_block_hashes_by_height(height)
{
let blocks_current_height =
blocks_current_height.values().flatten().cloned().collect::<Vec<_>>();
if let Some(block_hash) = blocks_current_height.first() {
let block = chain_store_update.get_block(block_hash)?;
for chunk_header in block.chunks() {
if min_chunk_height > chunk_header.inner.height_created {
min_chunk_height = chunk_header.inner.height_created;
}
}
let prev_hash = *chain_store_update.get_block_header(block_hash)?.prev_hash();
let prev_block_refcount = *chain_store_update.get_block_refcount(&prev_hash)?;
if prev_block_refcount > 1 {
Expand All @@ -600,6 +608,13 @@ impl Chain {
}
chain_store_update.update_tail(height);
chain_store_update.commit()?;

// Delete chunks and chunk-indexed data
for height in chunk_tail + 1..min_chunk_height {
let mut chain_store_update = self.store.store_update();
chain_store_update.clear_chunk_data(height)?;
chain_store_update.commit()?;
}
}
Ok(())
}
Expand Down Expand Up @@ -949,9 +964,12 @@ impl Chain {
}

// Clear Chunks data
let mut chain_store_update = self.mut_store().store_update();
chain_store_update.clear_chunk_data(gc_height)?;
chain_store_update.commit()?;
let chunk_tail = self.store.chunk_tail()?;
for height in chunk_tail..gc_height {
let mut chain_store_update = self.mut_store().store_update();
chain_store_update.clear_chunk_data(height)?;
chain_store_update.commit()?;
}

// clear all trie data
let keys: Vec<Vec<u8>> =
Expand Down Expand Up @@ -3554,77 +3572,3 @@ pub fn collect_receipts_from_response(
receipt_proof_response.iter().flat_map(|ReceiptProofResponse(_, proofs)| proofs),
)
}

// Used in testing only
pub fn check_refcount_map(chain: &mut Chain) -> Result<(), Error> {
let head = chain.head()?;
let mut block_refcounts = HashMap::new();
// TODO #2352: make sure there is no block with height > head.height and set highest_height to `head.height`
let highest_height = head.height + 100;
for height in chain.store().get_genesis_height() + 1..=highest_height {
let blocks_current_height = match chain.mut_store().get_all_block_hashes_by_height(height) {
Ok(blocks_current_height) => {
blocks_current_height.values().flatten().cloned().collect()
}
_ => vec![],
};
for block_hash in blocks_current_height.iter() {
if let Ok(prev_hash) =
chain.get_block(&block_hash).map(|block| *block.header().prev_hash())
{
*block_refcounts.entry(prev_hash).or_insert(0) += 1;
}
// This is temporary workaround to ignore all blocks with height >= highest_height
// TODO #2352: remove `if` and keep only `block_refcounts.entry(*block_hash).or_insert(0)`
if height < highest_height {
block_refcounts.entry(*block_hash).or_insert(0);
}
}
}
let mut chain_store_update = ChainStoreUpdate::new(chain.mut_store());
let mut tail_blocks = 0;
for (block_hash, refcount) in block_refcounts {
let block_refcount = chain_store_update.get_block_refcount(&block_hash)?.clone();
match chain_store_update.get_block(&block_hash) {
Ok(_) => {
if block_refcount != refcount {
return Err(ErrorKind::GCError(format!(
"invalid number of references in Block {:?}, expected {:?}, found {:?}",
block_hash, refcount, block_refcount
))
.into());
}
}
Err(e) => {
if block_refcount != 0 {
// May be the tail block
if block_refcount != refcount {
return Err(ErrorKind::GCError(format!(
"invalid number of references in deleted Block {:?}, expected {:?}, found {:?}; get_block failed: {:?}",
block_hash, refcount, block_refcount, e
))
.into());
}
}
if refcount >= 2 {
return Err(ErrorKind::GCError(format!(
"Block {:?} expected to be deleted, found {:?} references instead; get_block failed: {:?}",
block_hash, refcount, e
))
.into());
} else if refcount == 1 {
// If Block `block_hash` is successfully GCed, the only its descendant is alive.
tail_blocks += 1;
}
}
}
}
if tail_blocks >= 2 {
return Err(ErrorKind::GCError(format!(
"There are {:?} tail blocks found, expected no more than 1",
tail_blocks,
))
.into());
}
Ok(())
}
2 changes: 1 addition & 1 deletion chain/chain/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#[macro_use]
extern crate lazy_static;

pub use chain::{check_refcount_map, collect_receipts, Chain, ChainGenesis, MAX_ORPHAN_SIZE};
pub use chain::{collect_receipts, Chain, ChainGenesis, MAX_ORPHAN_SIZE};
pub use doomslug::{Doomslug, DoomslugBlockProductionReadiness, DoomslugThresholdMode};
pub use error::{Error, ErrorKind};
pub use lightclient::create_light_client_block_view;
Expand Down
Loading

0 comments on commit 6b8cd8e

Please sign in to comment.