Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
Optional first_block; removed insert_snapshot_block
Browse files Browse the repository at this point in the history
  • Loading branch information
arkpar committed Sep 19, 2016
1 parent f6ab6f5 commit 5d67bbf
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 50 deletions.
77 changes: 33 additions & 44 deletions ethcore/src/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,15 @@ pub trait BlockProvider {
/// (though not necessarily a part of the canon chain).
fn is_known(&self, hash: &H256) -> bool;

/// Get the first block which this chain holds.
/// Get the first block of the best part of the chain.
/// Return `None` if there is no gap and the first block is the genesis.
/// Any queries of blocks which precede this one are not guaranteed to
/// succeed.
fn first_block(&self) -> H256;
fn first_block(&self) -> Option<H256>;

/// Get the number of the first block.
fn first_block_number(&self) -> BlockNumber {
self.block_number(&self.first_block()).expect("First block always stored; qed")
fn first_block_number(&self) -> Option<BlockNumber> {
self.first_block().map(|b| self.block_number(&b).expect("First block always stored; qed"))
}

/// Get the best block of an first block sequence if there is a gap.
Expand Down Expand Up @@ -168,7 +169,7 @@ impl bc::group::BloomGroupDatabase for BlockChain {
pub struct BlockChain {
// All locks must be captured in the order declared here.
blooms_config: bc::Config,
first_block: H256,
first_block: Option<H256>,

best_block: RwLock<BestBlock>,
best_ancient_block: RwLock<Option<BestAncientBlock>>,
Expand Down Expand Up @@ -200,7 +201,7 @@ impl BlockProvider for BlockChain {
self.db.exists_with_cache(db::COL_EXTRA, &self.block_details, hash)
}

fn first_block(&self) -> H256 {
fn first_block(&self) -> Option<H256> {
self.first_block.clone()
}

Expand Down Expand Up @@ -413,7 +414,7 @@ impl BlockChain {
levels: LOG_BLOOMS_LEVELS,
elements_per_index: LOG_BLOOMS_ELEMENTS_PER_INDEX,
},
first_block: H256::zero(),
first_block: None,
best_block: RwLock::new(BestBlock::default()),
best_ancient_block: RwLock::new(None),
block_headers: RwLock::new(HashMap::new()),
Expand Down Expand Up @@ -468,7 +469,7 @@ impl BlockChain {
let best_block_total_difficulty = bc.block_details(&best_block_hash).unwrap().total_difficulty;
let best_block_rlp = bc.block(&best_block_hash).unwrap();

let raw_first = bc.db.get(db::COL_EXTRA, b"first").unwrap().map_or(Vec::new(), |v| v.to_vec());
let raw_first = bc.db.get(db::COL_EXTRA, b"first").unwrap().map(|v| v.to_vec());
let mut best_ancient = bc.db.get(db::COL_EXTRA, b"ancient").unwrap().map(|h| H256::from_slice(&h));
let best_ancient_number;
if best_ancient.is_none() && best_block_number > 1 && bc.block_hash(1).is_none() {
Expand All @@ -479,32 +480,34 @@ impl BlockChain {
}

// binary search for the first block.
if raw_first.is_empty() {
let (mut f, mut hash) = (best_block_number, best_block_hash);
let mut l = best_ancient_number.unwrap_or(0);
match raw_first {
None => {
let (mut f, mut hash) = (best_block_number, best_block_hash);
let mut l = best_ancient_number.unwrap_or(0);

loop {
if l >= f { break; }
loop {
if l >= f { break; }

let step = (f - l) >> 1;
let m = l + step;
let step = (f - l) >> 1;
let m = l + step;

match bc.block_hash(m) {
Some(h) => { f = m; hash = h },
None => { l = m + 1 },
match bc.block_hash(m) {
Some(h) => { f = m; hash = h },
None => { l = m + 1 },
}
}
}

let mut batch = db.transaction();
if hash != bc.genesis_hash() {
trace!("First block calculated: {:?}", hash);
batch.put(db::COL_EXTRA, b"first", &hash);
if hash != bc.genesis_hash() {
trace!("First block calculated: {:?}", hash);
let mut batch = db.transaction();
batch.put(db::COL_EXTRA, b"first", &hash);
db.write(batch).expect("Low level database error.");
bc.first_block = Some(hash);
}
},
Some(raw_first) => {
bc.first_block = Some(H256::from_slice(&raw_first));
}
db.write(batch).expect("Low level database error.");

bc.first_block = hash;
} else {
bc.first_block = H256::from_slice(&raw_first);
}

// and write them
Expand Down Expand Up @@ -673,20 +676,6 @@ impl BlockChain {
}
}

/// Inserts a verified, known block from the canonical chain.
///
/// Can be performed out-of-order, but care must be taken that the final chain is in a correct state.
/// This is used by snapshot restoration.
///
/// Supply a dummy parent total difficulty when the parent block may not be in the chain.
/// Returns true if the block is disconnected.
pub fn insert_snapshot_block(&self, bytes: &[u8], receipts: Vec<Receipt>, parent_td: Option<U256>, is_best: bool) -> bool {
let mut batch = self.db.transaction();
let result = self.insert_unordered_block(&mut batch, bytes, receipts, parent_td, is_best, false);
self.db.write(batch).unwrap();
result
}

/// Inserts a verified, known block from the canonical chain.
///
/// Can be performed out-of-order, but care must be taken that the final chain is in a correct state.
Expand Down Expand Up @@ -1264,8 +1253,8 @@ impl BlockChain {
genesis_hash: self.genesis_hash(),
best_block_hash: best_block.hash.clone(),
best_block_number: best_block.number,
first_block_hash: Some(self.first_block()),
first_block_number: Some(From::from(self.first_block_number())),
first_block_hash: self.first_block(),
first_block_number: From::from(self.first_block_number()),
ancient_block_hash: best_ancient_block.as_ref().map(|b| b.hash.clone()),
ancient_block_number: best_ancient_block.as_ref().map(|b| b.number),
}
Expand Down
10 changes: 7 additions & 3 deletions ethcore/src/snapshot/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,16 +548,18 @@ const POW_VERIFY_RATE: f32 = 0.02;
/// After all chunks have been submitted, we "glue" the chunks together.
pub struct BlockRebuilder {
chain: BlockChain,
db: Arc<Database>,
rng: OsRng,
disconnected: Vec<(u64, H256)>,
best_number: u64,
}

impl BlockRebuilder {
/// Create a new BlockRebuilder.
pub fn new(chain: BlockChain, best_number: u64) -> Result<Self, ::error::Error> {
pub fn new(chain: BlockChain, db: Arc<Database>, best_number: u64) -> Result<Self, ::error::Error> {
Ok(BlockRebuilder {
chain: chain,
db: db,
rng: try!(OsRng::new()),
disconnected: Vec::new(),
best_number: best_number,
Expand Down Expand Up @@ -595,15 +597,17 @@ impl BlockRebuilder {
}

let is_best = cur_number == self.best_number;
let mut batch = self.db.transaction();

// special-case the first block in each chunk.
if idx == 3 {
if self.chain.insert_snapshot_block(&block_bytes, receipts, Some(parent_total_difficulty), is_best) {
if self.chain.insert_unordered_block(&mut batch, &block_bytes, receipts, Some(parent_total_difficulty), is_best, false) {
self.disconnected.push((cur_number, block.header.hash()));
}
} else {
self.chain.insert_snapshot_block(&block_bytes, receipts, None, is_best);
self.chain.insert_unordered_block(&mut batch, &block_bytes, receipts, None, is_best, false);
}
self.db.write(batch).expect("Error writing to the DB");
self.chain.commit();

parent_hash = BlockView::new(&block_bytes).hash();
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/snapshot/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl Restoration {
.map_err(UtilError::SimpleString)));

let chain = BlockChain::new(Default::default(), params.genesis, raw_db.clone());
let blocks = try!(BlockRebuilder::new(chain, manifest.block_number));
let blocks = try!(BlockRebuilder::new(chain, raw_db.clone(), manifest.block_number));

let root = manifest.state_root.clone();
Ok(Restoration {
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/snapshot/tests/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ fn chunk_and_restore(amount: u64) {
// restore it.
let new_db = Arc::new(Database::open(&db_cfg, new_path.as_str()).unwrap());
let new_chain = BlockChain::new(Default::default(), &genesis, new_db.clone());
let mut rebuilder = BlockRebuilder::new(new_chain, amount).unwrap();
let mut rebuilder = BlockRebuilder::new(new_chain, new_db.clone(), amount).unwrap();
let reader = PackedReader::new(&snapshot_path).unwrap().unwrap();
let engine = ::engines::NullEngine::new(Default::default(), Default::default());
for chunk_hash in &reader.manifest().block_hashes {
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/verification/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ mod tests {
self.blocks.contains_key(hash)
}

fn first_block(&self) -> H256 {
fn first_block(&self) -> Option<H256> {
unimplemented!()
}

Expand Down

0 comments on commit 5d67bbf

Please sign in to comment.