Skip to content

Commit 7734222

Browse files
bkchrdarkfriend77
authored andcommitted
Inform sync explicitly about new best block (paritytech#7604)
* Inform sync explicitly about new best block Instead of "fishing" the new best block out of the processed blocks, we now tell sync directly that there is a new best block. It also makes sure that we update the corresponding sync handshake to the new best block. This is required for parachains as they first import blocks and declare the new best block after being made aware of it by the relay chain. * Adds test * Make sure async stuff had time to run
1 parent d4fe89a commit 7734222

File tree

7 files changed

+84
-55
lines changed

7 files changed

+84
-55
lines changed

client/network/src/protocol.rs

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -528,10 +528,9 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
528528
self.sync.num_sync_requests()
529529
}
530530

531-
/// Sync local state with the blockchain state.
532-
pub fn update_chain(&mut self) {
533-
let info = self.context_data.chain.info();
534-
self.sync.update_chain_info(&info.best_hash, info.best_number);
531+
/// Inform sync about new best imported block.
532+
pub fn new_best_block_imported(&mut self, hash: B::Hash, number: NumberFor<B>) {
533+
self.sync.update_chain_info(&hash, number);
535534
self.behaviour.set_legacy_handshake_message(
536535
build_status_message(&self.config, &self.context_data.chain),
537536
);
@@ -541,11 +540,6 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
541540
);
542541
}
543542

