mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 14:01:02 +00:00
Warp sync part II (#9284)
* Gap sync * Gap epoch test * Simplified network requests * Update client/db/src/utils.rs Co-authored-by: cheme <emericchevalier.pro@gmail.com> * Fixed v1 migration and added some comments * Next epoch is always regular * Removed fork tree change * Apply suggestions from code review Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Added a comment and converted assert to error Co-authored-by: cheme <emericchevalier.pro@gmail.com> Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com>
This commit is contained in:
@@ -168,7 +168,7 @@ pub struct AuthoritySet<H, N> {
|
||||
/// Track at which blocks the set id changed. This is useful when we need to prove finality for
|
||||
/// a given block since we can figure out what set the block belongs to and when the set
|
||||
/// started/ended.
|
||||
authority_set_changes: AuthoritySetChanges<N>,
|
||||
pub(crate) authority_set_changes: AuthoritySetChanges<N>,
|
||||
}
|
||||
|
||||
impl<H, N> AuthoritySet<H, N>
|
||||
@@ -714,6 +714,17 @@ impl<N: Ord + Clone> AuthoritySetChanges<N> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn insert(&mut self, block_number: N) {
|
||||
let idx = self
|
||||
.0
|
||||
.binary_search_by_key(&block_number, |(_, n)| n.clone())
|
||||
.unwrap_or_else(|b| b);
|
||||
|
||||
let set_id = if idx == 0 { 0 } else { self.0[idx - 1].0 + 1 };
|
||||
assert!(idx == self.0.len() || self.0[idx].0 != set_id);
|
||||
self.0.insert(idx, (set_id, block_number));
|
||||
}
|
||||
|
||||
/// Returns an iterator over all historical authority set changes starting at the given block
|
||||
/// number (excluded). The iterator yields a tuple representing the set id and the block number
|
||||
/// of the last block in that set.
|
||||
@@ -1632,6 +1643,18 @@ mod tests {
|
||||
assert_eq!(authorities.pending_forced_changes.first().unwrap().canon_hash, "D");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authority_set_changes_insert() {
|
||||
let mut authority_set_changes = AuthoritySetChanges::empty();
|
||||
authority_set_changes.append(0, 41);
|
||||
authority_set_changes.append(1, 81);
|
||||
authority_set_changes.append(4, 121);
|
||||
|
||||
authority_set_changes.insert(101);
|
||||
assert_eq!(authority_set_changes.get_set_id(100), AuthoritySetChangeId::Set(2, 101));
|
||||
assert_eq!(authority_set_changes.get_set_id(101), AuthoritySetChangeId::Set(2, 101));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authority_set_changes_for_complete_data() {
|
||||
let mut authority_set_changes = AuthoritySetChanges::empty();
|
||||
|
||||
@@ -551,6 +551,32 @@ where
|
||||
return self.import_state(block, new_cache).await
|
||||
}
|
||||
|
||||
if number <= self.inner.info().finalized_number {
|
||||
// Importing an old block. Just save justifications and authority set changes
|
||||
if self.check_new_change(&block.header, hash).is_some() {
|
||||
if block.justifications.is_none() {
|
||||
return Err(ConsensusError::ClientImport(
|
||||
"Justification required when importing \
|
||||
an old block with authority set change."
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
assert!(block.justifications.is_some());
|
||||
let mut authority_set = self.authority_set.inner_locked();
|
||||
authority_set.authority_set_changes.insert(number);
|
||||
crate::aux_schema::update_authority_set::<Block, _, _>(
|
||||
&authority_set,
|
||||
None,
|
||||
|insert| {
|
||||
block
|
||||
.auxiliary
|
||||
.extend(insert.iter().map(|(k, v)| (k.to_vec(), Some(v.to_vec()))))
|
||||
},
|
||||
);
|
||||
}
|
||||
return (&*self.inner).import_block(block, new_cache).await
|
||||
}
|
||||
|
||||
// on initial sync we will restrict logging under info to avoid spam.
|
||||
let initial_sync = block.origin == BlockOrigin::NetworkInitialSync;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ use sp_runtime::{
|
||||
traits::{Block as BlockT, Header as HeaderT, NumberFor, One},
|
||||
};
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
/// Warp proof processing error.
|
||||
#[derive(Debug, derive_more::Display, derive_more::From)]
|
||||
@@ -194,6 +194,7 @@ impl<Block: BlockT> WarpSyncProof<Block> {
|
||||
&self,
|
||||
set_id: SetId,
|
||||
authorities: AuthorityList,
|
||||
hard_forks: &HashMap<(Block::Hash, NumberFor<Block>), (SetId, AuthorityList)>,
|
||||
) -> Result<(SetId, AuthorityList), Error>
|
||||
where
|
||||
NumberFor<Block>: BlockNumberOps,
|
||||
@@ -202,26 +203,34 @@ impl<Block: BlockT> WarpSyncProof<Block> {
|
||||
let mut current_authorities = authorities;
|
||||
|
||||
for (fragment_num, proof) in self.proofs.iter().enumerate() {
|
||||
proof
|
||||
.justification
|
||||
.verify(current_set_id, ¤t_authorities)
|
||||
.map_err(|err| Error::InvalidProof(err.to_string()))?;
|
||||
let hash = proof.header.hash();
|
||||
let number = *proof.header.number();
|
||||
|
||||
if proof.justification.target().1 != proof.header.hash() {
|
||||
return Err(Error::InvalidProof(
|
||||
"Mismatch between header and justification".to_owned(),
|
||||
))
|
||||
}
|
||||
if let Some((set_id, list)) = hard_forks.get(&(hash.clone(), number)) {
|
||||
current_set_id = *set_id;
|
||||
current_authorities = list.clone();
|
||||
} else {
|
||||
proof
|
||||
.justification
|
||||
.verify(current_set_id, ¤t_authorities)
|
||||
.map_err(|err| Error::InvalidProof(err.to_string()))?;
|
||||
|
||||
if let Some(scheduled_change) = find_scheduled_change::<Block>(&proof.header) {
|
||||
current_authorities = scheduled_change.next_authorities;
|
||||
current_set_id += 1;
|
||||
} else if fragment_num != self.proofs.len() - 1 || !self.is_finished {
|
||||
// Only the last fragment of the last proof message is allowed to be missing
|
||||
// the authority set change.
|
||||
return Err(Error::InvalidProof(
|
||||
"Header is missing authority set change digest".to_string(),
|
||||
))
|
||||
if proof.justification.target().1 != hash {
|
||||
return Err(Error::InvalidProof(
|
||||
"Mismatch between header and justification".to_owned(),
|
||||
))
|
||||
}
|
||||
|
||||
if let Some(scheduled_change) = find_scheduled_change::<Block>(&proof.header) {
|
||||
current_authorities = scheduled_change.next_authorities;
|
||||
current_set_id += 1;
|
||||
} else if fragment_num != self.proofs.len() - 1 || !self.is_finished {
|
||||
// Only the last fragment of the last proof message is allowed to be missing the
|
||||
// authority set change.
|
||||
return Err(Error::InvalidProof(
|
||||
"Header is missing authority set change digest".to_string(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok((current_set_id, current_authorities))
|
||||
@@ -235,6 +244,7 @@ where
|
||||
{
|
||||
backend: Arc<Backend>,
|
||||
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
|
||||
hard_forks: HashMap<(Block::Hash, NumberFor<Block>), (SetId, AuthorityList)>,
|
||||
}
|
||||
|
||||
impl<Block: BlockT, Backend: ClientBackend<Block>> NetworkProvider<Block, Backend>
|
||||
@@ -245,8 +255,13 @@ where
|
||||
pub fn new(
|
||||
backend: Arc<Backend>,
|
||||
authority_set: SharedAuthoritySet<Block::Hash, NumberFor<Block>>,
|
||||
hard_forks: Vec<(SetId, (Block::Hash, NumberFor<Block>), AuthorityList)>,
|
||||
) -> Self {
|
||||
NetworkProvider { backend, authority_set }
|
||||
NetworkProvider {
|
||||
backend,
|
||||
authority_set,
|
||||
hard_forks: hard_forks.into_iter().map(|(s, hn, list)| (hn, (s, list))).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +298,7 @@ where
|
||||
.map(|p| p.header.clone())
|
||||
.ok_or_else(|| "Empty proof".to_string())?;
|
||||
let (next_set_id, next_authorities) =
|
||||
proof.verify(set_id, authorities).map_err(Box::new)?;
|
||||
proof.verify(set_id, authorities, &self.hard_forks).map_err(Box::new)?;
|
||||
if proof.is_finished {
|
||||
Ok(VerificationResult::<Block>::Complete(next_set_id, next_authorities, last_header))
|
||||
} else {
|
||||
@@ -417,7 +432,8 @@ mod tests {
|
||||
WarpSyncProof::generate(&*backend, genesis_hash, &authority_set_changes).unwrap();
|
||||
|
||||
// verifying the proof should yield the last set id and authorities
|
||||
let (new_set_id, new_authorities) = warp_sync_proof.verify(0, genesis_authorities).unwrap();
|
||||
let (new_set_id, new_authorities) =
|
||||
warp_sync_proof.verify(0, genesis_authorities, &Default::default()).unwrap();
|
||||
|
||||
let expected_authorities = current_authorities
|
||||
.iter()
|
||||
|
||||
Reference in New Issue
Block a user