Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit b105395

Browse files
committed
Kademlia: Speed-up the record fetching
Before libp2p 0.50.0 we used a quorum of one to fetch records from the DHT. In the pr that upgraded to libp2p 0.50.0 we accidentally changed this behavior. This pr brings back the old behavior of using a qorum of one and thus, a faster discovery. After finding the first value, we directly finish the query. There was also another behavior change in libp2p, they stopped automatic caching on remote nodes. This pr also brings back the remote caching on nodes that are nearest to the key from our point of view of the network. The pr that changed the behavior in libp2p: libp2p/rust-libp2p#2712
1 parent 6376f13 commit b105395

File tree

1 file changed

+50
-25
lines changed

1 file changed

+50
-25
lines changed

client/network/src/discovery.rs

+50-25
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ impl DiscoveryConfig {
249249
NonZeroUsize::new(MAX_KNOWN_EXTERNAL_ADDRESSES)
250250
.expect("value is a constant; constant is non-zero; qed."),
251251
),
252-
outbound_query_records: Vec::new(),
252+
records_to_publish: Default::default(),
253253
}
254254
}
255255
}
@@ -287,8 +287,12 @@ pub struct DiscoveryBehaviour {
287287
allow_non_globals_in_dht: bool,
288288
/// A cache of discovered external addresses. Only used for logging purposes.
289289
known_external_addresses: LruHashSet<Multiaddr>,
290-
/// A cache of outbound query records.
291-
outbound_query_records: Vec<(record::Key, Vec<u8>)>,
290+
/// Records to publish per QueryId.
291+
///
292+
/// After finishing a Kademlia query, libp2p will return us a list of the closest peers that
293+
/// did not return the record(in `FinishedWithNoAdditionalRecord`). We will then put the record
294+
/// to these peers.
295+
records_to_publish: HashMap<QueryId, Record>,
292296
}
293297

294298
impl DiscoveryBehaviour {
@@ -692,33 +696,54 @@ impl NetworkBehaviour for DiscoveryBehaviour {
692696
KademliaEvent::OutboundQueryProgressed {
693697
result: QueryResult::GetRecord(res),
694698
stats,
695-
step,
699+
id,
696700
..
697701
} => {
698702
let ev = match res {
699-
Ok(ok) =>
700-
if let GetRecordOk::FoundRecord(r) = ok {
701-
self.outbound_query_records
702-
.push((r.record.key, r.record.value));
703+
Ok(GetRecordOk::FoundRecord(r)) => {
704+
debug!(
705+
target: "sub-libp2p",
706+
"Libp2p => Found record ({:?}) with value: {:?}",
707+
r.record.key,
708+
r.record.value,
709+
);
710+
711+
// Let's directly finish the query, as we are only interested in a
712+
// quorum of 1.
713+
if let Some(kad) = self.kademlia.as_mut() {
714+
if let Some(mut query) = kad.query_mut(&id) {
715+
query.finish();
716+
}
717+
}
718+
719+
self.records_to_publish.insert(id, r.record.clone());
720+
721+
DiscoveryOut::ValueFound(
722+
vec![(r.record.key, r.record.value)],
723+
stats.duration().unwrap_or_default(),
724+
)
725+
},
726+
Ok(GetRecordOk::FinishedWithNoAdditionalRecord {
727+
cache_candidates,
728+
}) => {
729+
if cache_candidates.is_empty() {
703730
continue
704-
} else {
705-
debug!(
706-
target: "sub-libp2p",
707-
"Libp2p => Query progressed to {:?} step (last: {:?})",
708-
step.count,
709-
step.last,
710-
);
711-
if step.last {
712-
let records =
713-
self.outbound_query_records.drain(..).collect();
714-
DiscoveryOut::ValueFound(
715-
records,
716-
stats.duration().unwrap_or_default(),
717-
)
718-
} else {
719-
continue
731+
}
732+
733+
// Put the record to the `cache_candidates` that are nearest to the
734+
// record key from our point of view of the network.
735+
if let Some(record) = self.records_to_publish.remove(&id) {
736+
if let Some(kad) = self.kademlia.as_mut() {
737+
kad.put_record_to(
738+
record,
739+
cache_candidates.into_iter().map(|v| v.1),
740+
Quorum::One,
741+
);
720742
}
721-
},
743+
}
744+
745+
continue
746+
},
722747
Err(e @ libp2p::kad::GetRecordError::NotFound { .. }) => {
723748
trace!(
724749
target: "sub-libp2p",

0 commit comments

Comments
 (0)