Dynamically generate CHT roots on a full client (#6944)

* Generate CHT roots on a full client

* add changes_trie_root function

* Add a test

* Line widths

* Fix sc-service-test

* Clarify comments

* Revert comments
This commit is contained in:
Ashley
2020-08-24 15:11:21 +02:00
committed by GitHub
parent f009f6c227
commit c8ca2ce183
8 changed files with 139 additions and 56 deletions
+88 -3
View File
@@ -54,8 +54,8 @@ use std::collections::{HashMap, HashSet};
use sc_client_api::{
UsageInfo, MemoryInfo, IoInfo, MemorySize,
backend::{NewBlockState, PrunableStateChangesTrieStorage},
leaves::{LeafSet, FinalizationDisplaced},
backend::{NewBlockState, PrunableStateChangesTrieStorage, ProvideChtRoots},
leaves::{LeafSet, FinalizationDisplaced}, cht,
};
use sp_blockchain::{
Result as ClientResult, Error as ClientError,
@@ -70,7 +70,7 @@ use sp_core::ChangesTrieConfiguration;
use sp_core::offchain::storage::{OffchainOverlayedChange, OffchainOverlayedChanges};
use sp_core::storage::{well_known_keys, ChildInfo};
use sp_arithmetic::traits::Saturating;
use sp_runtime::{generic::BlockId, Justification, Storage};
use sp_runtime::{generic::{DigestItem, BlockId}, Justification, Storage};
use sp_runtime::traits::{
Block as BlockT, Header as HeaderT, NumberFor, Zero, One, SaturatedConversion, HashFor,
};
@@ -405,6 +405,14 @@ impl<Block: BlockT> BlockchainDb<Block> {
meta.finalized_hash = hash;
}
}
// Get block changes trie root, if available.
fn changes_trie_root(&self, block: BlockId<Block>) -> ClientResult<Option<Block::Hash>> {
self.header(block)
.map(|header| header.and_then(|header|
header.digest().log(DigestItem::as_changes_trie_root)
.cloned()))
}
}
impl<Block: BlockT> sc_client_api::blockchain::HeaderBackend<Block> for BlockchainDb<Block> {
@@ -525,6 +533,58 @@ impl<Block: BlockT> HeaderMetadata<Block> for BlockchainDb<Block> {
}
}
impl<Block: BlockT> ProvideChtRoots<Block> for BlockchainDb<Block> {
fn header_cht_root(
&self,
cht_size: NumberFor<Block>,
block: NumberFor<Block>,
) -> sp_blockchain::Result<Option<Block::Hash>> {
let cht_number = match cht::block_to_cht_number(cht_size, block) {
Some(number) => number,
None => return Ok(None),
};
let cht_start: NumberFor<Block> = cht::start_number(cht::size(), cht_number);
let mut current_num = cht_start;
let cht_range = ::std::iter::from_fn(|| {
let old_current_num = current_num;
current_num = current_num + One::one();
Some(old_current_num)
});
cht::compute_root::<Block::Header, HashFor<Block>, _>(
cht::size(), cht_number, cht_range.map(|num| self.hash(num))
).map(Some)
}
fn changes_trie_cht_root(
&self,
cht_size: NumberFor<Block>,
block: NumberFor<Block>,
) -> sp_blockchain::Result<Option<Block::Hash>> {
let cht_number = match cht::block_to_cht_number(cht_size, block) {
Some(number) => number,
None => return Ok(None),
};
let cht_start: NumberFor<Block> = cht::start_number(cht::size(), cht_number);
let mut current_num = cht_start;
let cht_range = ::std::iter::from_fn(|| {
let old_current_num = current_num;
current_num = current_num + One::one();
Some(old_current_num)
});
cht::compute_root::<Block::Header, HashFor<Block>, _>(
cht::size(),
cht_number,
cht_range.map(|num| self.changes_trie_root(BlockId::Number(num))),
).map(Some)
}
}
/// Database transaction
pub struct BlockImportOperation<Block: BlockT> {
old_state: SyncingCachingState<RefTrackingState<Block>, Block>,
@@ -2329,4 +2389,29 @@ pub(crate) mod tests {
backend.commit_operation(op).unwrap_err();
}
}
#[test]
fn header_cht_root_works() {
use sc_client_api::ProvideChtRoots;
let backend = Backend::<Block>::new_test(10, 10);
// insert 1 + SIZE + SIZE + 1 blocks so that CHT#0 is created
let mut prev_hash = insert_header(&backend, 0, Default::default(), None, Default::default());
let cht_size: u64 = cht::size();
for i in 1..1 + cht_size + cht_size + 1 {
prev_hash = insert_header(&backend, i, prev_hash, None, Default::default());
}
let blockchain = backend.blockchain();
let cht_root_1 = blockchain.header_cht_root(cht_size, cht::start_number(cht_size, 0))
.unwrap().unwrap();
let cht_root_2 = blockchain.header_cht_root(cht_size, cht::start_number(cht_size, 0) + cht_size / 2)
.unwrap().unwrap();
let cht_root_3 = blockchain.header_cht_root(cht_size, cht::end_number(cht_size, 0))
.unwrap().unwrap();
assert_eq!(cht_root_1, cht_root_2);
assert_eq!(cht_root_2, cht_root_3);
}
}
+3 -3
View File
@@ -23,11 +23,11 @@ use std::convert::TryInto;
use parking_lot::RwLock;
use sc_client_api::{
cht, backend::{AuxStore, NewBlockState}, UsageInfo,
cht, backend::{AuxStore, NewBlockState, ProvideChtRoots}, UsageInfo,
blockchain::{
BlockStatus, Cache as BlockchainCache, Info as BlockchainInfo,
},
Storage, ChtRootStorage,
Storage,
};
use sp_blockchain::{
CachedHeaderMetadata, HeaderMetadata, HeaderMetadataCache,
@@ -596,7 +596,7 @@ impl<Block> Storage<Block> for LightStorage<Block>
}
}
impl<Block> ChtRootStorage<Block> for LightStorage<Block>
impl<Block> ProvideChtRoots<Block> for LightStorage<Block>
where Block: BlockT,
{
fn header_cht_root(