Optimize tree route to sync faster (#3665)

* Introduce HeaderMetadata and use it for tree_route. Add lowest_common_ancestor.
* Add tests.
This commit is contained in:
Marcio Diaz
2019-10-02 20:30:43 +02:00
committed by GitHub
parent 8646cd158e
commit f6bd58ac1f
22 changed files with 677 additions and 280 deletions
+20 -6
View File
@@ -27,12 +27,15 @@ use state_machine::backend::{Backend as StateBackend, InMemory};
use state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId, ChangesTrieTransaction};
use hash_db::{Hasher, Prefix};
use trie::MemoryDB;
use header_metadata::{CachedHeaderMetadata, HeaderMetadata};
use crate::error;
use crate::backend::{self, NewBlockState, StorageCollection, ChildStorageCollection};
use crate::light;
use crate::leaves::LeafSet;
use crate::blockchain::{self, BlockStatus, HeaderBackend, well_known_cache_keys::Id as CacheKeyId};
use crate::blockchain::{
self, BlockStatus, HeaderBackend, well_known_cache_keys::Id as CacheKeyId
};
struct PendingBlock<B: BlockT> {
block: StoredBlock<B>,
@@ -221,11 +224,7 @@ impl<Block: BlockT> Blockchain<Block> {
if &best_hash == header.parent_hash() {
None
} else {
let route = crate::blockchain::tree_route(
|id| self.header(id)?.ok_or_else(|| error::Error::UnknownBlock(format!("{:?}", id))),
BlockId::Hash(best_hash),
BlockId::Hash(*header.parent_hash()),
)?;
let route = header_metadata::tree_route(self, best_hash, *header.parent_hash())?;
Some(route)
}
};
@@ -320,6 +319,21 @@ impl<Block: BlockT> HeaderBackend<Block> for Blockchain<Block> {
}
}
impl<Block: BlockT> HeaderMetadata<Block> for Blockchain<Block> {
type Error = error::Error;
fn header_metadata(&self, hash: Block::Hash) -> Result<CachedHeaderMetadata<Block>, Self::Error> {
self.header(BlockId::hash(hash))?.map(|header| CachedHeaderMetadata::from(&header))
.ok_or(error::Error::UnknownBlock("header not found".to_owned()))
}
fn insert_header_metadata(&self, _hash: Block::Hash, _metadata: CachedHeaderMetadata<Block>) {
// No need to implement.
}
fn remove_header_metadata(&self, _hash: Block::Hash) {
// No need to implement.
}
}
impl<Block: BlockT> blockchain::Backend<Block> for Blockchain<Block> {
fn body(&self, id: BlockId<Block>) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>> {