Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit ac78c90

Browse files
arkparseerscode
authored andcommitted
Header-only sync for old forks (#3942)
* Header-only sync for old forks * Simplified blocks-count * Update core/consensus/common/src/block_import.rs Co-Authored-By: Marcio Diaz <[email protected]>
1 parent 0aa2336 commit ac78c90

File tree

11 files changed

+179
-81
lines changed

11 files changed

+179
-81
lines changed

core/client/db/src/lib.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,12 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
894894
inmem
895895
}
896896

897+
/// Returns total numbet of blocks (headers) in the block DB.
898+
#[cfg(feature = "test-helpers")]
899+
pub fn blocks_count(&self) -> u64 {
900+
self.blockchain.db.iter(columns::HEADER).count() as u64
901+
}
902+
897903
/// Read (from storage or cache) changes trie config.
898904
///
899905
/// Currently changes tries configuration is set up once (at genesis) and could not
@@ -1115,7 +1121,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
11151121
);
11161122

11171123
transaction.put(columns::HEADER, &lookup_key, &pending_block.header.encode());
1118-
if let Some(body) = pending_block.body {
1124+
if let Some(body) = &pending_block.body {
11191125
transaction.put(columns::BODY, &lookup_key, &body.encode());
11201126
}
11211127
if let Some(justification) = pending_block.justification {
@@ -1127,21 +1133,26 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
11271133
transaction.put(columns::META, meta_keys::GENESIS_HASH, hash.as_ref());
11281134
}
11291135

1130-
let mut changeset: state_db::ChangeSet<Vec<u8>> = state_db::ChangeSet::default();
1131-
for (key, (val, rc)) in operation.db_updates.drain() {
1132-
if rc > 0 {
1133-
changeset.inserted.push((key, val.to_vec()));
1134-
} else if rc < 0 {
1135-
changeset.deleted.push(key);
1136+
let finalized = if pending_block.body.is_some() {
1137+
let mut changeset: state_db::ChangeSet<Vec<u8>> = state_db::ChangeSet::default();
1138+
for (key, (val, rc)) in operation.db_updates.drain() {
1139+
if rc > 0 {
1140+
changeset.inserted.push((key, val.to_vec()));
1141+
} else if rc < 0 {
1142+
changeset.deleted.push(key);
1143+
}
11361144
}
1137-
}
1138-
let number_u64 = number.saturated_into::<u64>();
1139-
let commit = self.storage.state_db.insert_block(&hash, number_u64, &pending_block.header.parent_hash(), changeset)
1140-
.map_err(|e: state_db::Error<io::Error>| client::error::Error::from(format!("State database error: {:?}", e)))?;
1141-
apply_state_commit(&mut transaction, commit);
1142-
1143-
// Check if need to finalize. Genesis is always finalized instantly.
1144-
let finalized = number_u64 == 0 || pending_block.leaf_state.is_final();
1145+
let number_u64 = number.saturated_into::<u64>();
1146+
let commit = self.storage.state_db.insert_block(&hash, number_u64, &pending_block.header.parent_hash(), changeset)
1147+
.map_err(|e: state_db::Error<io::Error>| client::error::Error::from(format!("State database error: {:?}", e)))?;
1148+
apply_state_commit(&mut transaction, commit);
1149+
1150+
// Check if need to finalize. Genesis is always finalized instantly.
1151+
let finalized = number_u64 == 0 || pending_block.leaf_state.is_final();
1152+
finalized
1153+
} else {
1154+
false
1155+
};
11451156

11461157
let header = &pending_block.header;
11471158
let is_best = pending_block.leaf_state.is_best();
@@ -1581,7 +1592,7 @@ mod tests {
15811592
};
15821593
let mut op = backend.begin_operation().unwrap();
15831594
backend.begin_state_operation(&mut op, block_id).unwrap();
1584-
op.set_block_data(header, None, None, NewBlockState::Best).unwrap();
1595+
op.set_block_data(header, Some(Vec::new()), None, NewBlockState::Best).unwrap();
15851596
op.update_changes_trie((changes_trie_update, ChangesTrieCacheAction::Clear)).unwrap();
15861597
backend.commit_operation(op).unwrap();
15871598

core/client/src/client.rs

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -927,22 +927,39 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
927927
BlockOrigin::Genesis | BlockOrigin::NetworkInitialSync | BlockOrigin::File => false,
928928
};
929929

930-
self.backend.begin_state_operation(&mut operation.op, BlockId::Hash(parent_hash))?;
930+
let storage_changes = match &body {
931+
Some(body) => {
932+
self.backend.begin_state_operation(&mut operation.op, BlockId::Hash(parent_hash))?;
933+
934+
// ensure parent block is finalized to maintain invariant that
935+
// finality is called sequentially.
936+
if finalized {
937+
self.apply_finality_with_block_hash(operation, parent_hash, None, info.best_hash, make_notifications)?;
938+
}
931939

932-
// ensure parent block is finalized to maintain invariant that
933-
// finality is called sequentially.
934-
if finalized {
935-
self.apply_finality_with_block_hash(operation, parent_hash, None, info.best_hash, make_notifications)?;
936-
}
940+
// FIXME #1232: correct path logic for when to execute this function
941+
let (storage_update, changes_update, storage_changes) = self.block_execution(
942+
&operation.op,
943+
&import_headers,
944+
origin,
945+
hash,
946+
&body,
947+
)?;
937948

938-
// FIXME #1232: correct path logic for when to execute this function
939-
let (storage_update, changes_update, storage_changes) = self.block_execution(
940-
&operation.op,
941-
&import_headers,
942-
origin,
943-
hash,
944-
body.clone(),
945-
)?;
949+
operation.op.update_cache(new_cache);
950+
if let Some(storage_update) = storage_update {
951+
operation.op.update_db_storage(storage_update)?;
952+
}
953+
if let Some(storage_changes) = storage_changes.clone() {
954+
operation.op.update_storage(storage_changes.0, storage_changes.1)?;
955+
}
956+
if let Some(Some(changes_update)) = changes_update {
957+
operation.op.update_changes_trie(changes_update)?;
958+
}
959+
storage_changes
960+
},
961+
None => Default::default()
962+
};
946963

947964
let is_new_best = finalized || match fork_choice {
948965
ForkChoiceStrategy::LongestChain => import_headers.post().number() > &info.best_number,
@@ -977,17 +994,6 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
977994
leaf_state,
978995
)?;
979996

980-
operation.op.update_cache(new_cache);
981-
if let Some(storage_update) = storage_update {
982-
operation.op.update_db_storage(storage_update)?;
983-
}
984-
if let Some(storage_changes) = storage_changes.clone() {
985-
operation.op.update_storage(storage_changes.0, storage_changes.1)?;
986-
}
987-
if let Some(Some(changes_update)) = changes_update {
988-
operation.op.update_changes_trie(changes_update)?;
989-
}
990-
991997
operation.op.insert_aux(aux)?;
992998

993999
if make_notifications {
@@ -1014,7 +1020,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
10141020
import_headers: &PrePostHeader<Block::Header>,
10151021
origin: BlockOrigin,
10161022
hash: Block::Hash,
1017-
body: Option<Vec<Block::Extrinsic>>,
1023+
body: &[Block::Extrinsic],
10181024
) -> error::Result<(
10191025
Option<StorageUpdate<B, Block>>,
10201026
Option<Option<ChangesUpdate<Block>>>,
@@ -1052,7 +1058,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
10521058

10531059
let encoded_block = <Block as BlockT>::encode_from(
10541060
import_headers.pre(),
1055-
&body.unwrap_or_default()
1061+
body,
10561062
);
10571063

10581064
let (_, storage_update, changes_update) = self.executor
@@ -1523,7 +1529,7 @@ impl<'a, B, E, Block, RA> consensus::BlockImport<Block> for &'a Client<B, E, Blo
15231529
&mut self,
15241530
block: BlockCheckParams<Block>,
15251531
) -> Result<ImportResult, Self::Error> {
1526-
let BlockCheckParams { hash, number, parent_hash } = block;
1532+
let BlockCheckParams { hash, number, parent_hash, header_only } = block;
15271533

15281534
if let Some(h) = self.fork_blocks.as_ref().and_then(|x| x.get(&number)) {
15291535
if &hash != h {
@@ -1541,7 +1547,9 @@ impl<'a, B, E, Block, RA> consensus::BlockImport<Block> for &'a Client<B, E, Blo
15411547
.map_err(|e| ConsensusError::ClientImport(e.to_string()))?
15421548
{
15431549
BlockStatus::InChainWithState | BlockStatus::Queued => {},
1544-
BlockStatus::Unknown | BlockStatus::InChainPruned => return Ok(ImportResult::UnknownParent),
1550+
BlockStatus::Unknown => return Ok(ImportResult::UnknownParent),
1551+
BlockStatus::InChainPruned if header_only => {},
1552+
BlockStatus::InChainPruned => return Ok(ImportResult::MissingState),
15451553
BlockStatus::KnownBad => return Ok(ImportResult::KnownBad),
15461554
}
15471555

@@ -1553,7 +1561,6 @@ impl<'a, B, E, Block, RA> consensus::BlockImport<Block> for &'a Client<B, E, Blo
15531561
BlockStatus::KnownBad => return Ok(ImportResult::KnownBad),
15541562
}
15551563

1556-
15571564
Ok(ImportResult::imported(false))
15581565
}
15591566
}

core/consensus/common/src/block_import.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,15 @@ pub enum ImportResult {
3535
KnownBad,
3636
/// Block parent is not in the chain.
3737
UnknownParent,
38+
/// Parent state is missing.
39+
MissingState,
3840
}
3941

4042
/// Auxiliary data associated with an imported block result.
4143
#[derive(Debug, Default, PartialEq, Eq)]
4244
pub struct ImportedAux {
45+
/// Only the header has been imported. Block body verification was skipped.
46+
pub header_only: bool,
4347
/// Clear all pending justification requests.
4448
pub clear_justification_requests: bool,
4549
/// Request a justification for the given block.
@@ -98,6 +102,8 @@ pub struct BlockCheckParams<Block: BlockT> {
98102
pub number: NumberFor<Block>,
99103
/// Parent hash of the block that we verify.
100104
pub parent_hash: Block::Hash,
105+
/// Don't check state availability
106+
pub header_only: bool,
101107
}
102108

103109
/// Data required to import a Block.

core/consensus/common/src/import_queue.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ pub fn import_single_block<B: BlockT, V: Verifier<B>>(
203203
Ok(BlockImportResult::ImportedKnown(number))
204204
},
205205
Ok(ImportResult::Imported(aux)) => Ok(BlockImportResult::ImportedUnknown(number, aux, peer.clone())),
206+
Ok(ImportResult::MissingState) => {
207+
debug!(target: "sync", "Parent state is missing for {}: {:?}, parent: {:?}", number, hash, parent_hash);
208+
Err(BlockImportError::UnknownParent)
209+
},
206210
Ok(ImportResult::UnknownParent) => {
207211
debug!(target: "sync", "Block with unknown parent {}: {:?}, parent: {:?}", number, hash, parent_hash);
208212
Err(BlockImportError::UnknownParent)
@@ -217,7 +221,12 @@ pub fn import_single_block<B: BlockT, V: Verifier<B>>(
217221
}
218222
}
219223
};
220-
match import_error(import_handle.check_block(BlockCheckParams { hash, number, parent_hash }))? {
224+
match import_error(import_handle.check_block(BlockCheckParams {
225+
hash,
226+
number,
227+
parent_hash,
228+
header_only: block.body.is_none(),
229+
}))? {
221230
BlockImportResult::ImportedUnknown { .. } => (),
222231
r => return Ok(r), // Any other successful result means that the block is already imported.
223232
}

core/finality-grandpa/src/light_import.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,7 @@ pub mod tests {
680680
bad_justification: false,
681681
needs_finality_proof: false,
682682
is_new_best: true,
683+
header_only: false,
683684
}));
684685
}
685686

@@ -692,6 +693,7 @@ pub mod tests {
692693
bad_justification: false,
693694
needs_finality_proof: false,
694695
is_new_best: true,
696+
header_only: false,
695697
}));
696698
}
697699

@@ -705,6 +707,7 @@ pub mod tests {
705707
bad_justification: false,
706708
needs_finality_proof: true,
707709
is_new_best: true,
710+
header_only: false,
708711
}));
709712
}
710713

@@ -721,6 +724,7 @@ pub mod tests {
721724
bad_justification: false,
722725
needs_finality_proof: true,
723726
is_new_best: false,
727+
header_only: false,
724728
},
725729
));
726730
}

core/finality-grandpa/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,7 @@ fn allows_reimporting_change_blocks() {
984984
bad_justification: false,
985985
needs_finality_proof: false,
986986
is_new_best: true,
987+
header_only: false,
987988
}),
988989
);
989990

0 commit comments

Comments
 (0)