diff --git a/crates/hotshot/src/traits/networking/libp2p_network.rs b/crates/hotshot/src/traits/networking/libp2p_network.rs index a20ef97901..c948202c47 100644 --- a/crates/hotshot/src/traits/networking/libp2p_network.rs +++ b/crates/hotshot/src/traits/networking/libp2p_network.rs @@ -4,6 +4,7 @@ #[cfg(feature = "hotshot-testing")] use std::str::FromStr; use std::{ + cmp::min, collections::{BTreeSet, HashSet}, fmt::Debug, net::SocketAddr, @@ -15,7 +16,7 @@ use std::{ time::Duration, }; -use anyhow::anyhow; +use anyhow::{anyhow, Context}; use async_compatibility_layer::{ art::{async_sleep, async_spawn}, channel::{ @@ -60,7 +61,7 @@ use libp2p_networking::{ spawn_network_node, MeshParams, NetworkEvent::{self, DirectRequest, DirectResponse, GossipMsg}, NetworkNodeConfig, NetworkNodeConfigBuilder, NetworkNodeHandle, NetworkNodeHandleError, - NetworkNodeReceiver, NetworkNodeType, + NetworkNodeReceiver, NetworkNodeType, DEFAULT_REPLICATION_FACTOR, }, reexport::{Multiaddr, ResponseChannel}, }; @@ -397,11 +398,23 @@ impl Libp2pNetwork { .parse()?; // Build our libp2p configuration from our global, network configuration - let mut config_builder = NetworkNodeConfigBuilder::default(); + let mut config_builder: NetworkNodeConfigBuilder = NetworkNodeConfigBuilder::default(); + + // The replication factor is the minimum of [the default and 2/3 the number of nodes] + let Some(default_replication_factor) = DEFAULT_REPLICATION_FACTOR else { + return Err(anyhow!("Default replication factor not supplied")); + }; + + let replication_factor = NonZeroUsize::new(min( + default_replication_factor.get(), + config.config.num_nodes_with_stake.get() * 2 / 3, + )) + .with_context(|| "Failed to calculate replication factor")?; config_builder .server_mode(libp2p_config.server_mode) .identity(keypair) + .replication_factor(replication_factor) .bound_addr(Some(bind_address.clone())) .mesh_params(Some(MeshParams { mesh_n_high: libp2p_config.mesh_n_high, diff --git a/crates/libp2p-networking/src/network/mod.rs b/crates/libp2p-networking/src/network/mod.rs index 1fa5391f20..94796117a9 100644 --- a/crates/libp2p-networking/src/network/mod.rs +++ b/crates/libp2p-networking/src/network/mod.rs @@ -39,7 +39,7 @@ pub use self::{ node::{ network_node_handle_error, spawn_network_node, MeshParams, NetworkNode, NetworkNodeConfig, NetworkNodeConfigBuilder, NetworkNodeConfigBuilderError, NetworkNodeHandle, - NetworkNodeHandleError, NetworkNodeReceiver, + NetworkNodeHandleError, NetworkNodeReceiver, DEFAULT_REPLICATION_FACTOR, }, }; #[cfg(not(any(async_executor_impl = "async-std", async_executor_impl = "tokio")))] diff --git a/crates/libp2p-networking/src/network/node.rs b/crates/libp2p-networking/src/network/node.rs index c91589f32a..8a782a0e63 100644 --- a/crates/libp2p-networking/src/network/node.rs +++ b/crates/libp2p-networking/src/network/node.rs @@ -45,6 +45,7 @@ use tracing::{debug, error, info, info_span, instrument, warn, Instrument}; pub use self::{ config::{ MeshParams, NetworkNodeConfig, NetworkNodeConfigBuilder, NetworkNodeConfigBuilderError, + DEFAULT_REPLICATION_FACTOR, }, handle::{ network_node_handle_error, spawn_network_node, NetworkNodeHandle, NetworkNodeHandleError, @@ -351,11 +352,17 @@ impl NetworkNode { /// Once replicated upon all nodes, the caller is notified over /// `chan`. If there is an error, a [`super::error::DHTError`] is /// sent instead. + /// + /// # Panics + /// If the default replication factor is `None` pub fn put_record(&mut self, mut query: KadPutQuery) { let record = Record::new(query.key.clone(), query.value.clone()); match self.swarm.behaviour_mut().dht.put_record( record, - libp2p::kad::Quorum::N(self.dht_handler.replication_factor()), + libp2p::kad::Quorum::N( + NonZeroUsize::try_from(self.dht_handler.replication_factor().get() / 2) + .expect("replication factor should be bigger than 0"), + ), ) { Err(e) => { // failed try again later