pub struct RoutingTable { /* private fields */ }Expand description
In-memory k-bucket routing table (ADR 022 §Routing Table).
Not internally synchronised — the runtime owns it behind whatever mutex /
RwLock the handler chooses. A bare &mut self interface keeps the
happy-path hot loop (one Vec::iter + LRU bump) cache-friendly and lets
callers compose with their own concurrency strategy.
Implementations§
Source§impl RoutingTable
impl RoutingTable
Sourcepub fn insert(&mut self, peer: NodeId) -> bool
pub fn insert(&mut self, peer: NodeId) -> bool
Insert or refresh peer. Returns true on a fresh insert, false
on a refresh (peer already present — its LRU position is moved to
the tail) or a self-insert (silently ignored).
On bucket overflow the least-recently-seen entry is evicted to make room. See the module docs for the LRU rationale vs. classic ping-then-evict.
Sourcepub fn remove(&mut self, peer: &NodeId) -> bool
pub fn remove(&mut self, peer: &NodeId) -> bool
Remove peer if present. Returns true if a removal occurred.
Sourcepub fn closest(&self, target: &[u8; 32], n: usize) -> Vec<NodeId>
pub fn closest(&self, target: &[u8; 32], n: usize) -> Vec<NodeId>
Return up to n peers from the table sorted by XOR distance to
target (closest first). Capped at K_BUCKET_SIZE since the wire
closer_nodes field is itself capped at MAX_CLOSER_NODES.
Walks every bucket; with 256 × 20 entries the worst case is 5120 XOR computes (once each, cached) + a sort over those cached distances — well under a microsecond on modern hardware and dwarfed by the QUIC round-trip cost.
The result is capped at K_BUCKET_SIZE (= MAX_CLOSER_NODES)
so it can be serialised directly into a wire closer_nodes field.
Callers needing more than K candidates (e.g. ADR 022 §STORE Flow
“K+3 closest” republish fanout) MUST use Self::closest_unbounded.
Sourcepub fn closest_unbounded(&self, target: &[u8; 32], n: usize) -> Vec<NodeId>
pub fn closest_unbounded(&self, target: &[u8; 32], n: usize) -> Vec<NodeId>
Like Self::closest but without the wire-cap clamp at
K_BUCKET_SIZE. Used by the republish path which fans out to
K+3 closest peers per ADR 022 §STORE Flow line 128 (“three
positions beyond K are overflow targets — publishing to a wider
set than the minimum required by the routing geometry means an
attacker forcing record expiry by suppressing receivers must
take down K+3 hosts rather than K”).
MUST NOT be used to populate wire responses — those are bound at
MAX_CLOSER_NODES and a larger result would violate the
ADR 022 wire-cost ceiling. Use Self::closest for that path.
Sourcepub fn iter_peers(&self) -> impl Iterator<Item = &NodeId> + '_
pub fn iter_peers(&self) -> impl Iterator<Item = &NodeId> + '_
Iterator over every peer currently held. Order is bucket-major,
recency within bucket — useful for republish scans and bootstrap
snapshots, but not distance-sorted (callers wanting closeness
must use Self::closest).
Sourcepub fn non_empty_bucket_fills(&self) -> Vec<(usize, usize)>
pub fn non_empty_bucket_fills(&self) -> Vec<(usize, usize)>
Per-bucket fill counts for the non-empty buckets only, as
(index, fill) pairs ordered by bucket index ascending. Read-only
snapshot for the admin_v1_status routing-table health view (issue
#741); empty buckets (the vast majority of the 256-bucket keyspace
on a small network) are omitted so the snapshot stays compact. The
per-bucket capacity is the fixed Kademlia K_BUCKET_SIZE.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for RoutingTable
impl RefUnwindSafe for RoutingTable
impl Send for RoutingTable
impl Sync for RoutingTable
impl Unpin for RoutingTable
impl UnsafeUnpin for RoutingTable
impl UnwindSafe for RoutingTable
Blanket Implementations§
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
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
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> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request