diff --git a/applications/tari_indexer/src/bootstrap.rs b/applications/tari_indexer/src/bootstrap.rs index 9f6b66a15..0964ff27b 100644 --- a/applications/tari_indexer/src/bootstrap.rs +++ b/applications/tari_indexer/src/bootstrap.rs @@ -94,7 +94,7 @@ pub async fn spawn_services( tari_networking::Config { listener_port: config.indexer.p2p.listener_port, swarm: SwarmConfig { - protocol_version: "/tari/devnet/0.0.1".try_into().unwrap(), + protocol_version: format!("/tari/{}/0.0.1", config.network).parse().unwrap(), user_agent: "/tari/indexer/0.0.1".to_string(), enable_mdns: config.indexer.p2p.enable_mdns, ..Default::default() diff --git a/applications/tari_validator_node/src/bootstrap.rs b/applications/tari_validator_node/src/bootstrap.rs index d7e91d17d..6553432e7 100644 --- a/applications/tari_validator_node/src/bootstrap.rs +++ b/applications/tari_validator_node/src/bootstrap.rs @@ -158,7 +158,7 @@ pub async fn spawn_services( tari_networking::Config { listener_port: config.validator_node.p2p.listener_port, swarm: SwarmConfig { - protocol_version: "/tari/devnet/0.0.1".try_into().unwrap(), + protocol_version: format!("/tari/{}/0.0.1", config.network).parse().unwrap(), user_agent: "/tari/validator/0.0.1".to_string(), enable_mdns: config.validator_node.p2p.enable_mdns, ..Default::default() diff --git a/networking/core/src/lib.rs b/networking/core/src/lib.rs index dae518792..97d44c04b 100644 --- a/networking/core/src/lib.rs +++ b/networking/core/src/lib.rs @@ -30,7 +30,7 @@ pub use config::*; pub use connection::*; pub use handle::*; pub use spawn::*; -pub use tari_swarm::{is_supported_multiaddr, Config as SwarmConfig, TariNetwork}; +pub use tari_swarm::{is_supported_multiaddr, Config as SwarmConfig}; #[async_trait] pub trait NetworkingService { diff --git a/networking/core/src/worker.rs b/networking/core/src/worker.rs index dd8eb63c2..e42e0847f 100644 --- a/networking/core/src/worker.rs +++ b/networking/core/src/worker.rs @@ -41,7 +41,6 @@ use tari_swarm::{ peersync, substream, substream::{NegotiatedSubstream, ProtocolNotification, StreamId}, - ProtocolVersion, TariNodeBehaviourEvent, TariSwarm, }; @@ -739,14 +738,10 @@ where } fn on_peer_identified(&mut self, peer_id: PeerId, info: identify::Info) -> Result<(), NetworkingError> { - if !self - .config - .swarm - .protocol_version - .is_compatible(&ProtocolVersion::try_from(info.protocol_version.as_str())?) - { + if !self.config.swarm.protocol_version.is_compatible(&info.protocol_version) { info!(target: LOG_TARGET, "🚨 Peer {} is using an incompatible protocol version: {}. Our version {}", peer_id, info.protocol_version, self.config.swarm.protocol_version); - // Errors just indicate that there was no connection to the peer. + // Error can be ignored as the docs indicate that an error only occurs if there was no connection to the + // peer. let _ignore = self.swarm.disconnect_peer_id(peer_id); return Ok(()); } diff --git a/networking/swarm/src/config.rs b/networking/swarm/src/config.rs index 8620397f0..5ee9f8085 100644 --- a/networking/swarm/src/config.rs +++ b/networking/swarm/src/config.rs @@ -9,7 +9,7 @@ use crate::protocol_version::ProtocolVersion; #[derive(Debug, Clone)] pub struct Config { - pub protocol_version: ProtocolVersion<'static>, + pub protocol_version: ProtocolVersion, pub user_agent: String, pub messaging_protocol: String, pub ping: ping::Config, @@ -22,7 +22,7 @@ pub struct Config { impl Default for Config { fn default() -> Self { Self { - protocol_version: "/tari/devnet/0.0.1".try_into().unwrap(), + protocol_version: "/tari/localnet/0.0.1".parse().unwrap(), user_agent: "/tari/unknown/0.0.1".to_string(), messaging_protocol: "/tari/messaging/0.0.1".to_string(), ping: ping::Config::default(), diff --git a/networking/swarm/src/error.rs b/networking/swarm/src/error.rs index 21427c2f6..443e19d06 100644 --- a/networking/swarm/src/error.rs +++ b/networking/swarm/src/error.rs @@ -11,6 +11,8 @@ pub enum TariSwarmError { InvalidProtocol(#[from] InvalidProtocol), #[error("Behaviour error: {0}")] BehaviourError(String), - #[error("Failed to parse protocol version field '{field}'")] - ProtocolVersionParseFailed { field: &'static str }, + #[error("'{given}' is not a valid protocol version string")] + ProtocolVersionParseFailed { given: String }, + #[error("Invalid version string: {given}")] + InvalidVersionString { given: String }, } diff --git a/networking/swarm/src/lib.rs b/networking/swarm/src/lib.rs index 93e146698..d80d96c55 100644 --- a/networking/swarm/src/lib.rs +++ b/networking/swarm/src/lib.rs @@ -4,13 +4,11 @@ mod behaviour; mod config; mod error; -mod network; mod protocol_version; pub use behaviour::*; pub use config::*; pub use error::*; -pub use network::*; pub use protocol_version::*; pub type TariSwarm = libp2p::Swarm>; diff --git a/networking/swarm/src/network.rs b/networking/swarm/src/network.rs deleted file mode 100644 index ce1e8e6cd..000000000 --- a/networking/swarm/src/network.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2023 The Tari Project -// SPDX-License-Identifier: BSD-3-Clause - -use std::{fmt::Display, str::FromStr}; - -use crate::TariSwarmError; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum TariNetwork { - DevNet, -} - -impl TariNetwork { - pub const fn as_str(&self) -> &'static str { - match self { - TariNetwork::DevNet => "devnet", - } - } -} - -impl Display for TariNetwork { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(self.as_str()) - } -} - -impl FromStr for TariNetwork { - type Err = TariSwarmError; - - fn from_str(s: &str) -> Result { - match s { - "devnet" => Ok(TariNetwork::DevNet), - _ => Err(TariSwarmError::ProtocolVersionParseFailed { field: "network" }), - } - } -} diff --git a/networking/swarm/src/protocol_version.rs b/networking/swarm/src/protocol_version.rs index 7a7d5588b..f101a1857 100644 --- a/networking/swarm/src/protocol_version.rs +++ b/networking/swarm/src/protocol_version.rs @@ -3,17 +3,17 @@ use std::{fmt, fmt::Display, str::FromStr}; -use crate::{TariNetwork, TariSwarmError}; +use crate::TariSwarmError; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct ProtocolVersion<'a> { - domain: &'a str, - network: TariNetwork, +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct ProtocolVersion { + domain: String, + network: String, version: Version, } -impl<'a> ProtocolVersion<'a> { - pub const fn new(domain: &'a str, network: TariNetwork, version: Version) -> Self { +impl ProtocolVersion { + pub const fn new(domain: String, network: String, version: Version) -> Self { Self { domain, network, @@ -21,66 +21,75 @@ impl<'a> ProtocolVersion<'a> { } } - pub const fn domain(&self) -> &'a str { - self.domain + pub fn domain(&self) -> &str { + &self.domain } - pub const fn network(&self) -> TariNetwork { - self.network + pub fn network(&self) -> &str { + &self.network } pub const fn version(&self) -> Version { self.version } - pub fn is_compatible(&self, other: &ProtocolVersion) -> bool { - self.domain == other.domain && self.network == other.network && self.version.semantic_version_eq(&other.version) + pub fn is_compatible(&self, protocol_str: &str) -> bool { + let Some((domain, network, version)) = parse_protocol_str(protocol_str) else { + return false; + }; + self.domain == domain && self.network == network && self.version.semantic_version_eq(&version) } } -impl PartialEq for ProtocolVersion<'_> { +impl PartialEq for ProtocolVersion { fn eq(&self, other: &String) -> bool { - let mut parts = other.split('/'); - let Some(domain) = parts.next() else { - return false; - }; - - let Some(network) = parts.next() else { - return false; - }; - - let Some(version) = parts.next().and_then(|s| s.parse().ok()) else { + let Some((domain, network, version)) = parse_protocol_str(other) else { return false; }; + self.domain == domain && self.network == network && self.version == version + } +} - self.domain == domain && self.network.as_str() == network && self.version == version +impl Display for ProtocolVersion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "/{}/{}/{}", self.domain, self.network, self.version) } } -impl<'a> TryFrom<&'a str> for ProtocolVersion<'a> { - type Error = TariSwarmError; +impl FromStr for ProtocolVersion { + type Err = TariSwarmError; - fn try_from(value: &'a str) -> Result { + fn from_str(value: &str) -> Result { let mut parts = value.split('/'); // Must have a leading '/' let leading = parts.next(); if leading.filter(|l| l.is_empty()).is_none() { - return Err(TariSwarmError::ProtocolVersionParseFailed { field: "leading '/'" }); + return Err(TariSwarmError::ProtocolVersionParseFailed { + given: value.to_string(), + }); } - let mut next = move |field| parts.next().ok_or(TariSwarmError::ProtocolVersionParseFailed { field }); - Ok(Self::new( - next("domain")?, - next("network")?.parse()?, - next("version")?.parse()?, - )) + let Some((domain, network, version)) = parse_protocol_str(value) else { + return Err(TariSwarmError::ProtocolVersionParseFailed { + given: value.to_string(), + }); + }; + Ok(Self::new(domain.to_string(), network.to_string(), version)) } } -impl Display for ProtocolVersion<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "/{}/{}/{}", self.domain, self.network, self.version) +fn parse_protocol_str(protocol_str: &str) -> Option<(&str, &str, Version)> { + let mut parts = protocol_str.split('/'); + // Must have a leading '/' + let leading = parts.next()?; + if !leading.is_empty() { + return None; } + + let domain = parts.next()?; + let network = parts.next()?; + let version = parts.next().and_then(|s| s.parse().ok())?; + Some((domain, network, version)) } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -129,17 +138,17 @@ impl FromStr for Version { fn from_str(s: &str) -> Result { let mut parts = s.split('.'); - let mut next = move |field| { + let mut next = move || { parts .next() - .ok_or(TariSwarmError::ProtocolVersionParseFailed { field })? + .ok_or(TariSwarmError::InvalidVersionString { given: s.to_string() })? .parse() - .map_err(|_| TariSwarmError::ProtocolVersionParseFailed { field }) + .map_err(|_| TariSwarmError::InvalidVersionString { given: s.to_string() }) }; Ok(Self { - major: next("version.major")?, - minor: next("version.minor")?, - patch: next("version.patch")?, + major: next()?, + minor: next()?, + patch: next()?, }) } } @@ -156,13 +165,13 @@ mod tests { #[test] fn it_parses_correctly() { - let version = ProtocolVersion::try_from("/tari/devnet/0.0.1").unwrap(); + let version = ProtocolVersion::from_str("/tari/igor/1.2.3").unwrap(); assert_eq!(version.domain(), "tari"); - assert_eq!(version.network(), TariNetwork::DevNet); + assert_eq!(version.network(), "igor"); assert_eq!(version.version(), Version { - major: 0, - minor: 0, - patch: 1 + major: 1, + minor: 2, + patch: 3 }); } }