mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 22:47:56 +00:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user