Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
05318b9
minor: fix warnings in transport/manager
dmitry-markin Aug 12, 2025
f4259c8
Add `QueryId` field to `QueryAction::PutRecordToFoundNodes`
dmitry-markin Aug 12, 2025
0874d72
Introduce `QueryType::PutRecordToFoundNodes`
dmitry-markin Aug 12, 2025
269a807
Track `PUT_VALUE` responses and emit `PutRecordSucceeded`
dmitry-markin Aug 12, 2025
7b2b2b4
Merge branch 'master' into dm-put-record-success
dmitry-markin Aug 15, 2025
de6e235
Send ACK responses to `PUT_VALUE` requests
dmitry-markin Aug 15, 2025
22fad0b
Extend tests
dmitry-markin Aug 15, 2025
5dc45cc
Clamp `Quorum::N` by number of discovered peers during `PUT_VALUE`
dmitry-markin Aug 15, 2025
2459646
minor: typo
dmitry-markin Aug 18, 2025
765883c
minor: revert feature flag fix now in master
dmitry-markin Aug 18, 2025
6644f83
minor: make clippy happy
dmitry-markin Aug 18, 2025
09317fc
Apply review suggestions
dmitry-markin Aug 19, 2025
531926f
Apply more review suggestions
dmitry-markin Aug 19, 2025
2bb7e88
Merge remote-tracking branch 'origin/master' into dm-put-record-success
dmitry-markin Aug 19, 2025
988270b
Omit sending optional fields in `PUT_VALUE` ACK response
dmitry-markin Aug 19, 2025
129a3f3
Rename `PutRecordToFoundNodesContext`->`ContactFoundNodesContext`
dmitry-markin Aug 21, 2025
74c2cd9
Track success/failure of sending a message to peers
dmitry-markin Aug 22, 2025
16a9683
minor: naming
dmitry-markin Aug 22, 2025
9a2f09c
Polish query success/failure reporting
dmitry-markin Aug 22, 2025
ecb137f
Update tests
dmitry-markin Aug 27, 2025
ddadb2e
Correctly track send successes as part of send/read requests
dmitry-markin Aug 27, 2025
9701164
Eat `PUT_VALUE` ACKs
dmitry-markin Aug 27, 2025
3cb8b95
Simplify `QueryResult`
dmitry-markin Aug 27, 2025
89d0ee2
Handle peers not receiving ACKs
dmitry-markin Aug 28, 2025
a001b3e
Reference issue #429 in TODOs
dmitry-markin Aug 28, 2025
858c54d
Pass `Quorum` for local providers
dmitry-markin Aug 18, 2025
4f1d471
Update tests to include quorum for local providers
dmitry-markin Aug 18, 2025
e1127c4
Track `ADD_PROVIDER` query success
dmitry-markin Sep 1, 2025
cdb007a
Add `QueryEngine` tests for `ADD_PROVIDER` progress tracking
dmitry-markin Sep 1, 2025
8a573c9
Update Kademlia e2e tests
dmitry-markin Sep 2, 2025
e6aad45
Make `RemotePublicKey` public to enable signature verification
dmitry-markin Sep 8, 2025
47746a6
Silently ignore send success for request-response requests
dmitry-markin Sep 9, 2025
d64e3b9
Merge branch 'dm-put-record-substream-tracking' into dm-add-provider-…
dmitry-markin Sep 9, 2025
0307643
Handle remote responding with incorrect message
dmitry-markin Sep 17, 2025
b2586d4
Merge remote-tracking branch 'origin/master' into dm-put-record-success
dmitry-markin Oct 24, 2025
7391ba3
Merge branch 'dm-put-record-success' into dm-put-record-substream-tra…
dmitry-markin Oct 24, 2025
b42583f
Merge branch 'dm-put-record-substream-tracking' into dm-add-provider-…
dmitry-markin Oct 24, 2025
1a0969a
Merge remote-tracking branch 'origin/master' into dm-put-record-success
dmitry-markin Nov 11, 2025
772797d
Merge branch 'dm-put-record-success' into dm-put-record-substream-tra…
dmitry-markin Nov 11, 2025
812eaed
Merge branch 'dm-put-record-substream-tracking' into dm-add-provider-…
dmitry-markin Nov 11, 2025
ae072a8
monor: return copyright notice
dmitry-markin Nov 11, 2025
fc1186e
Merge remote-tracking branch 'origin/master' into dm-add-provider-suc…
dmitry-markin Nov 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ str0m = { version = "0.9.0", optional = true }

# Fuzzing related dependencies.
serde_millis = {version = "0.1", optional = true}
enum-display = "0.1.4"
# End of fuzzing related dependencies.

