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

Commit

Permalink
keep track of first block in blockchain
Browse files Browse the repository at this point in the history
  • Loading branch information
rphmeier committed Aug 16, 2016
1 parent b45020f commit 31a6798
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
47 changes: 46 additions & 1 deletion ethcore/src/blockchain/blockchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ 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.
/// Any queries of blocks which precede this one are not guaranteed to
/// succeed.
fn first_block(&self) -> 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")
}

/// Get raw block data
fn block(&self, hash: &H256) -> Option<Bytes>;

Expand Down Expand Up @@ -145,6 +155,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,

best_block: RwLock<BestBlock>,

Expand Down Expand Up @@ -175,6 +186,10 @@ impl BlockProvider for BlockChain {
self.db.exists_with_cache(DB_COL_EXTRA, &self.block_details, hash)
}

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

/// Get raw block data
fn block(&self, hash: &H256) -> Option<Bytes> {
match (self.block_header_data(hash), self.block_body(hash)) {
Expand Down Expand Up @@ -326,11 +341,12 @@ impl BlockChain {
// 400 is the avarage size of the key
let cache_man = CacheManager::new(config.pref_cache_size, config.max_cache_size, 400);

let bc = BlockChain {
let mut bc = BlockChain {
blooms_config: bc::Config {
levels: LOG_BLOOMS_LEVELS,
elements_per_index: LOG_BLOOMS_ELEMENTS_PER_INDEX,
},
first_block: H256::zero(),
best_block: RwLock::new(BestBlock::default()),
block_headers: RwLock::new(HashMap::new()),
block_bodies: RwLock::new(HashMap::new()),
Expand Down Expand Up @@ -372,6 +388,7 @@ impl BlockChain {
batch.write(DB_COL_EXTRA, &hash, &details);
batch.write(DB_COL_EXTRA, &header.number(), &hash);
batch.put(DB_COL_EXTRA, b"best", &hash).unwrap();
batch.put(DB_COL_EXTRA, b"first", &hash).unwrap();
bc.db.write(batch).expect("Low level database error. Some issue with disk?");
hash
}
Expand All @@ -383,6 +400,34 @@ 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());

// 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 = 0;

loop {
if l >= f { break; }

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

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

let batch = db.transaction();
batch.put(DB_COL_EXTRA, b"first", &hash).unwrap();
db.write(batch).expect("Low level database error.");

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

// and write them
let mut best_block = bc.best_block.write();
*best_block = BestBlock {
Expand Down
4 changes: 4 additions & 0 deletions ethcore/src/verification/verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,10 @@ mod tests {
self.blocks.contains_key(hash)
}

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

/// Get raw block data
fn block(&self, hash: &H256) -> Option<Bytes> {
self.blocks.get(hash).cloned()
Expand Down

0 comments on commit 31a6798

Please sign in to comment.