Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions client/beefy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub use beefy_protocol_name::standard_name as protocol_standard_name;

pub(crate) mod beefy_protocol_name {
use sc_chain_spec::ChainSpec;
use sc_network::protocol_name::standard_protocol_name;

const NAME: &str = "/beefy/1";
/// Old names for the notifications protocol, used for backward compatibility.
Expand All @@ -62,11 +63,7 @@ pub(crate) mod beefy_protocol_name {
genesis_hash: &Hash,
chain_spec: &Box<dyn ChainSpec>,
) -> std::borrow::Cow<'static, str> {
let chain_prefix = match chain_spec.fork_id() {
Some(fork_id) => format!("/{}/{}", hex::encode(genesis_hash), fork_id),
None => format!("/{}", hex::encode(genesis_hash)),
};
format!("{}{}", chain_prefix, NAME).into()
standard_protocol_name(genesis_hash, &chain_spec.fork_id().map(ToOwned::to_owned), NAME)
}
}

Expand Down
7 changes: 2 additions & 5 deletions client/finality-grandpa/src/communication/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub(crate) mod tests;

pub mod grandpa_protocol_name {
use sc_chain_spec::ChainSpec;
use sc_network::protocol_name::standard_protocol_name;

pub(crate) const NAME: &str = "/grandpa/1";
/// Old names for the notifications protocol, used for backward compatibility.
Expand All @@ -81,11 +82,7 @@ pub mod grandpa_protocol_name {
genesis_hash: &Hash,
chain_spec: &Box<dyn ChainSpec>,
) -> std::borrow::Cow<'static, str> {
let chain_prefix = match chain_spec.fork_id() {
Some(fork_id) => format!("/{}/{}", hex::encode(genesis_hash), fork_id),
None => format!("/{}", hex::encode(genesis_hash)),
};
format!("{}{}", chain_prefix, NAME).into()
standard_protocol_name(genesis_hash, &chain_spec.fork_id().map(ToOwned::to_owned), NAME)
}
}

Expand Down
6 changes: 5 additions & 1 deletion client/network/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,13 @@ where
/// the network.
pub transaction_pool: Arc<dyn TransactionPool<H, B>>,

/// Name of the protocol to use on the wire. Should be different for each chain.
/// Legacy name of the protocol to use on the wire. Should be different for each chain.
pub protocol_id: ProtocolId,

/// Fork ID to distinguish protocols of different hard forks. Part of the standard protocol
/// name on the wire.
pub fork_id: Option<String>,

/// Import queue to use.
///
/// The import queue is the component that verifies that blocks received from other nodes are
Expand Down
1 change: 1 addition & 0 deletions client/network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ pub mod bitswap;
pub mod config;
pub mod error;
pub mod network_state;
pub mod protocol_name;
pub mod transactions;

#[doc(inline)]
Expand Down
97 changes: 97 additions & 0 deletions client/network/src/protocol_name.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// This file is part of Substrate.

// Copyright (C) 2017-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/>.

//! On-the-wire protocol name generation helpers.

use crate::config::ProtocolId;

/// Standard protocol name on the wire based on `genesis_hash`, `fork_id`, and protocol-specific
/// `short_name`.
///
/// `short_name` must include the leading slash, e.g.: "/transactions/1".
pub fn standard_protocol_name<Hash: AsRef<[u8]>>(
genesis_hash: Hash,
fork_id: &Option<String>,
short_name: &str,
) -> std::borrow::Cow<'static, str> {
let chain_prefix = match fork_id {
Some(fork_id) => format!("/{}/{}", hex::encode(genesis_hash), fork_id),
None => format!("/{}", hex::encode(genesis_hash)),
};
format!("{}{}", chain_prefix, short_name).into()
}

/// Legacy (fallback) protocol name on the wire based on [`ProtocolId`].
pub fn legacy_protocol_name(
protocol_id: &ProtocolId,
short_name: &str,
) -> std::borrow::Cow<'static, str> {
format!("/{}{}", protocol_id.as_ref(), short_name).into()
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn standard_protocol_name_test() {
const SHORT_NAME: &str = "/protocol/1";

// Create protocol name using random genesis hash and no fork id.
let genesis_hash = sp_core::H256::random();
let fork_id = None;
let expected = format!("/{}/protocol/1", hex::encode(genesis_hash));
let protocol_name = standard_protocol_name(genesis_hash, &fork_id, SHORT_NAME);
assert_eq!(protocol_name.to_string(), expected);

// Create protocol name with fork id.
let fork_id = Some("fork".to_string());
let expected = format!("/{}/fork/protocol/1", hex::encode(genesis_hash));
let protocol_name = standard_protocol_name(genesis_hash, &fork_id, SHORT_NAME);
assert_eq!(protocol_name.to_string(), expected);

// Create protocol name using hardcoded genesis hash. Verify exact representation.
let genesis_hash = [
53, 79, 112, 97, 119, 217, 39, 202, 147, 138, 225, 38, 88, 182, 215, 185, 110, 88, 8,
53, 125, 210, 158, 151, 50, 113, 102, 59, 245, 199, 221, 240,
];
let fork_id = None;
let expected =
"/354f706177d927ca938ae12658b6d7b96e5808357dd29e973271663bf5c7ddf0/protocol/1";
let protocol_name = standard_protocol_name(genesis_hash, &fork_id, SHORT_NAME);
assert_eq!(protocol_name.to_string(), expected.to_string());

// Create protocol name using hardcoded genesis hash and fork_id.
// Verify exact representation.
let fork_id = Some("fork".to_string());
let expected =
"/354f706177d927ca938ae12658b6d7b96e5808357dd29e973271663bf5c7ddf0/fork/protocol/1";
let protocol_name = standard_protocol_name(genesis_hash, &fork_id, SHORT_NAME);
assert_eq!(protocol_name.to_string(), expected.to_string());
}

