mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-20 13:26:34 +00:00
protocols/gossipsub/: Allow custom protocol id (#2718)
Allow for custom protocol ID via `GossipsubConfigBuilder::protocol_id()`.
This commit is contained in:
@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
- Update to `libp2p-swarm` `v0.37.0`.
|
- Update to `libp2p-swarm` `v0.37.0`.
|
||||||
|
|
||||||
|
- Allow for custom protocol ID via `GossipsubConfigBuilder::protocol_id()`. See [PR 2718].
|
||||||
|
|
||||||
|
[PR 2718]: https://github.com/libp2p/rust-libp2p/pull/2718/
|
||||||
|
|
||||||
# 0.38.1
|
# 0.38.1
|
||||||
|
|
||||||
- Fix duplicate connection id. See [PR 2702].
|
- Fix duplicate connection id. See [PR 2702].
|
||||||
|
@ -54,7 +54,7 @@ use crate::handler::{GossipsubHandler, GossipsubHandlerIn, HandlerEvent};
|
|||||||
use crate::mcache::MessageCache;
|
use crate::mcache::MessageCache;
|
||||||
use crate::metrics::{Churn, Config as MetricsConfig, Inclusion, Metrics, Penalty};
|
use crate::metrics::{Churn, Config as MetricsConfig, Inclusion, Metrics, Penalty};
|
||||||
use crate::peer_score::{PeerScore, PeerScoreParams, PeerScoreThresholds, RejectReason};
|
use crate::peer_score::{PeerScore, PeerScoreParams, PeerScoreThresholds, RejectReason};
|
||||||
use crate::protocol::SIGNING_PREFIX;
|
use crate::protocol::{ProtocolConfig, SIGNING_PREFIX};
|
||||||
use crate::subscription_filter::{AllowAllSubscriptionFilter, TopicSubscriptionFilter};
|
use crate::subscription_filter::{AllowAllSubscriptionFilter, TopicSubscriptionFilter};
|
||||||
use crate::time_cache::{DuplicateCache, TimeCache};
|
use crate::time_cache::{DuplicateCache, TimeCache};
|
||||||
use crate::topic::{Hasher, Topic, TopicHash};
|
use crate::topic::{Hasher, Topic, TopicHash};
|
||||||
@ -3053,13 +3053,15 @@ where
|
|||||||
type OutEvent = GossipsubEvent;
|
type OutEvent = GossipsubEvent;
|
||||||
|
|
||||||
fn new_handler(&mut self) -> Self::ConnectionHandler {
|
fn new_handler(&mut self) -> Self::ConnectionHandler {
|
||||||
GossipsubHandler::new(
|
let protocol_config = ProtocolConfig::new(
|
||||||
self.config.protocol_id_prefix().clone(),
|
self.config.protocol_id().clone(),
|
||||||
|
self.config.custom_id_version().clone(),
|
||||||
self.config.max_transmit_size(),
|
self.config.max_transmit_size(),
|
||||||
self.config.validation_mode().clone(),
|
self.config.validation_mode().clone(),
|
||||||
self.config.idle_timeout(),
|
|
||||||
self.config.support_floodsub(),
|
self.config.support_floodsub(),
|
||||||
)
|
);
|
||||||
|
|
||||||
|
GossipsubHandler::new(protocol_config, self.config.idle_timeout())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inject_connection_established(
|
fn inject_connection_established(
|
||||||
|
@ -49,10 +49,18 @@ pub enum ValidationMode {
|
|||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Selector for custom Protocol Id
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum GossipsubVersion {
|
||||||
|
V1_0,
|
||||||
|
V1_1,
|
||||||
|
}
|
||||||
|
|
||||||
/// Configuration parameters that define the performance of the gossipsub network.
|
/// Configuration parameters that define the performance of the gossipsub network.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct GossipsubConfig {
|
pub struct GossipsubConfig {
|
||||||
protocol_id_prefix: Cow<'static, str>,
|
protocol_id: Cow<'static, str>,
|
||||||
|
custom_id_version: Option<GossipsubVersion>,
|
||||||
history_length: usize,
|
history_length: usize,
|
||||||
history_gossip: usize,
|
history_gossip: usize,
|
||||||
mesh_n: usize,
|
mesh_n: usize,
|
||||||
@ -96,13 +104,20 @@ pub struct GossipsubConfig {
|
|||||||
impl GossipsubConfig {
|
impl GossipsubConfig {
|
||||||
// All the getters
|
// All the getters
|
||||||
|
|
||||||
/// The protocol id prefix to negotiate this protocol. The protocol id is of the form
|
/// The protocol id to negotiate this protocol. By default, the resulting protocol id has the form
|
||||||
/// `/<prefix>/<supported-versions>`. As gossipsub supports version 1.0 and 1.1, there are two
|
/// `/<prefix>/<supported-versions>`, but can optionally be changed to a literal form by providing some GossipsubVersion as custom_id_version.
|
||||||
/// protocol id's supported.
|
/// As gossipsub supports version 1.0 and 1.1, there are two suffixes supported for the resulting protocol id.
|
||||||
|
///
|
||||||
|
/// Calling `GossipsubConfigBuilder::protocol_id_prefix` will set a new prefix and retain the prefix logic.
|
||||||
|
/// Calling `GossipsubConfigBuilder::protocol_id` will set a custom `protocol_id` and disable the prefix logic.
|
||||||
///
|
///
|
||||||
/// The default prefix is `meshsub`, giving the supported protocol ids: `/meshsub/1.1.0` and `/meshsub/1.0.0`, negotiated in that order.
|
/// The default prefix is `meshsub`, giving the supported protocol ids: `/meshsub/1.1.0` and `/meshsub/1.0.0`, negotiated in that order.
|
||||||
pub fn protocol_id_prefix(&self) -> &Cow<'static, str> {
|
pub fn protocol_id(&self) -> &Cow<'static, str> {
|
||||||
&self.protocol_id_prefix
|
&self.protocol_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn custom_id_version(&self) -> &Option<GossipsubVersion> {
|
||||||
|
&self.custom_id_version
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overlay network parameters.
|
// Overlay network parameters.
|
||||||
@ -394,7 +409,8 @@ impl Default for GossipsubConfigBuilder {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
GossipsubConfigBuilder {
|
GossipsubConfigBuilder {
|
||||||
config: GossipsubConfig {
|
config: GossipsubConfig {
|
||||||
protocol_id_prefix: Cow::Borrowed("meshsub"),
|
protocol_id: Cow::Borrowed("meshsub"),
|
||||||
|
custom_id_version: None,
|
||||||
history_length: 5,
|
history_length: 5,
|
||||||
history_gossip: 3,
|
history_gossip: 3,
|
||||||
mesh_n: 6,
|
mesh_n: 6,
|
||||||
@ -457,9 +473,24 @@ impl From<GossipsubConfig> for GossipsubConfigBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GossipsubConfigBuilder {
|
impl GossipsubConfigBuilder {
|
||||||
/// The protocol id to negotiate this protocol (default is `/meshsub/1.0.0`).
|
/// The protocol id prefix to negotiate this protocol (default is `/meshsub/1.0.0`).
|
||||||
pub fn protocol_id_prefix(&mut self, protocol_id: impl Into<Cow<'static, str>>) -> &mut Self {
|
pub fn protocol_id_prefix(
|
||||||
self.config.protocol_id_prefix = protocol_id.into();
|
&mut self,
|
||||||
|
protocol_id_prefix: impl Into<Cow<'static, str>>,
|
||||||
|
) -> &mut Self {
|
||||||
|
self.config.custom_id_version = None;
|
||||||
|
self.config.protocol_id = protocol_id_prefix.into();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The full protocol id to negotiate this protocol (does not append `/1.0.0` or `/1.1.0`).
|
||||||
|
pub fn protocol_id(
|
||||||
|
&mut self,
|
||||||
|
protocol_id: impl Into<Cow<'static, str>>,
|
||||||
|
custom_id_version: GossipsubVersion,
|
||||||
|
) -> &mut Self {
|
||||||
|
self.config.custom_id_version = Some(custom_id_version);
|
||||||
|
self.config.protocol_id = protocol_id.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -810,7 +841,8 @@ impl GossipsubConfigBuilder {
|
|||||||
impl std::fmt::Debug for GossipsubConfig {
|
impl std::fmt::Debug for GossipsubConfig {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let mut builder = f.debug_struct("GossipsubConfig");
|
let mut builder = f.debug_struct("GossipsubConfig");
|
||||||
let _ = builder.field("protocol_id_prefix", &self.protocol_id_prefix);
|
let _ = builder.field("protocol_id", &self.protocol_id);
|
||||||
|
let _ = builder.field("custom_id_version", &self.custom_id_version);
|
||||||
let _ = builder.field("history_length", &self.history_length);
|
let _ = builder.field("history_length", &self.history_length);
|
||||||
let _ = builder.field("history_gossip", &self.history_gossip);
|
let _ = builder.field("history_gossip", &self.history_gossip);
|
||||||
let _ = builder.field("mesh_n", &self.mesh_n);
|
let _ = builder.field("mesh_n", &self.mesh_n);
|
||||||
@ -854,7 +886,11 @@ impl std::fmt::Debug for GossipsubConfig {
|
|||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::topic::IdentityHash;
|
use crate::topic::IdentityHash;
|
||||||
|
use crate::types::PeerKind;
|
||||||
use crate::Topic;
|
use crate::Topic;
|
||||||
|
use crate::{Gossipsub, MessageAuthenticity};
|
||||||
|
use libp2p_core::UpgradeInfo;
|
||||||
|
use libp2p_swarm::{ConnectionHandler, NetworkBehaviour};
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
@ -943,4 +979,57 @@ mod test {
|
|||||||
let result = builder.message_id(&get_gossipsub_message());
|
let result = builder.message_id(&get_gossipsub_message());
|
||||||
assert_eq!(result, get_expected_message_id());
|
assert_eq!(result, get_expected_message_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_config_with_protocol_id_prefix() {
|
||||||
|
let builder: GossipsubConfig = GossipsubConfigBuilder::default()
|
||||||
|
.protocol_id_prefix("purple")
|
||||||
|
.validation_mode(ValidationMode::Anonymous)
|
||||||
|
.message_id_fn(message_id_plain_function)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(builder.protocol_id(), "purple");
|
||||||
|
assert_eq!(builder.custom_id_version(), &None);
|
||||||
|
|
||||||
|
let mut gossipsub: Gossipsub =
|
||||||
|
Gossipsub::new(MessageAuthenticity::Anonymous, builder).expect("Correct configuration");
|
||||||
|
|
||||||
|
let handler = gossipsub.new_handler();
|
||||||
|
let (protocol_config, _) = handler.listen_protocol().into_upgrade();
|
||||||
|
let protocol_ids = protocol_config.protocol_info();
|
||||||
|
|
||||||
|
assert_eq!(protocol_ids.len(), 2);
|
||||||
|
|
||||||
|
assert_eq!(protocol_ids[0].protocol_id, b"/purple/1.1.0".to_vec());
|
||||||
|
assert_eq!(protocol_ids[0].kind, PeerKind::Gossipsubv1_1);
|
||||||
|
|
||||||
|
assert_eq!(protocol_ids[1].protocol_id, b"/purple/1.0.0".to_vec());
|
||||||
|
assert_eq!(protocol_ids[1].kind, PeerKind::Gossipsub);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn create_config_with_custom_protocol_id() {
|
||||||
|
let builder: GossipsubConfig = GossipsubConfigBuilder::default()
|
||||||
|
.protocol_id("purple", GossipsubVersion::V1_0)
|
||||||
|
.validation_mode(ValidationMode::Anonymous)
|
||||||
|
.message_id_fn(message_id_plain_function)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(builder.protocol_id(), "purple");
|
||||||
|
assert_eq!(builder.custom_id_version(), &Some(GossipsubVersion::V1_0));
|
||||||
|
|
||||||
|
let mut gossipsub: Gossipsub =
|
||||||
|
Gossipsub::new(MessageAuthenticity::Anonymous, builder).expect("Correct configuration");
|
||||||
|
|
||||||
|
let handler = gossipsub.new_handler();
|
||||||
|
let (protocol_config, _) = handler.listen_protocol().into_upgrade();
|
||||||
|
let protocol_ids = protocol_config.protocol_info();
|
||||||
|
|
||||||
|
assert_eq!(protocol_ids.len(), 1);
|
||||||
|
|
||||||
|
assert_eq!(protocol_ids[0].protocol_id, b"purple".to_vec());
|
||||||
|
assert_eq!(protocol_ids[0].kind, PeerKind::Gossipsub);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::config::ValidationMode;
|
|
||||||
use crate::error::{GossipsubHandlerError, ValidationError};
|
use crate::error::{GossipsubHandlerError, ValidationError};
|
||||||
use crate::protocol::{GossipsubCodec, ProtocolConfig};
|
use crate::protocol::{GossipsubCodec, ProtocolConfig};
|
||||||
use crate::types::{GossipsubRpc, PeerKind, RawGossipsubMessage};
|
use crate::types::{GossipsubRpc, PeerKind, RawGossipsubMessage};
|
||||||
@ -163,23 +162,9 @@ enum OutboundSubstreamState {
|
|||||||
|
|
||||||
impl GossipsubHandler {
|
impl GossipsubHandler {
|
||||||
/// Builds a new [`GossipsubHandler`].
|
/// Builds a new [`GossipsubHandler`].
|
||||||
pub fn new(
|
pub fn new(protocol_config: ProtocolConfig, idle_timeout: Duration) -> Self {
|
||||||
protocol_id_prefix: std::borrow::Cow<'static, str>,
|
|
||||||
max_transmit_size: usize,
|
|
||||||
validation_mode: ValidationMode,
|
|
||||||
idle_timeout: Duration,
|
|
||||||
support_floodsub: bool,
|
|
||||||
) -> Self {
|
|
||||||
GossipsubHandler {
|
GossipsubHandler {
|
||||||
listen_protocol: SubstreamProtocol::new(
|
listen_protocol: SubstreamProtocol::new(protocol_config, ()),
|
||||||
ProtocolConfig::new(
|
|
||||||
protocol_id_prefix,
|
|
||||||
max_transmit_size,
|
|
||||||
validation_mode,
|
|
||||||
support_floodsub,
|
|
||||||
),
|
|
||||||
(),
|
|
||||||
),
|
|
||||||
inbound_substream: None,
|
inbound_substream: None,
|
||||||
outbound_substream: None,
|
outbound_substream: None,
|
||||||
outbound_substream_establishing: false,
|
outbound_substream_establishing: false,
|
||||||
|
@ -160,7 +160,7 @@ mod rpc_proto;
|
|||||||
pub use self::behaviour::{Gossipsub, GossipsubEvent, MessageAuthenticity};
|
pub use self::behaviour::{Gossipsub, GossipsubEvent, MessageAuthenticity};
|
||||||
pub use self::transform::{DataTransform, IdentityTransform};
|
pub use self::transform::{DataTransform, IdentityTransform};
|
||||||
|
|
||||||
pub use self::config::{GossipsubConfig, GossipsubConfigBuilder, ValidationMode};
|
pub use self::config::{GossipsubConfig, GossipsubConfigBuilder, GossipsubVersion, ValidationMode};
|
||||||
pub use self::peer_score::{
|
pub use self::peer_score::{
|
||||||
score_parameter_decay, score_parameter_decay_with_base, PeerScoreParams, PeerScoreThresholds,
|
score_parameter_decay, score_parameter_decay_with_base, PeerScoreParams, PeerScoreThresholds,
|
||||||
TopicScoreParams,
|
TopicScoreParams,
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
// DEALINGS IN THE SOFTWARE.
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
use crate::config::ValidationMode;
|
use crate::config::{GossipsubVersion, ValidationMode};
|
||||||
use crate::error::{GossipsubHandlerError, ValidationError};
|
use crate::error::{GossipsubHandlerError, ValidationError};
|
||||||
use crate::handler::HandlerEvent;
|
use crate::handler::HandlerEvent;
|
||||||
use crate::rpc_proto;
|
use crate::rpc_proto;
|
||||||
@ -59,22 +59,32 @@ impl ProtocolConfig {
|
|||||||
///
|
///
|
||||||
/// Sets the maximum gossip transmission size.
|
/// Sets the maximum gossip transmission size.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
id_prefix: Cow<'static, str>,
|
id: Cow<'static, str>,
|
||||||
|
custom_id_peer_kind: Option<GossipsubVersion>,
|
||||||
max_transmit_size: usize,
|
max_transmit_size: usize,
|
||||||
validation_mode: ValidationMode,
|
validation_mode: ValidationMode,
|
||||||
support_floodsub: bool,
|
support_floodsub: bool,
|
||||||
) -> ProtocolConfig {
|
) -> ProtocolConfig {
|
||||||
// support version 1.1.0 and 1.0.0 with user-customized prefix
|
let protocol_ids = match custom_id_peer_kind {
|
||||||
|
Some(v) => match v {
|
||||||
|
GossipsubVersion::V1_0 => vec![ProtocolId::new(id, PeerKind::Gossipsub, false)],
|
||||||
|
GossipsubVersion::V1_1 => vec![ProtocolId::new(id, PeerKind::Gossipsubv1_1, false)],
|
||||||
|
},
|
||||||
|
None => {
|
||||||
let mut protocol_ids = vec![
|
let mut protocol_ids = vec![
|
||||||
ProtocolId::new(id_prefix.clone(), PeerKind::Gossipsubv1_1),
|
ProtocolId::new(id.clone(), PeerKind::Gossipsubv1_1, true),
|
||||||
ProtocolId::new(id_prefix, PeerKind::Gossipsub),
|
ProtocolId::new(id, PeerKind::Gossipsub, true),
|
||||||
];
|
];
|
||||||
|
|
||||||
// add floodsub support if enabled.
|
// add floodsub support if enabled.
|
||||||
if support_floodsub {
|
if support_floodsub {
|
||||||
protocol_ids.push(ProtocolId::new(Cow::from(""), PeerKind::Floodsub));
|
protocol_ids.push(ProtocolId::new(Cow::from(""), PeerKind::Floodsub, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protocol_ids
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ProtocolConfig {
|
ProtocolConfig {
|
||||||
protocol_ids,
|
protocol_ids,
|
||||||
max_transmit_size,
|
max_transmit_size,
|
||||||
@ -94,10 +104,16 @@ pub struct ProtocolId {
|
|||||||
|
|
||||||
/// An RPC protocol ID.
|
/// An RPC protocol ID.
|
||||||
impl ProtocolId {
|
impl ProtocolId {
|
||||||
pub fn new(prefix: Cow<'static, str>, kind: PeerKind) -> Self {
|
pub fn new(id: Cow<'static, str>, kind: PeerKind, prefix: bool) -> Self {
|
||||||
let protocol_id = match kind {
|
let protocol_id = match kind {
|
||||||
PeerKind::Gossipsubv1_1 => format!("/{}/{}", prefix, "1.1.0"),
|
PeerKind::Gossipsubv1_1 => match prefix {
|
||||||
PeerKind::Gossipsub => format!("/{}/{}", prefix, "1.0.0"),
|
true => format!("/{}/{}", id, "1.1.0"),
|
||||||
|
false => format!("{}", id),
|
||||||
|
},
|
||||||
|
PeerKind::Gossipsub => match prefix {
|
||||||
|
true => format!("/{}/{}", id, "1.0.0"),
|
||||||
|
false => format!("{}", id),
|
||||||
|
},
|
||||||
PeerKind::Floodsub => format!("/{}/{}", "floodsub", "1.0.0"),
|
PeerKind::Floodsub => format!("/{}/{}", "floodsub", "1.0.0"),
|
||||||
// NOTE: This is used for informing the behaviour of unsupported peers. We do not
|
// NOTE: This is used for informing the behaviour of unsupported peers. We do not
|
||||||
// advertise this variant.
|
// advertise this variant.
|
||||||
|
Reference in New Issue
Block a user