This repository was archived by the owner on Nov 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Beefy on-demand justifications as a custom RequestResponse protocol #12124
Merged
paritytech-processbot
merged 39 commits into
paritytech:master
from
acatangiu:beefy-custom-sync-protocol
Oct 3, 2022
Merged
Changes from all commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
46a4231
client/beefy: create communication module and move gossip there
acatangiu cda48fc
client/beefy: move beefy_protocol_name module to communication
acatangiu e8157d7
client/beefy: move notification module under communication
acatangiu f9bf81b
client/beefy: add incoming request_response protocol handler
acatangiu f68920e
client/beefy: keep track of connected peers and their progress
acatangiu 5fc1bb7
client/beefy: add logic for generating Justif requests
acatangiu 9f05d3a
client/beefy: cancel outdated on-demand justification requests
acatangiu ac5c3a5
try Andre's suggestion for JustificationEngine
acatangiu e9ebea7
justif engine add justifs validation
acatangiu fbd4f57
Merge branch 'master' of github.com:paritytech/substrate into beefy-c…
acatangiu 4ab5ab0
client/beefy: impl OnDemandJustificationsEngine async next()
acatangiu 88f8904
move beefy proto name test
acatangiu b5bf047
client/beefy: initialize OnDemandJustificationsEngine
acatangiu 2e47d2c
client/tests: allow for custom req-resp protocols
acatangiu fdebcaa
client/beefy: on-demand-justif: implement simple peer selection strategy
acatangiu 9aedbfa
Merge branch 'master' of github.com:paritytech/substrate into beefy-c…
acatangiu 2f02fba
client/beefy: fix voter initialization
acatangiu a9c60df
client/beefy: make sure justif requests are always out for mandatory …
acatangiu d48e199
client/beefy: add test for on-demand justifications sync
acatangiu 3cb39f7
client/beefy: tweak main loop event processing order
acatangiu 1908941
Merge branch 'master' of github.com:paritytech/substrate into beefy-c…
acatangiu d265845
Merge branch 'master' of github.com:paritytech/substrate into beefy-c…
acatangiu f76dd02
client/beefy: run on-demand-justif-handler under same async task as v…
acatangiu 5496ea8
client/beefy: add test for known-peers
acatangiu 940aaf2
client/beefy: reorg request-response module
acatangiu dbc2964
client/beefy: add issue references for future work todos
acatangiu b69471c
client/beefy: consolidate on-demand-justifications engine state machine
acatangiu b226996
Merge branch 'master' of github.com:paritytech/substrate into beefy-c…
acatangiu 68854a8
client/beefy: fix for polkadot companion
acatangiu 683ddc5
client/beefy: implement review suggestions
acatangiu 200cdf0
cargo fmt and clippy
acatangiu 7a8950d
Merge branch 'master' of github.com:paritytech/substrate into beefy-c…
acatangiu 447dc2d
fix merge damage
acatangiu 65cc99e
fix rust-doc
acatangiu 9d6cd2f
Merge branch 'master' of github.com:paritytech/substrate into beefy-c…
acatangiu c68cbef
fix merge damage
acatangiu 9a6bccd
fix merge damage
acatangiu b904741
client/beefy: add test for justif proto name
acatangiu fd50ee7
Merge branch 'master' of github.com:paritytech/substrate into beefy-c…
acatangiu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| // This file is part of Substrate. | ||
|
|
||
| // Copyright (C) 2022 Parity Technologies (UK) Ltd. | ||
| // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 | ||
|
|
||
| // This program is free software: you can redistribute it and/or modify | ||
| // it under the terms of the GNU General Public License as published by | ||
| // the Free Software Foundation, either version 3 of the License, or | ||
| // (at your option) any later version. | ||
|
|
||
| // This program is distributed in the hope that it will be useful, | ||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| // GNU General Public License for more details. | ||
|
|
||
| // You should have received a copy of the GNU General Public License | ||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
|
||
| //! Communication streams for the BEEFY networking protocols. | ||
|
|
||
| pub mod notification; | ||
| pub mod request_response; | ||
|
|
||
| pub(crate) mod gossip; | ||
| pub(crate) mod peers; | ||
|
|
||
| pub(crate) mod beefy_protocol_name { | ||
| use array_bytes::bytes2hex; | ||
| use sc_network::ProtocolName; | ||
|
|
||
| /// BEEFY votes gossip protocol name suffix. | ||
| const GOSSIP_NAME: &str = "/beefy/1"; | ||
| /// BEEFY justifications protocol name suffix. | ||
| const JUSTIFICATIONS_NAME: &str = "/beefy/justifications/1"; | ||
|
|
||
| /// Old names for the gossip protocol, used for backward compatibility. | ||
| pub(super) const LEGACY_NAMES: [&str; 1] = ["/paritytech/beefy/1"]; | ||
|
|
||
| /// Name of the votes gossip protocol used by BEEFY. | ||
| /// | ||
| /// Must be registered towards the networking in order for BEEFY voter to properly function. | ||
| pub fn gossip_protocol_name<Hash: AsRef<[u8]>>( | ||
| genesis_hash: Hash, | ||
| fork_id: Option<&str>, | ||
| ) -> ProtocolName { | ||
| let genesis_hash = genesis_hash.as_ref(); | ||
| if let Some(fork_id) = fork_id { | ||
| format!("/{}/{}{}", bytes2hex("", genesis_hash), fork_id, GOSSIP_NAME).into() | ||
| } else { | ||
| format!("/{}{}", bytes2hex("", genesis_hash), GOSSIP_NAME).into() | ||
| } | ||
| } | ||
|
|
||
| /// Name of the BEEFY justifications request-response protocol. | ||
| pub fn justifications_protocol_name<Hash: AsRef<[u8]>>( | ||
| genesis_hash: Hash, | ||
| fork_id: Option<&str>, | ||
| ) -> ProtocolName { | ||
| let genesis_hash = genesis_hash.as_ref(); | ||
| if let Some(fork_id) = fork_id { | ||
| format!("/{}/{}{}", bytes2hex("", genesis_hash), fork_id, JUSTIFICATIONS_NAME).into() | ||
| } else { | ||
| format!("/{}{}", bytes2hex("", genesis_hash), JUSTIFICATIONS_NAME).into() | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Returns the configuration value to put in | ||
| /// [`sc_network::config::NetworkConfiguration::extra_sets`]. | ||
| /// For standard protocol name see [`beefy_protocol_name::gossip_protocol_name`]. | ||
| pub fn beefy_peers_set_config( | ||
| gossip_protocol_name: sc_network::ProtocolName, | ||
| ) -> sc_network_common::config::NonDefaultSetConfig { | ||
| let mut cfg = | ||
| sc_network_common::config::NonDefaultSetConfig::new(gossip_protocol_name, 1024 * 1024); | ||
|
|
||
| cfg.allow_non_reserved(25, 25); | ||
| cfg.add_fallback_names(beefy_protocol_name::LEGACY_NAMES.iter().map(|&n| n.into()).collect()); | ||
| cfg | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| use sp_core::H256; | ||
|
|
||
| #[test] | ||
| fn beefy_protocols_names() { | ||
| use beefy_protocol_name::{gossip_protocol_name, justifications_protocol_name}; | ||
| // Create protocol name using random genesis hash. | ||
| let genesis_hash = H256::random(); | ||
| let genesis_hex = array_bytes::bytes2hex("", genesis_hash.as_ref()); | ||
|
|
||
| let expected_gossip_name = format!("/{}/beefy/1", genesis_hex); | ||
| let gossip_proto_name = gossip_protocol_name(&genesis_hash, None); | ||
| assert_eq!(gossip_proto_name.to_string(), expected_gossip_name); | ||
|
|
||
| let expected_justif_name = format!("/{}/beefy/justifications/1", genesis_hex); | ||
| let justif_proto_name = justifications_protocol_name(&genesis_hash, None); | ||
| assert_eq!(justif_proto_name.to_string(), expected_justif_name); | ||
|
|
||
| // Create protocol name using hardcoded genesis hash. Verify exact representation. | ||
| let genesis_hash = [ | ||
| 50, 4, 60, 123, 58, 106, 216, 246, 194, 188, 139, 193, 33, 212, 202, 171, 9, 55, 123, | ||
| 94, 8, 43, 12, 251, 187, 57, 173, 19, 188, 74, 205, 147, | ||
| ]; | ||
| let genesis_hex = "32043c7b3a6ad8f6c2bc8bc121d4caab09377b5e082b0cfbbb39ad13bc4acd93"; | ||
|
|
||
| let expected_gossip_name = format!("/{}/beefy/1", genesis_hex); | ||
| let gossip_proto_name = gossip_protocol_name(&genesis_hash, None); | ||
| assert_eq!(gossip_proto_name.to_string(), expected_gossip_name); | ||
|
|
||
| let expected_justif_name = format!("/{}/beefy/justifications/1", genesis_hex); | ||
| let justif_proto_name = justifications_protocol_name(&genesis_hash, None); | ||
| assert_eq!(justif_proto_name.to_string(), expected_justif_name); | ||
| } | ||
| } | ||
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| // This file is part of Substrate. | ||
|
|
||
| // Copyright (C) 2022 Parity Technologies (UK) Ltd. | ||
| // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 | ||
|
|
||
| // This program is free software: you can redistribute it and/or modify | ||
| // it under the terms of the GNU General Public License as published by | ||
| // the Free Software Foundation, either version 3 of the License, or | ||
| // (at your option) any later version. | ||
|
|
||
| // This program is distributed in the hope that it will be useful, | ||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| // GNU General Public License for more details. | ||
|
|
||
| // You should have received a copy of the GNU General Public License | ||
| // along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
|
|
||
| //! Logic for keeping track of BEEFY peers. | ||
|
|
||
| // TODO (issue #12296): replace this naive peer tracking with generic one that infers data | ||
| // from multiple network protocols. | ||
|
|
||
| use sc_network::PeerId; | ||
| use sp_runtime::traits::{Block, NumberFor, Zero}; | ||
| use std::collections::{HashMap, VecDeque}; | ||
|
|
||
| struct PeerData<B: Block> { | ||
| last_voted_on: NumberFor<B>, | ||
| } | ||
|
|
||
| impl<B: Block> Default for PeerData<B> { | ||
| fn default() -> Self { | ||
| PeerData { last_voted_on: Zero::zero() } | ||
| } | ||
| } | ||
|
|
||
| /// Keep a simple map of connected peers | ||
| /// and the most recent voting round they participated in. | ||
| pub struct KnownPeers<B: Block> { | ||
| live: HashMap<PeerId, PeerData<B>>, | ||
| } | ||
|
|
||
| impl<B: Block> KnownPeers<B> { | ||
| pub fn new() -> Self { | ||
| Self { live: HashMap::new() } | ||
| } | ||
|
|
||
| /// Add new connected `peer`. | ||
| pub fn add_new(&mut self, peer: PeerId) { | ||
| self.live.entry(peer).or_default(); | ||
| } | ||
|
|
||
| /// Note vote round number for `peer`. | ||
| pub fn note_vote_for(&mut self, peer: PeerId, round: NumberFor<B>) { | ||
| let data = self.live.entry(peer).or_default(); | ||
| data.last_voted_on = round.max(data.last_voted_on); | ||
| } | ||
|
|
||
| /// Remove connected `peer`. | ||
| pub fn remove(&mut self, peer: &PeerId) { | ||
| self.live.remove(peer); | ||
| } | ||
|
|
||
| /// Return _filtered and cloned_ list of peers that have voted on `block` or higher. | ||
| pub fn at_least_at_block(&self, block: NumberFor<B>) -> VecDeque<PeerId> { | ||
| self.live | ||
| .iter() | ||
| .filter_map(|(k, v)| (v.last_voted_on >= block).then_some(k)) | ||
| .cloned() | ||
| .collect() | ||
| } | ||
|
|
||
| /// Answer whether `peer` is part of `KnownPeers` set. | ||
| pub fn contains(&self, peer: &PeerId) -> bool { | ||
| self.live.contains_key(peer) | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| #[test] | ||
| fn should_track_known_peers_progress() { | ||
| let (alice, bob, charlie) = (PeerId::random(), PeerId::random(), PeerId::random()); | ||
| let mut peers = KnownPeers::<sc_network_test::Block>::new(); | ||
| assert!(peers.live.is_empty()); | ||
|
|
||
| // Alice and Bob new connected peers. | ||
| peers.add_new(alice); | ||
| peers.add_new(bob); | ||
| // 'Tracked' Bob seen voting for 5. | ||
| peers.note_vote_for(bob, 5); | ||
| // Previously unseen Charlie now seen voting for 10. | ||
| peers.note_vote_for(charlie, 10); | ||
|
|
||
| assert_eq!(peers.live.len(), 3); | ||
| assert!(peers.contains(&alice)); | ||
| assert!(peers.contains(&bob)); | ||
| assert!(peers.contains(&charlie)); | ||
|
|
||
| // Get peers at block >= 5 | ||
| let at_5 = peers.at_least_at_block(5); | ||
| // Should be Bob and Charlie | ||
| assert_eq!(at_5.len(), 2); | ||
| assert!(at_5.contains(&bob)); | ||
| assert!(at_5.contains(&charlie)); | ||
|
|
||
| // 'Tracked' Alice seen voting for 10. | ||
| peers.note_vote_for(alice, 10); | ||
|
|
||
| // Get peers at block >= 9 | ||
| let at_9 = peers.at_least_at_block(9); | ||
| // Should be Charlie and Alice | ||
| assert_eq!(at_9.len(), 2); | ||
| assert!(at_9.contains(&charlie)); | ||
| assert!(at_9.contains(&alice)); | ||
|
|
||
| // Remove Alice | ||
| peers.remove(&alice); | ||
| assert_eq!(peers.live.len(), 2); | ||
| assert!(!peers.contains(&alice)); | ||
|
|
||
| // Get peers at block >= 9 | ||
| let at_9 = peers.at_least_at_block(9); | ||
| // Now should be just Charlie | ||
| assert_eq!(at_9.len(), 1); | ||
| assert!(at_9.contains(&charlie)); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.