pub struct DhtConfig {
pub k: usize,
pub alpha: usize,
pub provider_ttl: Duration,
pub republish_interval: Duration,
pub refresh_interval: Duration,
pub rpc_timeout: Duration,
pub provider_store_limits: ProviderStoreLimits,
pub discovery_cache_ttl: Duration,
pub discovery_cache_limits: ProviderStoreLimits,
}Expand description
Kademlia parameters for a DhtService.
The defaults follow the canonical Kademlia paper (k = 20, α = 3) and typical provider-record
lifetimes; every field is documented so a node operator can tune replication vs. traffic.
Fields§
§k: usizeReplication parameter k — the bucket size and the number of closest peers a lookup
converges on. A provider record is announced to (and a find_node returns) up to k peers.
Larger k = more redundancy against churn, more traffic. Canonical default: 20.
alpha: usizeLookup parallelism α — how many peers an iterative lookup queries concurrently per
round. Larger α = faster convergence, more in-flight traffic. Canonical default: 3.
provider_ttl: DurationProvider-record TTL — how long a PUT provider record is considered valid. A holder republishes before this elapses; a finder discards records older than this. Default: 2 hours.
This is also the clamp ceiling for inbound add_provider records (SPEC §6.2, §14): a
responder never stores a third-party expires_at further in the future than
now + provider_ttl, so a malicious record can never outlive local GC indefinitely.
republish_interval: DurationRepublish interval — how often the holder re-announces the content it still holds, so its
provider records never expire while it is online. MUST be shorter than Self::provider_ttl.
Default: 1 hour.
refresh_interval: DurationBucket-refresh interval — how often a bucket with no recent activity is refreshed by looking up a random key that falls in it, keeping the routing table populated. Default: 1 hour.
rpc_timeout: DurationPer-RPC timeout — how long a single request to one peer may take before that peer is treated as unresponsive and the lookup moves on. Default: 5 seconds.
provider_store_limits: ProviderStoreLimitsProvider-store admission-control caps — the per-content-key and global record limits
enforced on every inbound add_provider (SPEC §6.3, §14). Bounds worst-case memory growth
from a single peer (or a small set of colluding peers) flooding announces. Default:
ProviderStoreLimits::default.
discovery_cache_ttl: DurationDiscovery-cache TTL — how long a provider record LEARNED FROM THIS NODE’S OWN LOOKUP is kept so a later fetch of the same content can dial directly instead of walking the DHT again (SPEC §6.8). Default: 15 minutes.
Deliberately far shorter than Self::provider_ttl, for a reason specific to this cache:
nothing republishes into it. An authoritative record survives 2 hours because its holder
refreshes it on Self::republish_interval; a cached one has no such keeper, so its age is
pure guesswork about a holder this node has not spoken to since. 15 minutes spans a whole
multi-range download of one store and the re-reads that immediately follow it — where the
saving actually accrues — while keeping a holder that dropped the content (an LRU eviction
upstream takes minutes, not hours) from being dialed for the rest of the afternoon.
It is a CLAMP, never an extension: a cached record expires at
min(record.expires_at, now + discovery_cache_ttl), so a peer cannot lengthen its own
residence in this node’s cache by claiming a distant expiry.
discovery_cache_limits: ProviderStoreLimitsDiscovery-cache caps — the per-content-key and global record limits enforced on the
cache (SPEC §6.8), by the same ProviderStore
admission control the authoritative store uses.
Tighter than Self::provider_store_limits on both axes, because the cache answers a
narrower question. Per key it holds 8 — a caller dials a handful of candidates and gives
up, so a ninth is memory spent on a dial nobody will make, and it matches the
MAX_ADDRESSES_PER_RECORD disclosure budget the node’s redirect path already settled on.
Globally it holds 10 000 keys’ worth: the cache is keyed by what THIS node went looking
for, which is bounded by its own fetch behaviour rather than by strangers’ announces, so the
authoritative store’s 100 000-record ceiling would buy nothing but a larger footprint for a
pathological workload to fill.
Implementations§
Source§impl DhtConfig
impl DhtConfig
Sourcepub fn provider_ttl_secs(&self) -> u64
pub fn provider_ttl_secs(&self) -> u64
The provider TTL in whole seconds (records store an absolute Unix-seconds expiry).
Sourcepub fn discovery_cache_ttl_secs(&self) -> u64
pub fn discovery_cache_ttl_secs(&self) -> u64
The discovery-cache TTL in whole seconds (the cache stores absolute Unix-seconds expiries).
Trait Implementations§
Auto Trait Implementations§
impl Freeze for DhtConfig
impl RefUnwindSafe for DhtConfig
impl Send for DhtConfig
impl Sync for DhtConfig
impl Unpin for DhtConfig
impl UnsafeUnpin for DhtConfig
impl UnwindSafe for DhtConfig
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.