544-
/// Inform sync about an own imported block.
545-
pub fn own_block_imported(&mut self, hash: B::Hash, number: NumberFor<B>) {
546-
self.sync.update_chain_info(&hash, number);
547-
}
548-
549543
fn update_peer_info(&mut self, who: &PeerId) {
550544
if let Some(info) = self.sync.peer_info(who) {
551545
if let Some(ref mut peer) = self.context_data.peers.get_mut(who) {
@@ -1258,18 +1252,6 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> {
12581252
count: usize,
12591253
results: Vec<(Result<BlockImportResult<NumberFor<B>>, BlockImportError>, B::Hash)>
12601254
) {
1261-
let new_best = results.iter().rev().find_map(|r| match r {
1262-
(Ok(BlockImportResult::ImportedUnknown(n, aux, _)), hash) if aux.is_new_best => Some((*n, hash.clone())),
1263-
_ => None,
1264-
});
1265-
if let Some((best_num, best_hash)) = new_best {
1266-
self.sync.update_chain_info(&best_hash, best_num);
1267-
self.behaviour.set_legacy_handshake_message(build_status_message(&self.config, &self.context_data.chain));
1268-
self.behaviour.set_notif_protocol_handshake(
1269-
&self.block_announces_protocol,
1270-
BlockAnnouncesHandshake::build(&self.config, &self.context_data.chain).encode()
1271-
);
1272-
}
12731255
let results = self.sync.on_blocks_processed(
12741256
imported,
12751257
count,

client/network/src/service.rs

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -484,11 +484,9 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkWorker<B, H> {
484484
self.network_service.user_protocol_mut().on_block_finalized(hash, &header);
485485
}
486486

487-
/// This should be called when blocks are added to the
488-
/// chain by something other than the import queue.
489-
/// Currently this is only useful for tests.
490-
pub fn update_chain(&mut self) {
491-
self.network_service.user_protocol_mut().update_chain();
487+
/// Inform the network service about new best imported block.
488+
pub fn new_best_block_imported(&mut self, hash: B::Hash, number: NumberFor<B>) {
489+
self.network_service.user_protocol_mut().new_best_block_imported(hash, number);
492490
}
493491

494492
/// Returns the local `PeerId`.
@@ -1012,21 +1010,11 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkService<B, H> {
10121010
self.num_connected.load(Ordering::Relaxed)
10131011
}
10141012

1015-
/// This function should be called when blocks are added to the chain by something other
1016-
/// than the import queue.
1017-
///
1018-
/// > **Important**: This function is a hack and can be removed at any time. Do **not** use it.
1019-
pub fn update_chain(&self) {
1020-
let _ = self
1021-
.to_worker
1022-
.unbounded_send(ServiceToWorkerMsg::UpdateChain);
1023-
}
1024-
1025-
/// Inform the network service about an own imported block.
1026-
pub fn own_block_imported(&self, hash: B::Hash, number: NumberFor<B>) {
1013+
/// Inform the network service about new best imported block.
1014+
pub fn new_best_block_imported(&self, hash: B::Hash, number: NumberFor<B>) {
10271015
let _ = self
10281016
.to_worker
1029-
.unbounded_send(ServiceToWorkerMsg::OwnBlockImported(hash, number));
1017+
.unbounded_send(ServiceToWorkerMsg::NewBestBlockImported(hash, number));
10301018
}
10311019

10321020
/// Utility function to extract `PeerId` from each `Multiaddr` for priority group updates.
@@ -1181,8 +1169,7 @@ enum ServiceToWorkerMsg<B: BlockT, H: ExHashT> {
11811169
protocol_name: Cow<'static, str>,
11821170
},
11831171
DisconnectPeer(PeerId),
1184-
UpdateChain,
1185-
OwnBlockImported(B::Hash, NumberFor<B>),
1172+
NewBestBlockImported(B::Hash, NumberFor<B>),
11861173
}
11871174

11881175
/// Main network worker. Must be polled in order for the network to advance.
@@ -1319,10 +1306,8 @@ impl<B: BlockT + 'static, H: ExHashT> Future for NetworkWorker<B, H> {
13191306
this.network_service.register_notifications_protocol(protocol_name),
13201307
ServiceToWorkerMsg::DisconnectPeer(who) =>
13211308
this.network_service.user_protocol_mut().disconnect_peer(&who),
1322-
ServiceToWorkerMsg::UpdateChain =>
1323-
this.network_service.user_protocol_mut().update_chain(),
1324-
ServiceToWorkerMsg::OwnBlockImported(hash, number) =>
1325-
this.network_service.user_protocol_mut().own_block_imported(hash, number),
1309+
ServiceToWorkerMsg::NewBestBlockImported(hash, number) =>
1310+
this.network_service.user_protocol_mut().new_best_block_imported(hash, number),
13261311
}
13271312
}
13281313

client/network/test/src/lib.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ impl<D> Peer<D> {
279279
where F: FnMut(BlockBuilder<Block, PeersFullClient, substrate_test_runtime_client::Backend>) -> Block
280280
{
281281
let best_hash = self.client.info().best_hash;
282-
self.generate_blocks_at(BlockId::Hash(best_hash), count, origin, edit_block, false)
282+
self.generate_blocks_at(BlockId::Hash(best_hash), count, origin, edit_block, false, true)
283283
}
284284

285285
/// Add blocks to the peer -- edit the block before adding. The chain will
@@ -291,6 +291,7 @@ impl<D> Peer<D> {
291291
origin: BlockOrigin,
292292
mut edit_block: F,
293293
headers_only: bool,
294+
inform_sync_about_new_best_block: bool,
294295
) -> H256 where F: FnMut(BlockBuilder<Block, PeersFullClient, substrate_test_runtime_client::Backend>) -> Block {
295296
let full_client = self.client.as_full()
296297
.expect("blocks could only be generated by full clients");
@@ -328,7 +329,12 @@ impl<D> Peer<D> {
328329
at = hash;
329330
}
330331

331-
self.network.update_chain();
332+
if inform_sync_about_new_best_block {
333+
self.network.new_best_block_imported(
334+
at,
335+
full_client.header(&BlockId::Hash(at)).ok().flatten().unwrap().number().clone(),
336+
);
337+
}
332338
self.network.service().announce_block(at.clone(), Vec::new());
333339
at
334340
}
@@ -342,18 +348,36 @@ impl<D> Peer<D> {
342348
/// Push blocks to the peer (simplified: with or without a TX)
343349
pub fn push_headers(&mut self, count: usize) -> H256 {
344350
let best_hash = self.client.info().best_hash;
345-
self.generate_tx_blocks_at(BlockId::Hash(best_hash), count, false, true)
351+
self.generate_tx_blocks_at(BlockId::Hash(best_hash), count, false, true, true)
346352
}
347353

348354
/// Push blocks to the peer (simplified: with or without a TX) starting from
349355
/// given hash.
350356
pub fn push_blocks_at(&mut self, at: BlockId<Block>, count: usize, with_tx: bool) -> H256 {
351-
self.generate_tx_blocks_at(at, count, with_tx, false)
357+
self.generate_tx_blocks_at(at, count, with_tx, false, true)
358+
}
359+
360+
/// Push blocks to the peer (simplified: with or without a TX) starting from
361+
/// given hash without informing the sync protocol about the new best block.
362+
pub fn push_blocks_at_without_informing_sync(
363+
&mut self,
364+
at: BlockId<Block>,
365+
count: usize,
366+
with_tx: bool,
367+
) -> H256 {
368+
self.generate_tx_blocks_at(at, count, with_tx, false, false)
352369
}
353370

354371
/// Push blocks/headers to the peer (simplified: with or without a TX) starting from
355372
/// given hash.
356-
fn generate_tx_blocks_at(&mut self, at: BlockId<Block>, count: usize, with_tx: bool, headers_only:bool) -> H256 {
373+
fn generate_tx_blocks_at(
374+
&mut self,
375+
at: BlockId<Block>,
376+
count: usize,
377+
with_tx: bool,
378+
headers_only: bool,
379+
inform_sync_about_new_best_block: bool,
380+
) -> H256 {
357381
let mut nonce = 0;
358382
if with_tx {
359383
self.generate_blocks_at(
@@ -370,7 +394,8 @@ impl<D> Peer<D> {
370394
nonce = nonce + 1;
371395
builder.build().unwrap().block
372396
},
373-
headers_only
397+
headers_only,
398+
inform_sync_about_new_best_block,
374399
)
375400
} else {
376401
self.generate_blocks_at(
@@ -379,6 +404,7 @@ impl<D> Peer<D> {
379404
BlockOrigin::File,
380405
|builder| builder.build().unwrap().block,
381406
headers_only,
407+
inform_sync_about_new_best_block,
382408
)
383409
}
384410
}

client/network/test/src/sync.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -779,3 +779,38 @@ fn wait_until_deferred_block_announce_validation_is_ready() {
779779
net.block_until_idle();
780780
}
781781
}
782+
783+
/// When we don't inform the sync protocol about the best block, a node will not sync from us as the
784+
/// handshake is not does not contain our best block.
785+
#[test]
786+
fn sync_to_tip_requires_that_sync_protocol_is_informed_about_best_block() {
787+
sp_tracing::try_init_simple();
788+
log::trace!(target: "sync", "Test");
789+
let mut net = TestNet::new(1);
790+
791+
// Produce some blocks
792+
let block_hash = net.peer(0).push_blocks_at_without_informing_sync(BlockId::Number(0), 3, true);
793+
794+
// Add a node and wait until they are connected
795+
net.add_full_peer_with_config(Default::default());
796+
net.block_until_connected();
797+
net.block_until_idle();
798+
799+
// The peer should not have synced the block.
800+
assert!(!net.peer(1).has_block(&block_hash));
801+
802+
// Make sync protocol aware of the best block
803+
net.peer(0).network_service().new_best_block_imported(block_hash, 3);
804+
net.block_until_idle();
805+
806+
// Connect another node that should now sync to the tip
807+
net.add_full_peer_with_config(Default::default());
808+
net.block_until_connected();
809+
810+
while !net.peer(2).has_block(&block_hash) {
811+
net.block_until_idle();
812+
}
813+
814+
// However peer 1 should still not have the block.
815+
assert!(!net.peer(1).has_block(&block_hash));
816+
}

client/service/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ async fn build_network_future<
250250
network.service().announce_block(notification.hash, Vec::new());
251251
}
252252

253-
if let sp_consensus::BlockOrigin::Own = notification.origin {
254-
network.service().own_block_imported(
253+
if notification.is_new_best {
254+
network.service().new_best_block_imported(
255255
notification.hash,
256256
notification.header.number().clone(),
257257
);

client/service/test/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,8 @@ pub fn sync<G, E, Fb, F, Lb, L, B, ExF, U>(
542542

543543
make_block_and_import(&first_service, first_user_data);
544544
}
545-
network.full_nodes[0].1.network().update_chain();
545+
let info = network.full_nodes[0].1.client().info();
546+
network.full_nodes[0].1.network().new_best_block_imported(info.best_hash, info.best_number);
546547
network.full_nodes[0].3.clone()
547548
};
548549

primitives/consensus/common/src/import_queue.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ pub trait Link<B: BlockT>: Send {
136136

137137
/// Block import successful result.
138138
#[derive(Debug, PartialEq)]
139-
pub enum BlockImportResult<N: ::std::fmt::Debug + PartialEq> {
139+
pub enum BlockImportResult<N: std::fmt::Debug + PartialEq> {
140140
/// Imported known block.
141141
ImportedKnown(N),
142142
/// Imported unknown block.

0 commit comments

Comments
 (0)