keep track of first block in blockchain (#1937)
This commit is contained in:
parent
d7c184bd72
commit
0e0cc20d84
@ -41,6 +41,16 @@ pub trait BlockProvider {
|
|||||||
/// (though not necessarily a part of the canon chain).
|
/// (though not necessarily a part of the canon chain).
|
||||||
fn is_known(&self, hash: &H256) -> bool;
|
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
|
/// Get raw block data
|
||||||
fn block(&self, hash: &H256) -> Option<Bytes>;
|
fn block(&self, hash: &H256) -> Option<Bytes>;
|
||||||
|
|
||||||
@ -144,6 +154,7 @@ impl bc::group::BloomGroupDatabase for BlockChain {
|
|||||||
pub struct BlockChain {
|
pub struct BlockChain {
|
||||||
// All locks must be captured in the order declared here.
|
// All locks must be captured in the order declared here.
|
||||||
blooms_config: bc::Config,
|
blooms_config: bc::Config,
|
||||||
|
first_block: H256,
|
||||||
|
|
||||||
best_block: RwLock<BestBlock>,
|
best_block: RwLock<BestBlock>,
|
||||||
|
|
||||||
@ -174,6 +185,10 @@ impl BlockProvider for BlockChain {
|
|||||||
self.db.exists_with_cache(db::COL_EXTRA, &self.block_details, hash)
|
self.db.exists_with_cache(db::COL_EXTRA, &self.block_details, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn first_block(&self) -> H256 {
|
||||||
|
self.first_block
|
||||||
|
}
|
||||||
|
|
||||||
/// Get raw block data
|
/// Get raw block data
|
||||||
fn block(&self, hash: &H256) -> Option<Bytes> {
|
fn block(&self, hash: &H256) -> Option<Bytes> {
|
||||||
match (self.block_header_data(hash), self.block_body(hash)) {
|
match (self.block_header_data(hash), self.block_body(hash)) {
|
||||||
@ -325,11 +340,12 @@ impl BlockChain {
|
|||||||
// 400 is the avarage size of the key
|
// 400 is the avarage size of the key
|
||||||
let cache_man = CacheManager::new(config.pref_cache_size, config.max_cache_size, 400);
|
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 {
|
blooms_config: bc::Config {
|
||||||
levels: LOG_BLOOMS_LEVELS,
|
levels: LOG_BLOOMS_LEVELS,
|
||||||
elements_per_index: LOG_BLOOMS_ELEMENTS_PER_INDEX,
|
elements_per_index: LOG_BLOOMS_ELEMENTS_PER_INDEX,
|
||||||
},
|
},
|
||||||
|
first_block: H256::zero(),
|
||||||
best_block: RwLock::new(BestBlock::default()),
|
best_block: RwLock::new(BestBlock::default()),
|
||||||
block_headers: RwLock::new(HashMap::new()),
|
block_headers: RwLock::new(HashMap::new()),
|
||||||
block_bodies: RwLock::new(HashMap::new()),
|
block_bodies: RwLock::new(HashMap::new()),
|
||||||
@ -370,7 +386,9 @@ impl BlockChain {
|
|||||||
|
|
||||||
batch.write(db::COL_EXTRA, &hash, &details);
|
batch.write(db::COL_EXTRA, &hash, &details);
|
||||||
batch.write(db::COL_EXTRA, &header.number(), &hash);
|
batch.write(db::COL_EXTRA, &header.number(), &hash);
|
||||||
|
|
||||||
batch.put(db::COL_EXTRA, b"best", &hash);
|
batch.put(db::COL_EXTRA, b"best", &hash);
|
||||||
|
batch.put(db::COL_EXTRA, b"first", &hash);
|
||||||
bc.db.write(batch).expect("Low level database error. Some issue with disk?");
|
bc.db.write(batch).expect("Low level database error. Some issue with disk?");
|
||||||
hash
|
hash
|
||||||
}
|
}
|
||||||
@ -382,6 +400,34 @@ impl BlockChain {
|
|||||||
let best_block_total_difficulty = bc.block_details(&best_block_hash).unwrap().total_difficulty;
|
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 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);
|
||||||
|
db.write(batch).expect("Low level database error.");
|
||||||
|
|
||||||
|
bc.first_block = hash;
|
||||||
|
} else {
|
||||||
|
bc.first_block = H256::from_slice(&raw_first);
|
||||||
|
}
|
||||||
|
|
||||||
// and write them
|
// and write them
|
||||||
let mut best_block = bc.best_block.write();
|
let mut best_block = bc.best_block.write();
|
||||||
*best_block = BestBlock {
|
*best_block = BestBlock {
|
||||||
|
@ -284,6 +284,10 @@ mod tests {
|
|||||||
self.blocks.contains_key(hash)
|
self.blocks.contains_key(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn first_block(&self) -> H256 {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get raw block data
|
/// Get raw block data
|
||||||
fn block(&self, hash: &H256) -> Option<Bytes> {
|
fn block(&self, hash: &H256) -> Option<Bytes> {
|
||||||
self.blocks.get(hash).cloned()
|
self.blocks.get(hash).cloned()
|
||||||
|
Loading…
Reference in New Issue
Block a user