#[test]
fn legacy_protocol_name_test() {
const SHORT_NAME: &str = "/protocol/1";

let protocol_id = ProtocolId::from("dot");
let expected = "/dot/protocol/1";
let legacy_name = legacy_protocol_name(&protocol_id, SHORT_NAME);
assert_eq!(legacy_name.to_string(), expected.to_string());
}
}
12 changes: 10 additions & 2 deletions client/network/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,16 @@ where
fs::create_dir_all(path)?;
}

let transactions_handler_proto =
transactions::TransactionsHandlerPrototype::new(params.protocol_id.clone());
let transactions_handler_proto = transactions::TransactionsHandlerPrototype::new(
params.protocol_id.clone(),
params
.chain
.block_hash(0u32.into())
.ok()
.flatten()
.expect("Genesis block exists; qed"),
params.fork_id.clone(),
);
params
.network_config
.extra_sets
Expand Down
3 changes: 3 additions & 0 deletions client/network/src/service/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ fn build_test_full_node(

let protocol_id = ProtocolId::from("/test-protocol-name");

let fork_id = Some(String::from("test-fork-id"));

let block_request_protocol_config = {
let (handler, protocol_config) = BlockRequestHandler::new(&protocol_id, client.clone(), 50);
async_std::task::spawn(handler.run().boxed());
Expand Down Expand Up @@ -122,6 +124,7 @@ fn build_test_full_node(
chain: client.clone(),
transaction_pool: Arc::new(crate::config::EmptyTransactionPool),
protocol_id,
fork_id,
import_queue,
create_chain_sync: Box::new(
move |sync_mode, chain, warp_sync_provider| match ChainSync::new(
Expand Down
21 changes: 18 additions & 3 deletions client/network/src/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::{
config::{self, TransactionImport, TransactionImportFuture, TransactionPool},
error,
protocol::message,
protocol_name::{legacy_protocol_name, standard_protocol_name},
service::NetworkService,
utils::{interval, LruHashSet},
Event, ExHashT, ObservedRole,
Expand Down Expand Up @@ -70,6 +71,9 @@ const MAX_TRANSACTIONS_SIZE: u64 = 16 * 1024 * 1024;
/// Maximum number of transaction validation request we keep at any moment.
const MAX_PENDING_TRANSACTIONS: usize = 8192;

/// Transactions protocol short name (everything after /{genesis_hash}/{fork_id}...).
const PROTOCOL_SHORT_NAME: &str = "/transactions/1";

mod rep {
use sc_peerset::ReputationChange as Rep;
/// Reputation change when a peer sends us any transaction.
Expand Down Expand Up @@ -127,19 +131,30 @@ impl<H: ExHashT> Future for PendingTransaction<H> {
/// Prototype for a [`TransactionsHandler`].
pub struct TransactionsHandlerPrototype {
protocol_name: Cow<'static, str>,
fallback_protocol_names: Vec<Cow<'static, str>>,
}

impl TransactionsHandlerPrototype {
/// Create a new instance.
pub fn new(protocol_id: ProtocolId) -> Self {
Self { protocol_name: format!("/{}/transactions/1", protocol_id.as_ref()).into() }
pub fn new<Hash: AsRef<[u8]>>(
protocol_id: ProtocolId,
genesis_hash: Hash,
fork_id: Option<String>,
) -> Self {
Self {
protocol_name: standard_protocol_name(genesis_hash, &fork_id, PROTOCOL_SHORT_NAME),
fallback_protocol_names: std::iter::once(
legacy_protocol_name(&protocol_id, PROTOCOL_SHORT_NAME).into(),
)
.collect(),
}
}

/// Returns the configuration of the set to put in the network configuration.
pub fn set_config(&self) -> config::NonDefaultSetConfig {
config::NonDefaultSetConfig {
notifications_protocol: self.protocol_name.clone(),
fallback_names: Vec::new(),
fallback_names: self.fallback_protocol_names.clone(),
max_notification_size: MAX_TRANSACTIONS_SIZE,
set_config: config::SetConfig {
in_peers: 0,
Expand Down
3 changes: 3 additions & 0 deletions client/network/test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,8 @@ where

let protocol_id = ProtocolId::from("test-protocol-name");

let fork_id = Some(String::from("test-fork-id"));

let block_request_protocol_config = {
let (handler, protocol_config) =
BlockRequestHandler::new(&protocol_id, client.clone(), 50);
Expand Down Expand Up @@ -849,6 +851,7 @@ where
chain: client.clone(),
transaction_pool: Arc::new(EmptyTransactionPool),
protocol_id,
fork_id,
import_queue,
create_chain_sync: Box::new(move |sync_mode, chain, warp_sync_provider| {
match ChainSync::new(
Expand Down
1 change: 1 addition & 0 deletions client/service/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ where
chain: client.clone(),
transaction_pool: transaction_pool_adapter as _,
protocol_id,
fork_id: config.chain_spec.fork_id().map(ToOwned::to_owned),
import_queue: Box::new(import_queue),
create_chain_sync: Box::new(
move |sync_mode, chain, warp_sync_provider| match ChainSync::new(
Expand Down