mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 19:17:58 +00:00
Fast sync (#8884)
* State sync * Importing state fixes * Bugfixes * Sync with proof * Status reporting * Unsafe sync mode * Sync test * Cleanup * Apply suggestions from code review Co-authored-by: cheme <emericchevalier.pro@gmail.com> Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com> * set_genesis_storage * Extract keys from range proof * Detect iter completion * Download and import bodies with fast sync * Replaced meta updates tuple with a struct * Fixed reverting finalized state * Reverted timeout * Typo * Doc * Doc * Fixed light client test * Fixed error handling * Tweaks * More UpdateMeta changes * Rename convert_transaction * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Code review suggestions * Fixed count handling Co-authored-by: cheme <emericchevalier.pro@gmail.com> Co-authored-by: Pierre Krieger <pierre.krieger1708@gmail.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -41,6 +41,7 @@ use sp_consensus::BlockOrigin;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
pub use sp_state_machine::Backend as StateBackend;
|
||||
pub use sp_consensus::ImportedState;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Extracts the state backend type for the given backend.
|
||||
@@ -161,6 +162,10 @@ pub trait BlockImportOperation<Block: BlockT> {
|
||||
update: TransactionForSB<Self::State, Block>,
|
||||
) -> sp_blockchain::Result<()>;
|
||||
|
||||
/// Set genesis state. If `commit` is `false` the state is saved in memory, but is not written
|
||||
/// to the database.
|
||||
fn set_genesis_state(&mut self, storage: Storage, commit: bool) -> sp_blockchain::Result<Block::Hash>;
|
||||
|
||||
/// Inject storage data into the database replacing any existing data.
|
||||
fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result<Block::Hash>;
|
||||
|
||||
|
||||
@@ -347,6 +347,11 @@ impl<Block: BlockT> HeaderBackend<Block> for Blockchain<Block> {
|
||||
genesis_hash: storage.genesis_hash,
|
||||
finalized_hash: storage.finalized_hash,
|
||||
finalized_number: storage.finalized_number,
|
||||
finalized_state: if storage.finalized_hash != Default::default() {
|
||||
Some((storage.finalized_hash.clone(), storage.finalized_number))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
number_leaves: storage.leaves.count()
|
||||
}
|
||||
}
|
||||
@@ -528,6 +533,32 @@ pub struct BlockImportOperation<Block: BlockT> {
|
||||
set_head: Option<BlockId<Block>>,
|
||||
}
|
||||
|
||||
impl<Block: BlockT> BlockImportOperation<Block> where
|
||||
Block::Hash: Ord,
|
||||
{
|
||||
fn apply_storage(&mut self, storage: Storage, commit: bool) -> sp_blockchain::Result<Block::Hash> {
|
||||
check_genesis_storage(&storage)?;
|
||||
|
||||
let child_delta = storage.children_default.iter()
|
||||
.map(|(_storage_key, child_content)|
|
||||
(
|
||||
&child_content.child_info,
|
||||
child_content.data.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref())))
|
||||
)
|
||||
);
|
||||
|
||||
let (root, transaction) = self.old_state.full_storage_root(
|
||||
storage.top.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))),
|
||||
child_delta,
|
||||
);
|
||||
|
||||
if commit {
|
||||
self.new_state = Some(transaction);
|
||||
}
|
||||
Ok(root)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Block: BlockT> backend::BlockImportOperation<Block> for BlockImportOperation<Block> where
|
||||
Block::Hash: Ord,
|
||||
{
|
||||
@@ -569,24 +600,12 @@ impl<Block: BlockT> backend::BlockImportOperation<Block> for BlockImportOperatio
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_genesis_state(&mut self, storage: Storage, commit: bool) -> sp_blockchain::Result<Block::Hash> {
|
||||
self.apply_storage(storage, commit)
|
||||
}
|
||||
|
||||
fn reset_storage(&mut self, storage: Storage) -> sp_blockchain::Result<Block::Hash> {
|
||||
check_genesis_storage(&storage)?;
|
||||
|
||||
let child_delta = storage.children_default.iter()
|
||||
.map(|(_storage_key, child_content)|
|
||||
(
|
||||
&child_content.child_info,
|
||||
child_content.data.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref())))
|
||||
)
|
||||
);
|
||||
|
||||
let (root, transaction) = self.old_state.full_storage_root(
|
||||
storage.top.iter().map(|(k, v)| (k.as_ref(), Some(v.as_ref()))),
|
||||
child_delta,
|
||||
);
|
||||
|
||||
self.new_state = Some(transaction);
|
||||
Ok(root)
|
||||
self.apply_storage(storage, true)
|
||||
}
|
||||
|
||||
fn insert_aux<I>(&mut self, ops: I) -> sp_blockchain::Result<()>
|
||||
@@ -806,12 +825,12 @@ impl<Block: BlockT> backend::RemoteBackend<Block> for Backend<Block> where Block
|
||||
/// Check that genesis storage is valid.
|
||||
pub fn check_genesis_storage(storage: &Storage) -> sp_blockchain::Result<()> {
|
||||
if storage.top.iter().any(|(k, _)| well_known_keys::is_child_storage_key(k)) {
|
||||
return Err(sp_blockchain::Error::GenesisInvalid.into());
|
||||
return Err(sp_blockchain::Error::InvalidState.into());
|
||||
}
|
||||
|
||||
if storage.children_default.keys()
|
||||
.any(|child_key| !well_known_keys::is_child_storage_key(&child_key)) {
|
||||
return Err(sp_blockchain::Error::GenesisInvalid.into());
|
||||
return Err(sp_blockchain::Error::InvalidState.into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -41,6 +41,7 @@ pub use proof_provider::*;
|
||||
pub use sp_blockchain::HeaderBackend;
|
||||
|
||||
pub use sp_state_machine::{StorageProof, ExecutionStrategy};
|
||||
pub use sp_storage::{StorageData, StorageKey, PrefixedStorageKey, ChildInfo};
|
||||
|
||||
/// Usage Information Provider interface
|
||||
///
|
||||
|
||||
@@ -70,4 +70,31 @@ pub trait ProofProvider<Block: BlockT> {
|
||||
storage_key: Option<&PrefixedStorageKey>,
|
||||
key: &StorageKey,
|
||||
) -> sp_blockchain::Result<ChangesProof<Block::Header>>;
|
||||
|
||||
/// Given a `BlockId` iterate over all storage values starting at `start_key` exclusively,
|
||||
/// building proofs until size limit is reached. Returns combined proof and the number of collected keys.
|
||||
fn read_proof_collection(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
start_key: &[u8],
|
||||
size_limit: usize,
|
||||
) -> sp_blockchain::Result<(StorageProof, u32)>;
|
||||
|
||||
/// Given a `BlockId` iterate over all storage values starting at `start_key`.
|
||||
/// Returns collected keys and values.
|
||||
fn storage_collection(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
start_key: &[u8],
|
||||
size_limit: usize,
|
||||
) -> sp_blockchain::Result<Vec<(Vec<u8>, Vec<u8>)>>;
|
||||
|
||||
/// Verify read storage proof for a set of keys.
|
||||
/// Returns collected key-value pairs and a flag indicating if iteration is complete.
|
||||
fn verify_range_proof(
|
||||
&self,
|
||||
root: Block::Hash,
|
||||
proof: StorageProof,
|
||||
start_key: &[u8],
|
||||
) -> sp_blockchain::Result<(Vec<(Vec<u8>, Vec<u8>)>, bool)>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user