mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 21:31:02 +00:00
Warp sync part I (#9227)
* Started warp sync * BABE & GRANDPA recovery * Warp sync protocol * Sync warp proofs first * Added basic documentation * Apply suggestions from code review Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Style changes * Apply suggestions from code review Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * fmt * Apply suggestions from code review Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> * Fixed chage trie pruning wrt missing blocks * Restore parent finalization * fmt * fmt * Revert pwasm-utils bump * Change error type & check API version * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Build fix * Fixed target block check * Formatting Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
use std::{collections::HashMap, marker::PhantomData, sync::Arc};
|
||||
|
||||
use log::debug;
|
||||
use parity_scale_codec::Encode;
|
||||
use parity_scale_codec::{Decode, Encode};
|
||||
|
||||
use sc_client_api::{backend::Backend, utils::is_descendent_of};
|
||||
use sc_consensus::{
|
||||
@@ -27,10 +27,11 @@ use sc_consensus::{
|
||||
BlockCheckParams, BlockImport, BlockImportParams, ImportResult, JustificationImport,
|
||||
};
|
||||
use sc_telemetry::TelemetryHandle;
|
||||
use sp_api::TransactionFor;
|
||||
use sp_api::{Core, RuntimeApiInfo, TransactionFor};
|
||||
use sp_blockchain::{well_known_cache_keys, BlockStatus};
|
||||
use sp_consensus::{BlockOrigin, Error as ConsensusError, SelectChain};
|
||||
use sp_finality_grandpa::{ConsensusLog, ScheduledChange, SetId, GRANDPA_ENGINE_ID};
|
||||
use sp_core::hashing::twox_128;
|
||||
use sp_finality_grandpa::{ConsensusLog, GrandpaApi, ScheduledChange, SetId, GRANDPA_ENGINE_ID};
|
||||
use sp_runtime::{
|
||||
generic::{BlockId, OpaqueDigestItemId},
|
||||
traits::{Block as BlockT, DigestFor, Header as HeaderT, NumberFor, Zero},
|
||||
@@ -43,7 +44,7 @@ use crate::{
|
||||
environment::finalize_block,
|
||||
justification::GrandpaJustification,
|
||||
notification::GrandpaJustificationSender,
|
||||
ClientForGrandpa, CommandOrError, Error, NewAuthoritySet, VoterCommand,
|
||||
AuthoritySetChanges, ClientForGrandpa, CommandOrError, Error, NewAuthoritySet, VoterCommand,
|
||||
};
|
||||
|
||||
/// A block-import handler for GRANDPA.
|
||||
@@ -230,6 +231,10 @@ where
|
||||
DigestFor<Block>: Encode,
|
||||
BE: Backend<Block>,
|
||||
Client: ClientForGrandpa<Block, BE>,
|
||||
Client::Api: GrandpaApi<Block>,
|
||||
for<'a> &'a Client:
|
||||
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<Client, Block>>,
|
||||
TransactionFor<Client, Block>: 'static,
|
||||
{
|
||||
// check for a new authority set change.
|
||||
fn check_new_change(
|
||||
@@ -418,6 +423,91 @@ where
|
||||
|
||||
Ok(PendingSetChanges { just_in_case, applied_changes, do_pause })
|
||||
}
|
||||
|
||||
/// Read current set id form a given state.
|
||||
fn current_set_id(&self, id: &BlockId<Block>) -> Result<SetId, ConsensusError> {
|
||||
let runtime_version = self.inner.runtime_api().version(id).map_err(|e| {
|
||||
ConsensusError::ClientImport(format!(
|
||||
"Unable to retrieve current runtime version. {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
if runtime_version
|
||||
.api_version(&<dyn GrandpaApi<Block>>::ID)
|
||||
.map_or(false, |v| v < 3)
|
||||
{
|
||||
// The new API is not supported in this runtime. Try reading directly from storage.
|
||||
// This code may be removed once warp sync to an old runtime is no longer needed.
|
||||
for prefix in ["GrandpaFinality", "Grandpa"] {
|
||||
let k = [twox_128(prefix.as_bytes()), twox_128(b"CurrentSetId")].concat();
|
||||
if let Ok(Some(id)) =
|
||||
self.inner.storage(&id, &sc_client_api::StorageKey(k.to_vec()))
|
||||
{
|
||||
if let Ok(id) = SetId::decode(&mut id.0.as_ref()) {
|
||||
return Ok(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(ConsensusError::ClientImport("Unable to retrieve current set id.".into()))
|
||||
} else {
|
||||
self.inner
|
||||
.runtime_api()
|
||||
.current_set_id(&id)
|
||||
.map_err(|e| ConsensusError::ClientImport(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Import whole new state and reset authority set.
|
||||
async fn import_state(
|
||||
&mut self,
|
||||
mut block: BlockImportParams<Block, TransactionFor<Client, Block>>,
|
||||
new_cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
|
||||
) -> Result<ImportResult, ConsensusError> {
|
||||
let hash = block.post_hash();
|
||||
let number = *block.header.number();
|
||||
// Force imported state finality.
|
||||
block.finalized = true;
|
||||
let import_result = (&*self.inner).import_block(block, new_cache).await;
|
||||
match import_result {
|
||||
Ok(ImportResult::Imported(aux)) => {
|
||||
// We've just imported a new state. We trust the sync module has verified
|
||||
// finality proofs and that the state is correct and final.
|
||||
// So we can read the authority list and set id from the state.
|
||||
self.authority_set_hard_forks.clear();
|
||||
let block_id = BlockId::hash(hash);
|
||||
let authorities = self
|
||||
.inner
|
||||
.runtime_api()
|
||||
.grandpa_authorities(&block_id)
|
||||
.map_err(|e| ConsensusError::ClientImport(e.to_string()))?;
|
||||
let set_id = self.current_set_id(&block_id)?;
|
||||
let authority_set = AuthoritySet::new(
|
||||
authorities.clone(),
|
||||
set_id,
|
||||
fork_tree::ForkTree::new(),
|
||||
Vec::new(),
|
||||
AuthoritySetChanges::empty(),
|
||||
)
|
||||
.ok_or_else(|| ConsensusError::ClientImport("Invalid authority list".into()))?;
|
||||
*self.authority_set.inner_locked() = authority_set.clone();
|
||||
|
||||
crate::aux_schema::update_authority_set::<Block, _, _>(
|
||||
&authority_set,
|
||||
None,
|
||||
|insert| self.inner.insert_aux(insert, []),
|
||||
)
|
||||
.map_err(|e| ConsensusError::ClientImport(e.to_string()))?;
|
||||
let new_set =
|
||||
NewAuthoritySet { canon_number: number, canon_hash: hash, set_id, authorities };
|
||||
let _ = self
|
||||
.send_voter_commands
|
||||
.unbounded_send(VoterCommand::ChangeAuthorities(new_set));
|
||||
Ok(ImportResult::Imported(aux))
|
||||
},
|
||||
Ok(r) => Ok(r),
|
||||
Err(e) => Err(ConsensusError::ClientImport(e.to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
@@ -427,6 +517,7 @@ where
|
||||
DigestFor<Block>: Encode,
|
||||
BE: Backend<Block>,
|
||||
Client: ClientForGrandpa<Block, BE>,
|
||||
Client::Api: GrandpaApi<Block>,
|
||||
for<'a> &'a Client:
|
||||
BlockImport<Block, Error = ConsensusError, Transaction = TransactionFor<Client, Block>>,
|
||||
TransactionFor<Client, Block>: 'static,
|
||||
@@ -455,6 +546,10 @@ where
|
||||
Err(e) => return Err(ConsensusError::ClientImport(e.to_string())),
|
||||
}
|
||||
|
||||
if block.with_state() {
|
||||
return self.import_state(block, new_cache).await
|
||||
}
|
||||
|
||||
// on initial sync we will restrict logging under info to avoid spam.
|
||||
let initial_sync = block.origin == BlockOrigin::NetworkInitialSync;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user