[dev-dependencies]
Expand Down
25 changes: 22 additions & 3 deletions src/protocol/libp2p/kademlia/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use std::{
///
/// Quorum defines how many peers must be successfully contacted
/// in order for the query to be considered successful.
#[derive(Debug, Copy, Clone)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "fuzz", derive(serde::Serialize, serde::Deserialize))]
pub enum Quorum {
/// All peers must be successfully contacted.
Expand Down Expand Up @@ -156,6 +156,9 @@ pub enum KademliaCommand {
/// Provided key.
key: RecordKey,

/// [`Quorum`] for the query.
quorum: Quorum,

/// Query ID for the query.
query_id: QueryId,
},
Expand Down Expand Up @@ -240,6 +243,15 @@ pub enum KademliaEvent {
key: RecordKey,
},

/// `ADD_PROVIDER` query succeeded.
AddProviderSuccess {
/// Query ID.
query_id: QueryId,

/// Provided key.
provided_key: RecordKey,
},

/// Query failed.
QueryFailed {
/// Query ID.
Expand Down Expand Up @@ -373,9 +385,16 @@ impl KademliaHandle {
///
/// Register the local peer ID & its `public_addresses` as a provider for a given `key`.
/// Returns [`Err`] only if `Kademlia` is terminating.
pub async fn start_providing(&mut self, key: RecordKey) -> QueryId {
pub async fn start_providing(&mut self, key: RecordKey, quorum: Quorum) -> QueryId {
let query_id = self.next_query_id();
let _ = self.cmd_tx.send(KademliaCommand::StartProviding { key, query_id }).await;
let _ = self
.cmd_tx
.send(KademliaCommand::StartProviding {
key,
quorum,
query_id,
})
.await;

query_id
}
Expand Down
3 changes: 2 additions & 1 deletion src/protocol/libp2p/kademlia/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ use crate::{
};

use bytes::{Bytes, BytesMut};
use enum_display::EnumDisplay;
use prost::Message;
use std::time::{Duration, Instant};

/// Logging target for the file.
const LOG_TARGET: &str = "litep2p::ipfs::kademlia::message";

/// Kademlia message.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, EnumDisplay)]
pub enum KademliaMessage {
/// `FIND_NODE` message.
FindNode {
Expand Down
39 changes: 33 additions & 6 deletions src/protocol/libp2p/kademlia/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,7 @@ impl Kademlia {
provided_key,
provider,
peers,
quorum,
} => {
tracing::trace!(
target: LOG_TARGET,
Expand All @@ -932,7 +933,7 @@ impl Kademlia {

let message = KademliaMessage::add_provider(provided_key.clone(), provider);

for peer in peers {
for peer in &peers {
if let Err(error) = self.open_substream_or_dial(
peer.peer,
PeerAction::SendAddProvider(query, message.clone()),
Expand All @@ -948,6 +949,28 @@ impl Kademlia {
}
}

self.engine.start_add_provider_to_found_nodes_requests_tracking(
query,
provided_key,
peers.into_iter().map(|peer| peer.peer).collect(),
quorum,
);

Ok(())
}
QueryAction::AddProviderQuerySucceeded {
query,
provided_key,
} => {
tracing::debug!(target: LOG_TARGET, ?query, "`ADD_PROVIDER` query succeeded");

let _ = self
.event_tx
.send(KademliaEvent::AddProviderSuccess {
query_id: query,
provided_key,
})
.await;
Ok(())
}
QueryAction::GetRecordQueryDone { query_id } => {
Expand Down Expand Up @@ -1215,6 +1238,7 @@ impl Kademlia {
}
Some(KademliaCommand::StartProviding {
key,
quorum,
query_id
}) => {
tracing::debug!(
Expand All @@ -1230,7 +1254,7 @@ impl Kademlia {
addresses,
};

self.store.put_provider(key.clone(), provider.clone());
self.store.put_local_provider(key.clone(), quorum);

self.engine.start_add_provider(
query_id,
Expand All @@ -1239,6 +1263,7 @@ impl Kademlia {
self.routing_table
.closest(&Key::new(key), self.replication_factor)
.into(),
quorum,
);
}
Some(KademliaCommand::StopProviding {
Expand Down Expand Up @@ -1349,16 +1374,17 @@ impl Kademlia {
}
},
action = self.store.next_action() => match action {
Some(MemoryStoreAction::RefreshProvider { provided_key, provider }) => {
Some(MemoryStoreAction::RefreshProvider { provided_key, provider, quorum }) => {
tracing::trace!(
target: LOG_TARGET,
?provided_key,
"republishing local provider",
);

self.store.put_provider(provided_key.clone(), provider.clone());
// We never update local provider addresses in the store when refresh
// it, as this is done anyway when replying to `GET_PROVIDERS` request.
self.store.put_local_provider(provided_key.clone(), quorum);

// We never update local provider addresses in the store during refresh,
// as this is done anyway when replying to `GET_PROVIDERS` request.

let query_id = self.next_query_id();
self.engine.start_add_provider(
Expand All @@ -1368,6 +1394,7 @@ impl Kademlia {
self.routing_table
.closest(&Key::new(provided_key), self.replication_factor)
.into(),
quorum,
);
}
None => {}
Expand Down
Loading
Loading