-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Split block announce processing into two parts #6958
Changes from 115 commits
b336104
95c1420
0416a0b
f974fe7
7afdc67
67d811b
e714641
508dfcd
43cd1d0
0de5451
20d4ca4
4b3197c
9f590df
761ec7c
f7791d0
127673f
144192c
1f33b6e
ebd6d5c
ce89cc9
117bb45
4c0a477
3bddf6c
e4178cc
8f28655
6b2f7ea
7d53c94
539f4d2
8182870
b622015
dbbaef1
7972673
9231166
9007d28
8502300
f723458
0f302b9
3541fa8
f8189fc
658c389
b309241
130b7d4
29c993a
4dee242
68bdfec
8c92258
6deea30
8f4db26
2bc6943
52ae515
27aaf0a
49191fd
79cc67d
a22edf0
b4fbdda
67c778b
39d8f4d
5fa219d
0a850ae
29b42c3
384f29f
d123792
d35044c
de59f04
f96646a
89e6d66
bd44423
0f61352
0fd0d95
006f3f0
cc3040d
6db5fe3
bb7052d
a9a3be3
4b471dd
6c89d07
8b82790
a5977f5
caab538
5f6987a
c071d06
72ea91f
f5e0c63
b2b0db5
9d9cf8a
c2ef92d
b805faf
c867bc2
111a110
f406f49
d2c7c1f
0ddcd66
4e4c321
9167fe0
59b4668
2c65036
86026fc
da02c0b
f1380be
585629a
9bf2f2f
fa2fbe7
fbf617e
5a2c400
b7a3b2b
f8ee0e1
ecaf240
6b1d600
7cc397f
98a6a8c
f75c540
3a0cb2a
a837031
a0f3789
20c00ea
3f977ab
e352e41
f7f0873
4f252be
e08cbcf
41aa638
2b18234
047f80c
9cbfc19
8ea6c88
8e5a00a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -122,6 +122,8 @@ mod rep { | |
| pub const BAD_ROLE: Rep = Rep::new_fatal("Unsupported role"); | ||
| /// Peer response data does not have requested bits. | ||
| pub const BAD_RESPONSE: Rep = Rep::new(-(1 << 12), "Incomplete response"); | ||
| /// Peer send us a block announcement that failed at validation. | ||
| pub const BAD_BLOCK_ANNOUNCEMENT: Rep = Rep::new(-(1 << 12), "Bad block announcement"); | ||
| } | ||
|
|
||
| struct Metrics { | ||
|
|
@@ -542,7 +544,9 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> { | |
| pub fn update_chain(&mut self) { | ||
| let info = self.context_data.chain.info(); | ||
| self.sync.update_chain_info(&info.best_hash, info.best_number); | ||
| self.behaviour.set_legacy_handshake_message(build_status_message(&self.config, &self.context_data.chain)); | ||
| self.behaviour.set_legacy_handshake_message( | ||
| build_status_message(&self.config, &self.context_data.chain), | ||
| ); | ||
| self.behaviour.set_notif_protocol_handshake( | ||
| &self.block_announces_protocol, | ||
| BlockAnnouncesHandshake::build(&self.config, &self.context_data.chain).encode() | ||
|
|
@@ -573,11 +577,16 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> { | |
| who: PeerId, | ||
| data: BytesMut, | ||
| ) -> CustomMessageOutcome<B> { | ||
|
|
||
| let message = match <Message<B> as Decode>::decode(&mut &data[..]) { | ||
| Ok(message) => message, | ||
| Err(err) => { | ||
| debug!(target: "sync", "Couldn't decode packet sent by {}: {:?}: {}", who, data, err.what()); | ||
| debug!( | ||
| target: "sync", | ||
| "Couldn't decode packet sent by {}: {:?}: {}", | ||
| who, | ||
| data, | ||
| err.what(), | ||
| ); | ||
| self.peerset_handle.report_peer(who, rep::BAD_MESSAGE); | ||
| return CustomMessageOutcome::None; | ||
| } | ||
|
|
@@ -591,9 +600,7 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> { | |
| GenericMessage::Status(_) => | ||
| debug!(target: "sub-libp2p", "Received unexpected Status"), | ||
| GenericMessage::BlockAnnounce(announce) => { | ||
| let outcome = self.on_block_announce(who.clone(), announce); | ||
| self.update_peer_info(&who); | ||
| return outcome; | ||
| return self.push_block_announce_validation(who.clone(), announce) | ||
| }, | ||
| GenericMessage::Transactions(m) => | ||
| self.on_transactions(who, m), | ||
|
|
@@ -1156,51 +1163,79 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> { | |
| } | ||
| } | ||
|
|
||
| fn on_block_announce( | ||
| /// Push a block announce validation. | ||
| /// | ||
| /// It is required that [`ChainSync::poll_block_announce_validation`] is | ||
| /// called later to check for finished validations. The result of the validation | ||
| /// needs to be passed to [`Protocol::process_block_announce_validation_result`] | ||
| /// finish the processing. | ||
| fn push_block_announce_validation( | ||
| &mut self, | ||
| who: PeerId, | ||
| announce: BlockAnnounce<B::Header>, | ||
| ) -> CustomMessageOutcome<B> { | ||
| let hash = announce.header.hash(); | ||
| let number = *announce.header.number(); | ||
|
|
||
| if let Some(ref mut peer) = self.context_data.peers.get_mut(&who) { | ||
| peer.known_blocks.insert(hash.clone()); | ||
| } | ||
|
|
||
| let is_their_best = match announce.state.unwrap_or(message::BlockState::Best) { | ||
| let is_best = match announce.state.unwrap_or(message::BlockState::Best) { | ||
| message::BlockState::Best => true, | ||
| message::BlockState::Normal => false, | ||
| }; | ||
|
|
||
| match self.sync.on_block_announce(&who, hash, &announce, is_their_best) { | ||
| sync::OnBlockAnnounce::Nothing => { | ||
| if let Some(res) = self.sync.push_block_announce_validation(who, &hash, announce, is_best) { | ||
| self.process_block_announce_validation_result(res) | ||
| } else { | ||
| CustomMessageOutcome::None | ||
| } | ||
| } | ||
|
|
||
| /// Process the result of the block announce validation. | ||
| fn process_block_announce_validation_result( | ||
| &mut self, | ||
| validation_result: sync::BlockAnnounceResult<B::Header>, | ||
| ) -> CustomMessageOutcome<B> { | ||
| let (header, is_best, who) = match validation_result { | ||
| sync::BlockAnnounceResult::Nothing { is_best, who, header } => { | ||
| self.update_peer_info(&who); | ||
|
|
||
| // `on_block_announce` returns `OnBlockAnnounce::ImportHeader` | ||
| // when we have all data required to import the block | ||
| // in the BlockAnnounce message. This is only when: | ||
| // 1) we're on light client; | ||
| // AND | ||
| // 2) parent block is already imported and not pruned. | ||
| if is_their_best { | ||
| return CustomMessageOutcome::PeerNewBest(who, number); | ||
| if is_best { | ||
| return CustomMessageOutcome::PeerNewBest(who, *header.number()) | ||
| } else { | ||
| return CustomMessageOutcome::None; | ||
| return CustomMessageOutcome::None | ||
| } | ||
| } | ||
| sync::OnBlockAnnounce::ImportHeader => () // We proceed with the import. | ||
| } | ||
| sync::BlockAnnounceResult::ImportHeader { header, is_best, who } => { | ||
| self.update_peer_info(&who); | ||
| (header, is_best, who) | ||
| } | ||
| sync::BlockAnnounceResult::Failure { who } => { | ||
| self.report_peer(who, rep::BAD_BLOCK_ANNOUNCEMENT); | ||
| return CustomMessageOutcome::None | ||
| } | ||
| }; | ||
|
|
||
| // to import header from announced block let's construct response to request that normally would have | ||
| // been sent over network (but it is not in our case) | ||
| let number = *header.number(); | ||
|
|
||
| // to import header from announced block let's construct response to request that normally | ||
| // would have been sent over network (but it is not in our case) | ||
| let blocks_to_import = self.sync.on_block_data( | ||
| &who, | ||
| None, | ||
| message::generic::BlockResponse { | ||
| id: 0, | ||
| blocks: vec![ | ||
| message::generic::BlockData { | ||
| hash: hash, | ||
| header: Some(announce.header), | ||
| hash: header.hash(), | ||
| header: Some(header), | ||
| body: None, | ||
| receipt: None, | ||
| message_queue: None, | ||
|
|
@@ -1210,8 +1245,10 @@ impl<B: BlockT, H: ExHashT> Protocol<B, H> { | |
| }, | ||
| ); | ||
|
|
||
| if is_their_best { | ||
| self.pending_messages.push_back(CustomMessageOutcome::PeerNewBest(who, number)); | ||
| if is_best { | ||
| self.pending_messages.push_back( | ||
| CustomMessageOutcome::PeerNewBest(who, number), | ||
| ); | ||
| } | ||
|
|
||
| match blocks_to_import { | ||
|
|
@@ -1643,9 +1680,7 @@ impl<B: BlockT, H: ExHashT> NetworkBehaviour for Protocol<B, H> { | |
| } | ||
| Some(Fallback::BlockAnnounce) => { | ||
| if let Ok(announce) = message::BlockAnnounce::decode(&mut message.as_ref()) { | ||
| let outcome = self.on_block_announce(peer_id.clone(), announce); | ||
| self.update_peer_info(&peer_id); | ||
| outcome | ||
| self.push_block_announce_validation(peer_id, announce) | ||
|
mxinden marked this conversation as resolved.
Outdated
|
||
| } else { | ||
| warn!(target: "sub-libp2p", "Failed to decode block announce"); | ||
| CustomMessageOutcome::None | ||
|
|
@@ -1659,6 +1694,14 @@ impl<B: BlockT, H: ExHashT> NetworkBehaviour for Protocol<B, H> { | |
| }; | ||
|
|
||
| if let CustomMessageOutcome::None = outcome { | ||
| // Check if there is any block announcement validation finished. | ||
| while let Poll::Ready(result) = self.sync.poll_block_announce_validation(cx) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this nested within
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because you could have added a block announce above, which in most of the times will directly be finished when
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That should lead to a wake-up of the underlying task, which then results in this poll function being called again which then calls
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To wake up the underlying task, I need to poll a future at least once. And honestly, the same structure already exists above with these |
||
| match self.process_block_announce_validation_result(result) { | ||
| CustomMessageOutcome::None => continue, | ||
| outcome => return Poll::Ready(NetworkBehaviourAction::GenerateEvent(outcome)) | ||
| } | ||
| } | ||
|
|
||
| Poll::Pending | ||
| } else { | ||
| Poll::Ready(NetworkBehaviourAction::GenerateEvent(outcome)) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.